samagotchi 0.141.0 → 0.143.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 +111 -7
- data/README.md +2 -1
- data/bin/chi +2 -0
- data/docs/architecture.md +25 -289
- data/docs/bundle-authoring.md +7 -6
- data/docs/bundles.md +1232 -0
- data/docs/cli.md +51 -13
- data/docs/configuration.md +68 -30
- data/docs/context.md +12 -12
- data/docs/guardrails.md +27 -20
- data/docs/hooks.md +28 -9
- data/docs/internals/attached-context.md +225 -0
- data/docs/internals/background-tasks.md +1 -1
- data/docs/internals/bridge.md +380 -0
- data/docs/internals/bundles.md +6 -3
- data/docs/internals/context-telemetry.md +1 -1
- data/docs/internals/engine.md +31 -19
- data/docs/internals/participants.md +13 -12
- data/docs/internals/prompt-caching.md +12 -12
- data/docs/internals/remote-sessions.md +1 -1
- data/docs/internals/{tool-guardrails.md → tool-output-limits.md} +21 -2
- data/docs/internals/web-push.md +1 -1
- data/docs/memory.md +33 -3
- data/docs/plugins.md +127 -1231
- data/docs/sessions.md +51 -27
- data/docs/sub-agent.md +6 -6
- data/docs/system-one.md +122 -0
- data/docs/testing.md +3 -1
- data/lib/samagotchi/bridge.rb +2 -0
- data/lib/samagotchi/bundle_command/api_calls.rb +132 -0
- data/lib/samagotchi/bundle_command/check.rb +50 -34
- data/lib/samagotchi/bundle_command/installed_check.rb +86 -0
- data/lib/samagotchi/bundle_command/scaffold.rb +1 -0
- data/lib/samagotchi/bundle_settings_check.rb +58 -0
- data/lib/samagotchi/bundles/agents-md/manifest.yml +4 -2
- data/lib/samagotchi/bundles/agents-md/plugin.rb +1 -1
- data/lib/samagotchi/bundles/btw/manifest.yml +4 -2
- data/lib/samagotchi/bundles/btw/plugin.rb +1 -1
- data/lib/samagotchi/bundles/check-in/manifest.yml +7 -3
- data/lib/samagotchi/bundles/check-in/plugin.rb +101 -11
- data/lib/samagotchi/bundles/claude-peer/manifest.yml +3 -3
- data/lib/samagotchi/bundles/claude-peer/plugin.rb +1 -1
- data/lib/samagotchi/bundles/claude-peer/scripts/pair +1 -1
- data/lib/samagotchi/bundles/codex-peer/manifest.yml +2 -2
- data/lib/samagotchi/bundles/codex-peer/plugin.rb +1 -1
- data/lib/samagotchi/bundles/coordinator/manifest.yml +2 -2
- data/lib/samagotchi/bundles/coordinator/plugin.rb +1 -1
- data/lib/samagotchi/bundles/core/manifest.yml +2 -2
- data/lib/samagotchi/bundles/cost-cap/manifest.yml +6 -3
- data/lib/samagotchi/bundles/cost-cap/plugin.rb +5 -7
- data/lib/samagotchi/bundles/github-pr/manifest.yml +3 -1
- data/lib/samagotchi/bundles/known-names/manifest.yml +3 -1
- data/lib/samagotchi/bundles/loop-guard/manifest.yml +4 -2
- data/lib/samagotchi/bundles/loop-guard/plugin.rb +1 -1
- data/lib/samagotchi/bundles/mcp/manifest.yml +4 -2
- data/lib/samagotchi/bundles/mcp/plugin.rb +2 -2
- data/lib/samagotchi/bundles/ruby/manifest.yml +2 -2
- data/lib/samagotchi/bundles/ruby/plugin.rb +1 -1
- data/lib/samagotchi/bundles/skills/manifest.yml +4 -2
- data/lib/samagotchi/bundles/skills/plugin.rb +1 -1
- data/lib/samagotchi/bundles/slow-commands/manifest.yml +4 -2
- data/lib/samagotchi/bundles/slow-commands/plugin.rb +1 -1
- data/lib/samagotchi/bundles/source-links/manifest.yml +3 -1
- data/lib/samagotchi/bundles/system/config_modification_protocol.md +3 -3
- data/lib/samagotchi/bundles/system/manifest.yml +4 -4
- data/lib/samagotchi/bundles/system/memory_guide.md +1 -1
- data/lib/samagotchi/bundles/system/self_map.md +3 -3
- data/lib/samagotchi/bundles/work-cap/manifest.yml +6 -3
- data/lib/samagotchi/bundles/work-cap/plugin.rb +11 -13
- data/lib/samagotchi/config.rb +74 -14
- data/lib/samagotchi/context_candidate_choice.rb +20 -3
- data/lib/samagotchi/context_candidates.rb +4 -1
- data/lib/samagotchi/context_candidates_log.rb +36 -1
- data/lib/samagotchi/context_judge.rb +6 -2
- data/lib/samagotchi/context_status.rb +1 -2
- data/lib/samagotchi/engine.rb +96 -70
- data/lib/samagotchi/extension_load.rb +11 -4
- data/lib/samagotchi/guardrail_wiring.rb +36 -31
- data/lib/samagotchi/guardrails/chi_dirs.rb +7 -4
- data/lib/samagotchi/guardrails/path_resolve.rb +1 -1
- data/lib/samagotchi/guardrails/protected_paths.rb +7 -4
- data/lib/samagotchi/guardrails_command.rb +3 -3
- data/lib/samagotchi/hook_routes.rb +37 -2
- data/lib/samagotchi/hooks/bundle_loader.rb +20 -4
- data/lib/samagotchi/hooks/registry.rb +23 -5
- data/lib/samagotchi/host_model.rb +3 -3
- data/lib/samagotchi/host_registry.rb +14 -7
- data/lib/samagotchi/judgments_command.rb +155 -0
- data/lib/samagotchi/kernel_loop.rb +20 -3
- data/lib/samagotchi/llm/chat_loop.rb +79 -10
- data/lib/samagotchi/llm/errors.rb +7 -5
- data/lib/samagotchi/llm/stray_tool_call.rb +68 -0
- data/lib/samagotchi/log_line.rb +1 -1
- data/lib/samagotchi/memory_bundle/builder.rb +4 -2
- data/lib/samagotchi/memory_bundle/entry_size.rb +100 -0
- data/lib/samagotchi/memory_bundle/installed_bundle.rb +9 -2
- data/lib/samagotchi/memory_bundle/installed_copy.rb +92 -0
- data/lib/samagotchi/memory_bundle/installer.rb +2 -0
- data/lib/samagotchi/memory_bundle/manifest.rb +23 -13
- data/lib/samagotchi/memory_bundle/provenance.rb +4 -1
- data/lib/samagotchi/memory_bundle/shipped_update.rb +13 -1
- data/lib/samagotchi/model_catalog.rb +3 -2
- data/lib/samagotchi/models_command.rb +1 -1
- data/lib/samagotchi/plugin/api.rb +41 -7
- data/lib/samagotchi/plugin/context.rb +59 -1
- data/lib/samagotchi/plugin/judgments.rb +72 -0
- data/lib/samagotchi/plugin/loader.rb +6 -3
- data/lib/samagotchi/plugin/peer.rb +17 -22
- data/lib/samagotchi/plugin_session_state.rb +32 -5
- data/lib/samagotchi/prompt_warmup.rb +1 -9
- data/lib/samagotchi/run_options.rb +1 -0
- data/lib/samagotchi/self_report.rb +36 -0
- data/lib/samagotchi/session_access/contract.rb +1 -1
- data/lib/samagotchi/session_access/local.rb +1 -1
- data/lib/samagotchi/session_access/remote.rb +3 -3
- data/lib/samagotchi/session_archive_command.rb +3 -3
- data/lib/samagotchi/session_commands.rb +7 -4
- data/lib/samagotchi/session_config.rb +9 -3
- data/lib/samagotchi/session_continue.rb +1 -1
- data/lib/samagotchi/session_manager.rb +25 -5
- data/lib/samagotchi/session_retention.rb +10 -0
- data/lib/samagotchi/side_judgments.rb +12 -1
- data/lib/samagotchi/system_one/answer.rb +63 -11
- data/lib/samagotchi/system_one/approval_label.rb +56 -0
- data/lib/samagotchi/system_one/approval_question.rb +2 -0
- data/lib/samagotchi/system_one/client.rb +43 -17
- data/lib/samagotchi/system_one/fake_backend.rb +1 -1
- data/lib/samagotchi/system_one/http_backend.rb +12 -4
- data/lib/samagotchi/system_one/judgment_settings.rb +61 -0
- data/lib/samagotchi/system_one/judgments.rb +243 -0
- data/lib/samagotchi/system_one/log.rb +25 -2
- data/lib/samagotchi/system_one/recording.rb +117 -0
- data/lib/samagotchi/system_one/runs.rb +179 -0
- data/lib/samagotchi/system_one/runs_store.rb +230 -0
- data/lib/samagotchi/system_one.rb +9 -0
- data/lib/samagotchi/terminal_ui/attach_link.rb +2 -2
- data/lib/samagotchi/terminal_ui/attached_loop/exit_commands.rb +1 -1
- data/lib/samagotchi/terminal_ui/attached_loop.rb +1 -1
- data/lib/samagotchi/terminal_ui/local_link.rb +1 -1
- data/lib/samagotchi/terminal_ui/remote_link.rb +1 -2
- data/lib/samagotchi/testing/bundle.rb +9 -2
- data/lib/samagotchi/testing/host.rb +2 -1
- data/lib/samagotchi/testing/judgments.rb +176 -0
- data/lib/samagotchi/testing/recorder.rb +5 -0
- data/lib/samagotchi/testing/recording_api.rb +1 -1
- data/lib/samagotchi/tool_output_cut.rb +26 -6
- data/lib/samagotchi/tool_response.rb +1 -1
- data/lib/samagotchi/tool_runner.rb +63 -4
- data/lib/samagotchi/toolkit_suggest.rb +11 -2
- data/lib/samagotchi/tools/memory.rb +28 -0
- data/lib/samagotchi/turn_note.rb +9 -0
- data/lib/samagotchi/update_command.rb +49 -16
- data/lib/samagotchi/version.rb +1 -1
- data/lib/samagotchi/web/app.rb +1 -0
- data/lib/samagotchi/web/auto_update.rb +79 -49
- data/lib/samagotchi/web/auto_update_record.rb +59 -0
- data/lib/samagotchi/web/public/app.js +8 -4
- data/lib/samagotchi/web/public/hash_intent.js +24 -0
- data/lib/samagotchi/web/public/index.html +3 -1
- data/lib/samagotchi/web/public/revise_stack.js +14 -5
- data/lib/samagotchi/web/session_control.rb +3 -3
- data/lib/samagotchi/web/update_check.rb +7 -6
- data/lib/samagotchi/web/update_ops.rb +80 -25
- metadata +23 -2
data/docs/cli.md
CHANGED
|
@@ -16,12 +16,12 @@
|
|
|
16
16
|
- `chi web --start-dir DIR` (config `web.start_dir`) — the folder chi web starts in, in place of the one you run it in (`~` and a relative path work; chi web never changes its own folder): its page opens on that folder's project (the printed link, a bare `/`, the LAN link and its QR code, the Home Screen app), and a new session from the all view starts there; the header's project chip switches projects. One that isn't a folder exits 1; `--start-dir` without `web` exits 2. A chi web already running in another folder keeps it (the second one says so: restart it to change it)
|
|
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
|
-
- `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
|
|
19
|
+
- `chi web --web-markdown` / `--no-web-markdown` — opt in to, or opt out of, sanitized Markdown rendering for completed assistant messages, the stage's asking text and a resolved question card's reply (`web.markdown`, off by default; `--no-web-markdown` turns a config's `web.markdown: true` off for this run)
|
|
20
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))
|
|
21
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
|
|
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
|
-
- `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))
|
|
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; `chi context push NAME -m TEXT` (the long form is `--message TEXT`) gives a `--push` source its new text, read from stdin when no `-m` is given (see [Attached context](context.md))
|
|
25
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))
|
|
26
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))
|
|
27
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))
|
|
@@ -33,12 +33,13 @@
|
|
|
33
33
|
- `chi memory ls [--scope project|system] [--format text|json]` — the memories of both scopes (this folder's project first), one row each: scope, name, size, date, `from <bundle>`, the index description and its model overlays; `chi memory rm NAME [--scope project|system]` removes one as `memory_write` with `remove: true` does: its file and model overlays go to the bundle trash (the line names the dir; `chi bundle trash` lists and empties it) and its index line is dropped. NAME in both scopes without `--scope` exits 2 naming both; a missing NAME or a bundle's memory (`chi bundle uninstall` removes it) exits 1 (see [Memory: Listing and removing from the shell](memory.md#listing-and-removing-from-the-shell))
|
|
34
34
|
- `chi desktop install|upgrade|uninstall|status` — the macOS "Send to chi" helper: a Service and a ⌃⌥⌘N hotkey that send text or images to a session (live, stopped or new) as a message (⏎, a turn runs) or a context note (⌘⏎) (see [Desktop helper](desktop.md))
|
|
35
35
|
- `chi models [--format text|json] [--timeout S] [TEXT]` — list the models every configured host offers, as the names `--model` takes (see [Listing the models](#listing-the-models))
|
|
36
|
-
- `chi self` — print version, source dir (checkout or installed gem), config/memory/session paths, model/host and bundles. Run by a session's `execute`, the `model` row (and host, loop, profile, thinking, served model) is **that session's** model, labelled `(this session <id8>; default …)`; elsewhere it is the default, `(default)`. `model key` is the memory overlay key (`<name>.<key>.md`), and `model notes` the model notes a prompt of that model loads (`model_notes_deepseek (system, 612 chars)`, `none`; inside a session its `--mute` list is left out). `chi self --model` prints only the model a new session starts on, an alias resolved to its target (the desktop helper's hint)
|
|
37
|
-
- `chi update [--dry-run] [--to VERSION] [--json] [--no-gem] [--no-bundles] [--no-desktop]` — update an installed chi: the gem, the system bundle, the shipped bundles you installed and the desktop helper, in one table (see [Updating](#updating))
|
|
36
|
+
- `chi self` — print version, source dir (checkout or installed gem), config/memory/session paths, model/host and bundles. Run by a session's `execute`, the `model` row (and host, loop, profile, thinking, served model) is **that session's** model, labelled `(this session <id8>; default …)`; elsewhere it is the default, `(default)`. `model key` is the memory overlay key (`<name>.<key>.md`), and `big memories` the memories over `memory.entry_warn_tokens` ([Memory](memory.md#a-memorys-size)), and `model notes` the model notes a prompt of that model loads (`model_notes_deepseek (system, 612 chars)`, `none`; inside a session its `--mute` list is left out). `chi self --model` prints only the model a new session starts on, an alias resolved to its target (the desktop helper's hint)
|
|
37
|
+
- `chi update [--dry-run] [--to VERSION] [--json] [--no-gem] [--no-bundles] [--no-desktop]` — update an installed chi: the gem, the system bundle, the shipped bundles you installed and the desktop helper, and check the bundles from elsewhere, in one table (see [Updating](#updating))
|
|
38
38
|
- `chi home`, `chi home set [--ruby PATH]`, `chi home doctor` — the chi home: the one Ruby (and its gem path) every chi launch boots, whoever launches it. `chi home` shows it (its Ruby, the newest chi in it, gem home and path, `mise`, when and by which chi it was set, and the chi you ran when that is another one; exit 1 with the problem when it can't boot chi), `set` records this chi's Ruby and gem path (or `--ruby PATH`'s own; it must have samagotchi), `doctor` checks it and what should follow it, one row each with `ok`, `warn` or `fail` and what to run (exit 1 on a `fail`; see [Checking it](configuration.md#checking-it-chi-home-doctor)). At a terminal, a chi on another Ruby than the home's says so in one dim line a day. This machine only (see [The chi home](configuration.md#the-chi-home))
|
|
39
|
-
- `chi bundle install|upgrade|uninstall|status|diff|list|build|trash|new|test|check` — manage memory bundles (see [Bundle hooks](hooks.md#bundle-hooks-unified-workflow-bundle)); `list` shows the installed ones and the ones shipped with chi, which `install <name>` installs; `core` and `dev` are profiles that install a set of them (see [Bundle profiles](memory.md#bundle-profiles-core-and-dev), [Guardrails](guardrails.md), [
|
|
39
|
+
- `chi bundle install|upgrade|uninstall|status|diff|list|build|trash|new|test|check` — manage memory bundles (see [Bundle hooks](hooks.md#bundle-hooks-unified-workflow-bundle)); `list` shows the installed ones and the ones shipped with chi, which `install <name>` installs; `core` and `dev` are profiles that install a set of them (see [Bundle profiles](memory.md#bundle-profiles-core-and-dev), [Guardrails](guardrails.md), [Bundles](bundles.md#the-btw-bundle), [the mcp bundle](bundles.md#the-mcp-bundle) [the loop-guard bundle](bundles.md#the-loop-guard-bundle), [the check-in bundle](bundles.md#the-check-in-bundle) and [the skills bundle](bundles.md#the-skills-bundle)). `trash` lists and empties the bundle trash (moved files from uninstalls/upgrades). A usage error (an unknown subcommand or flag, a missing argument, a bad `build --scope`) exits 2, as for the other subcommands. Plain `chi` and `chi web` exit 1 on an unknown flag, a flag missing its value or a stray argument. `new`, `test` and `check` are for writing one: see [Writing a bundle](#writing-a-bundle-new-test-check)
|
|
40
40
|
|
|
41
41
|
- `chi guardrails replay [--dry-run] [--threshold T] [--model M]` — seed System 1's record from the approvals this machine's sessions already answered: each ask is judged by the configured model and written to `guardrails/judgments.jsonl` with the answer the user gave, then a per-rule table prints (asks, allowed, denied, would-be auto-allows, false allows, asks with no judgment). A parent agent's answer is not the user's: only its deny is replayed, and only where the parent could have allowed. `--dry-run` judges without writing, `--threshold` overrides `guardrails.system_one.threshold` for the table, `--model` the configured model for this run. Exit 2 when `guardrails.system_one.mode` is off or no `host` is set; a usage error exits 2 (see [System 1](guardrails.md#system-1-experimental))
|
|
42
|
+
- `chi judgments ls` / `chi judgments report NAME [--days N]` — what [System 1's saved runs](system-one.md) hold: each judgment's digests, runs, labels, failures, models and size; one judgment's counts, p histogram and labels by value. Reads only; local only; `--days` must be a positive whole number.
|
|
42
43
|
- `chi toolkit report [--days N]` — grade toolkit suggestions: the kit on mode would have run (the suggested kit when it would have applied it, else the default; an on-mode line's `did` says what it ran) against the tools the session called from that turn on (only that turn when the toolkit was chosen since), `call_tool` targets included, for both the chat and the raw-prompt loop. Each is *covers*, *short of a tool* (naming the tools), *wider than needed* (a narrower kit offered in the same ask would also have covered) or *ungradable* (calls it can't read back); then a per-kit tally with what on mode would have done. Includes archived sessions and caps the report at 14 days and 500 sessions. Reads `toolkit_suggestions.jsonl` (each ask logs every offered kit's rules, expanded against the called tools here); it never runs the model or changes a session. Local only; `--days` must be a positive whole number.
|
|
43
44
|
|
|
44
45
|
- `chi bundle try PATH -p TEXT [options]` — install a bundle in a temporary, filtered sandbox, run one real model turn,
|
|
@@ -152,7 +153,9 @@ The loop for a bundle you're writing (the whole path: [bundle-authoring.md](bund
|
|
|
152
153
|
then forces), `install` (each Installer warning, a `needs` one as warn, and each plugin or hook load failure at
|
|
153
154
|
the source `file:line`; skipped while a placeholder sha is unfilled), `registered` (info: each command, tool,
|
|
154
155
|
hook with its priority, init, toolkit, tool source and peer source), `hook-event` (warn: a `chi.on` event chi
|
|
155
|
-
never fires), `
|
|
156
|
+
never fires), `settings` (warn: a `--set` the manifest's `settings:` rules out, as config.yml's `bundles:` is told), `api` (warn: a `ctx.*` / `chi.*` call or a keyword this chi's API lacks, read from the source with
|
|
157
|
+
Prism against the API's own classes, on a path that never runs too; written on a local `ctx` / `chi` itself, so a
|
|
158
|
+
`s = ctx.sessions` variable isn't followed; a name the plugin guards with `respond_to?` is left), `boundary` (warn: a `Samagotchi::` name outside "Stable for bundles"; a shipped bundle's listed
|
|
156
159
|
exceptions aside) and `tests` (info: how to run them, or "no tests"). `--set KEY=VALUE` (repeatable, typed as
|
|
157
160
|
`chi --set`) goes to `bundles: <name>:` in the sandbox's config.yml.
|
|
158
161
|
|
|
@@ -228,8 +231,10 @@ btw 0.1.1 up to date
|
|
|
228
231
|
known-names 0.1.0 0.1.1 updated
|
|
229
232
|
core 0.1.0 0.2.0 updated (+ new-bundle)
|
|
230
233
|
infra_tools 1.0.0 skipped (not from chi)
|
|
234
|
+
infra_tools warn api plugin.rb:3: ctx.old_name isn't in chi 0.3.0's plugin API (fix: docs/plugins.md has the API)
|
|
231
235
|
Chi Helper 0.2.0 up to date (launch file refreshed)
|
|
232
236
|
workers 2 live on 0.2.0: they keep it until restarted (chi sessions restart 2ea8c1f0 91b0d2aa); or they idle out after 30 min with nothing attached
|
|
237
|
+
Bundles not from chi are left as they are: their author's next version, or chi bundle upgrade NAME, is what changes them
|
|
233
238
|
Also shipped, not installed: dev (mcp, skills, source-links) (chi bundle install NAME)
|
|
234
239
|
done
|
|
235
240
|
```
|
|
@@ -238,8 +243,10 @@ done
|
|
|
238
243
|
newest release. It must be newer than the running chi; an equal or older
|
|
239
244
|
version is refused.
|
|
240
245
|
- `--json` writes the component rows as one JSON array on stdout. Each row has
|
|
241
|
-
`component`, `from`, `to`, `status`, `failed` and `
|
|
242
|
-
array of edited filenames
|
|
246
|
+
`component`, `from`, `to`, `status`, `failed`, `kept` and `level` fields;
|
|
247
|
+
`kept` is an array of edited filenames, and `level` is `warn` or `error` on a
|
|
248
|
+
re-check's row (below), `null` on the others. Install progress is written to
|
|
249
|
+
stderr.
|
|
243
250
|
|
|
244
251
|
- **chi web update notices.** By default, chi web checks RubyGems about 30
|
|
245
252
|
seconds after it starts and every 24 hours after that. Once a stable release
|
|
@@ -301,6 +308,30 @@ done
|
|
|
301
308
|
A bundle of the same name from elsewhere (a zip, git) is skipped ("not from
|
|
302
309
|
chi"), a newer installed one is left, one whose new version needs a newer
|
|
303
310
|
chi is skipped, and bundles you didn't install stay uninstalled.
|
|
311
|
+
- **Bundles not from chi** are never changed, but the chi the update leaves
|
|
312
|
+
checks what is installed of them (the plugin, hooks and rules as they are,
|
|
313
|
+
not their source, which may be gone) with `chi bundle check`'s own checks,
|
|
314
|
+
and each warning or error is a row under the bundle's name: `requires_chi`
|
|
315
|
+
ruling this chi out, a plugin or hook that no longer loads, a hook on an event
|
|
316
|
+
chi no longer fires, a `ctx`/`chi` call the API lacks, a reference to chi's
|
|
317
|
+
internals, a name chi now ships, or a hook or plugin edited since it was installed (it
|
|
318
|
+
doesn't load). What only an author can act on (shas, unlisted files, tests, a
|
|
319
|
+
missing `requires_chi`, its floor, `trust_level`) is left out, and so are
|
|
320
|
+
profiles. A clean bundle gets no row beyond its `skipped (not from chi)`.
|
|
321
|
+
- **They fail nothing:** an error row too has `failed: false` and leaves the exit
|
|
322
|
+
status 0, chi web's **Update** and `update.auto` done. A warning repeats on
|
|
323
|
+
every run until the bundle changes, and a second run still says `everything is up to date`.
|
|
324
|
+
- **Each runs in a child process**, with your config.yml `bundles: <name>:`
|
|
325
|
+
settings in a sandbox: its code runs, as in any session. One that exits or
|
|
326
|
+
doesn't answer in 30 s is an `error check` row of its own; the rest go on.
|
|
327
|
+
- **Under the new chi:** the check runs in the update handed over to, so the new
|
|
328
|
+
API is what it's held against. When that hasn't happened, a row says
|
|
329
|
+
`external bundles … not checked (…)` instead of an answer about the old
|
|
330
|
+
API: `--dry-run` with a newer gem to install (without one, a dry run checks,
|
|
331
|
+
against this chi), and a gem installed with no way to hand over (run `chi
|
|
332
|
+
update` again). A failed gem install checks against this chi, since it stays.
|
|
333
|
+
- `--no-bundles` (`update.bundles: false`) leaves these out too: no check, no row
|
|
334
|
+
but `bundles skipped`.
|
|
304
335
|
- **Profiles** (`core`, `dev`): an installed one installs the bundles a new
|
|
305
336
|
chi added to it (`updated (+ name)`), even at the same version, and retries
|
|
306
337
|
one that failed before; one you uninstalled stays out. See [Bundle
|
|
@@ -377,10 +408,12 @@ flag also works as `--kebab-case VALUE`, e.g. `--server-host`, `--server-port`,
|
|
|
377
408
|
`--read-truncate-at-bytes`; an on/off setting is `--[no-]kebab-case` with no value
|
|
378
409
|
(`--context-status`, `--no-context-status`). `chi --help` lists them all.
|
|
379
410
|
|
|
380
|
-
**Which loop runs.** There is no backend flag: the model's host decides. A host
|
|
381
|
-
`api: openai`
|
|
382
|
-
provider via `url:` and `api_key_env:`)
|
|
383
|
-
|
|
411
|
+
**Which loop runs.** There is no backend flag: the model's host's `api:` decides. A host whose `api:` has
|
|
412
|
+
a chat adapter runs `LLM::ChatLoop` — `api: openai` through `LLM::OpenAIChat` (`/v1/chat/completions`,
|
|
413
|
+
streamed; a remote provider via `url:` and `api_key_env:`) or `api: anthropic` through
|
|
414
|
+
`LLM::AnthropicMessages` (`/v1/messages`). Every other host (no `api:`, or `api: llama_cpp`) runs chi's own
|
|
415
|
+
raw-prompt loop, `KernelLoop`, on llama.cpp's native `/completion`. `/model` and `--model host:model` switch
|
|
416
|
+
hosts, and the loop with them. See [Configuration](configuration.md) (`hosts:` and `api:`).
|
|
384
417
|
`--backend`, `SAMAGOTCHI_BACKEND` and a `backend:` key were removed (`backend:` warns
|
|
385
418
|
as an unknown key).
|
|
386
419
|
|
|
@@ -461,6 +494,11 @@ and `--shared` are refused. Its first line says it is a scratch session.
|
|
|
461
494
|
|
|
462
495
|
### Sharing a session
|
|
463
496
|
|
|
497
|
+
Two different things share a session: `session.shared` is about UIs — several
|
|
498
|
+
terminals and the Web UI attached to one worker — while `chi share` invites
|
|
499
|
+
other people, participants with a link of their own (see
|
|
500
|
+
[Participants](#participants)).
|
|
501
|
+
|
|
464
502
|
Plain `chi` runs the session in a background worker and attaches the terminal
|
|
465
503
|
to it (`session.shared`, default `true`). A worker's session can have any number
|
|
466
504
|
of UIs at once: the Web UI and attached terminals (`chi`, `--resume`,
|
|
@@ -1492,7 +1530,7 @@ chi --remote work sessions list
|
|
|
1492
1530
|
|
|
1493
1531
|
SSH can forward a Unix socket as well, which is how claude-peer's pairing makes
|
|
1494
1532
|
a Claude session on this laptop reachable from chi on that machine
|
|
1495
|
-
(`pair --inbox-socket <path>`): see [
|
|
1533
|
+
(`pair --inbox-socket <path>`): see [bundles.md](bundles.md#the-claude-peer-bundle), "chi on another
|
|
1496
1534
|
machine".
|
|
1497
1535
|
|
|
1498
1536
|
How it works inside (`SessionAccess`, chi web's routes, where each check runs):
|
data/docs/configuration.md
CHANGED
|
@@ -127,7 +127,7 @@ own subsystems: `hosts:` (below), `models:` (see "Prompt profile" and
|
|
|
127
127
|
`guardrails:` (see [Guardrails](guardrails.md)), `bundles:` (a bundle's
|
|
128
128
|
settings for its hooks, see [Hooks: Settings](hooks.md#settings); a session's own
|
|
129
129
|
`--set BUNDLE.KEY=VALUE`, for a key the bundle's manifest lists in `session_settings:`, lays over them, see
|
|
130
|
-
[Per-session settings](plugins.md#per-session-settings); `--set KEY=VALUE` does the same for a few core keys,
|
|
130
|
+
[Per-session settings](plugins.md#per-session-settings); a name no installed bundle has, or a key its manifest's `settings:` rules out, warns at a session's start; `--set KEY=VALUE` does the same for a few core keys,
|
|
131
131
|
see "Per-session settings" below),
|
|
132
132
|
`memories:` and `append_system_prompt:` (see "Appended prompt files"). Their entry names (host names, model ids, aliases) are yours to
|
|
133
133
|
choose. The `memories:` list is the persistent baseline for preloaded memory entries —
|
|
@@ -149,7 +149,7 @@ or `chi web` restart.
|
|
|
149
149
|
|---|---|---|
|
|
150
150
|
| `default.model` | New session | Existing sessions keep their saved model; change one with `/model`. |
|
|
151
151
|
| `default.input`, `no_default_input`, `no_interrupt` | Next CLI run | These set up that run's first prompt or turn limit. |
|
|
152
|
-
| `default.max_tokens`, `max_tool_output_chars`, `read.*`, `execute.*` except `execute.description`, `image.*` | Next matching request or tool use | An operation already in progress keeps its resolved limits. |
|
|
152
|
+
| `default.max_tokens`, `max_tool_output_chars`, `memory.read_max_chars`, `read.*`, `execute.*` except `execute.description`, `image.*` | Next matching request or tool use | An operation already in progress keeps its resolved limits. |
|
|
153
153
|
| `server.host`, `server.port`, `hosts.*` | Worker start | Includes host addresses, APIs, declared models and host-level settings. The web model picker refreshes `hosts:` on file change; a running worker does not. |
|
|
154
154
|
| `server.open_timeout`, `server.read_timeout`, `server.first_token_timeout` | Worker start | The worker's clients retain the timeouts set when they were built. |
|
|
155
155
|
| `model_aliases` | Next model lookup | A session keeps its resolved model unless it is explicitly switched. |
|
|
@@ -166,9 +166,10 @@ or `chi web` restart.
|
|
|
166
166
|
| `toolkit.kits`, `execute.description`, `llm_context.policy` | Worker start | These are held by the engine's toolkit or tool registry. |
|
|
167
167
|
| `toolkit.suggest.mode`, `toolkit.suggest.threshold`, `toolkit.suggest.defer_turns`, `toolkit.suggest.defer_tokens` | Worker start | Suggestion settings are config-only and are resolved when the worker runs its audit or on-mode ask. |
|
|
168
168
|
| `skip_agents_md` | Prompt rebuild | A running engine caches its built prompt; a new worker or `/model` rebuild uses the changed value. |
|
|
169
|
-
| `context.*` except `context.every_seconds`, `llm_context.*` except `llm_context.policy`, `steer.cut_after`, `memory.index_warn_tokens`, `status.line`, `web.participants.*` | Next matching turn, display, poll or write | Readers resolve these settings when they perform that operation. Session-specific LLM context and thinking values remain saved in the session. A participant's grant keeps the expiry and cap it was issued with; `web.participants.*` is what the next invite gets, and the cap and queue of a grant from before caps. |
|
|
169
|
+
| `context.*` except `context.every_seconds`, `llm_context.*` except `llm_context.policy`, `steer.cut_after`, `memory.index_warn_tokens`, `memory.entry_warn_tokens`, `status.line`, `web.participants.*` | Next matching turn, display, poll or write | Readers resolve these settings when they perform that operation. Session-specific LLM context and thinking values remain saved in the session. A participant's grant keeps the expiry and cap it was issued with; `web.participants.*` is what the next invite gets, and the cap and queue of a grant from before caps. |
|
|
170
170
|
| `context.every_seconds` | Next context poll | The poller checks it for each source that has no explicit interval. |
|
|
171
171
|
| `guardrails.*` | Next tool call or approval | Guardrail rules and disable lists are reloaded when the config file changes; rule settings take effect on that evaluation. `guardrails.parent_answers` is checked when a parent answers a question. |
|
|
172
|
+
| `system_one.host`, `system_one.model`, `system_one.timeout_ms`, `system_one.runs`, `system_one.judgments` | Next tool call or approval | Each ask reads them. |
|
|
172
173
|
| `hooks`, `bundles` | Worker start | Hooks, plugins and their bundle settings load with the engine. |
|
|
173
174
|
| `recap.*` | Worker start | The engine builds its recap job at start, and again when it binds a session with its own `recap.enabled` or `recap.sentences` (`--set`, see "Per-session settings") and when `/recap on\|off\|default` changes the session's own value. |
|
|
174
175
|
| `session.shared` | Next `chi` invocation | It selects attached-worker or in-process mode for that invocation. |
|
|
@@ -185,7 +186,7 @@ or `chi web` restart.
|
|
|
185
186
|
|
|
186
187
|
### Per-session settings
|
|
187
188
|
|
|
188
|
-
A few core keys can be set for one session: `chi --set KEY=VALUE` (or `chi send --new --set KEY=VALUE`, or
|
|
189
|
+
A few core keys can be set for one session (the registry entries marked `session: true`, `Config::Entry#session?`): `chi --set KEY=VALUE` (or `chi send --new --set KEY=VALUE`, or
|
|
189
190
|
`POST /api/sessions` `settings`) at its creation, and `recap.enabled` later too with `/recap on`, `/recap off` or `/recap default`
|
|
190
191
|
(at once; `default` removes the session's own value, see [Session recap](cli.md#session-recap)). The value is saved in the session file (`config_settings`), so a
|
|
191
192
|
worker respawn, a continue and a fork keep it; a delegate child starts without it, on config.yml's. It goes first:
|
|
@@ -1451,7 +1452,7 @@ To skip loading AGENTS.md (all of the chain), set `skip_agents_md: true` at the
|
|
|
1451
1452
|
|
|
1452
1453
|
Nested `AGENTS.md` files (in directories the session doesn't run in) are
|
|
1453
1454
|
steered into the conversation on first touch by the `agents-md` bundle
|
|
1454
|
-
([The agents-md bundle](
|
|
1455
|
+
([The agents-md bundle](bundles.md#the-agents-md-bundle)); `skip_agents_md`
|
|
1455
1456
|
disables that steering too.
|
|
1456
1457
|
|
|
1457
1458
|
## Appended prompt files
|
|
@@ -1526,14 +1527,14 @@ toolkit:
|
|
|
1526
1527
|
`undecided` for greetings or check-ins. Only a default-origin session with at least two described candidates is
|
|
1527
1528
|
asked; chosen or inherited toolkits, delegate children, review sessions and participant turns are skipped. After
|
|
1528
1529
|
`undecided`, later owner prompts may be asked again within both defer limits. The default is `off`. System 1's
|
|
1529
|
-
host, model and timeout come from `
|
|
1530
|
+
host, model and timeout come from `system_one.*`; the suggestion threshold and defer limits are its own
|
|
1530
1531
|
settings below. Suggestions are
|
|
1531
1532
|
kept in `toolkit_suggestions.jsonl`; `chi toolkit report` grades them against the session's tool calls. One ask
|
|
1532
1533
|
runs at a time (a turn that comes while one still runs goes unasked, with an info line), and a kit that doesn't
|
|
1533
1534
|
resolve (a missing base, a cycle) is left out of the candidates. A worker that exits waits about a second for a
|
|
1534
1535
|
running ask, so a one-shot `-p --non-interactive` run may end before its suggestion is logged.
|
|
1535
1536
|
- **On mode.** `toolkit.suggest.mode: on` asks the same question on the same eligible turns, but the turn waits for
|
|
1536
|
-
the answer before it declares any tool, for at most `
|
|
1537
|
+
the answer before it declares any tool, for at most `system_one.timeout_ms` from the ask's start (it
|
|
1537
1538
|
starts right after the turn does, so plugin and MCP start-up hide most of it). A described kit picked with
|
|
1538
1539
|
confidence at or above `toolkit.suggest.threshold` becomes the session's toolkit, saved with `toolkit_origin:
|
|
1539
1540
|
suggested`, and the turn's first request declares it; the notice reads
|
|
@@ -1541,14 +1542,12 @@ toolkit:
|
|
|
1541
1542
|
pick, `undecided`, no answer, a failing System 1, which warns once as `[samagotchi:toolkit]`) keeps the default
|
|
1542
1543
|
kit. No answer in time or none at all says so in a warn notice, `toolkit: full (no suggestion: System 1 took over
|
|
1543
1544
|
5000 ms) · /toolkit to change` (or `System 1 gave no answer`), and a timeout logs a `toolkit_suggest_timeout`
|
|
1544
|
-
warning: a slow System 1 host wants a larger `
|
|
1545
|
+
warning: a slow System 1 host wants a larger `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
|
|
1545
1546
|
nothing switches. After an `undecided`, a later prompt within the defer limits may switch the session; that notice
|
|
1546
1547
|
says `from this turn`, and that request re-reads the whole prompt (system prompt, tools and conversation, which
|
|
1547
1548
|
the defer limits keep small) without `/toolkit`'s cache confirmation. `/toolkit` or `ctx.use_toolkit` marks the
|
|
1548
1549
|
toolkit chosen, and nothing is suggested after that; a `/toolkit` sent during a turn runs after it and replaces
|
|
1549
|
-
that turn's suggestion.
|
|
1550
|
-
root, as audit checks), on mode asks only on a session's first turn, never on the deferred path, and sends no
|
|
1551
|
-
warm-up (one info line). Otherwise an idle worker for an eligible session sends one warm-up ask with the real
|
|
1550
|
+
that turn's suggestion. An idle worker for an eligible session sends one warm-up ask with the real
|
|
1552
1551
|
question and a stand-in prompt so the server has its prefix cached; its answer is dropped and never logged, and
|
|
1553
1552
|
the first real ask stops a warm-up still running. Each answered ask's line in `toolkit_suggestions.jsonl` adds
|
|
1554
1553
|
`did`: `suggested`, `default`, `defer`, `chosen` (the toolkit was no longer the default), `unavailable` (the
|
|
@@ -1591,7 +1590,7 @@ toolkit:
|
|
|
1591
1590
|
- **A new web chat: 🧰.** The start page's 🧰 (beside ⚙; a bottom sheet on a phone) picks the new session's toolkit.
|
|
1592
1591
|
**Auto**, checked by default, sends nothing: the session is on `toolkit.default` with `toolkit_origin: default`, so
|
|
1593
1592
|
with `toolkit.suggest.mode: on` its first message may switch it to a suggested kit. Auto is listed only when that
|
|
1594
|
-
can happen as far as chi web can tell (on mode, a `
|
|
1593
|
+
can happen as far as chi web can tell (on mode, a `system_one.host`, two described config kits); bundle
|
|
1595
1594
|
and memory kits can add candidates it doesn't see. A kit picked is sent as `POST /api/sessions`'s `toolkit` and
|
|
1596
1595
|
saved as `chosen`: no suggestion, the default kit included (its row says `default`); without Auto, the default's
|
|
1597
1596
|
row is the one checked and sends nothing. The list holds the built-ins and config kits a new session can start
|
|
@@ -1640,6 +1639,21 @@ toolkit:
|
|
|
1640
1639
|
changes what saved sessions on it send after an upgrade: the next request reads the prompt again once, as a
|
|
1641
1640
|
tool's schema change does. So can an edit to `toolkit.kits`: a session's worker reads the kits once when it starts, so a running session keeps its
|
|
1642
1641
|
tools and the edit reaches it at its next worker start (after an idle exit, `chi sessions restart`).
|
|
1642
|
+
- **Why a session is on its kit: `toolkit_origin`.** The session file records `default` (the configured kit),
|
|
1643
|
+
`chosen` (a user-selected kit, `/toolkit` and `ctx.use_toolkit` included), `inherited` (a continue or a fork) or
|
|
1644
|
+
`suggested` (`toolkit.suggest.mode: on` switched it). A file from before the field reads as `chosen`, so an old
|
|
1645
|
+
default session is never newly suggested a kit; only a `default` session is ever suggested one. A delegate child
|
|
1646
|
+
gets the kit its `delegate` call names (`toolkit:`, any kit the parent knows), else `toolkit.child`; a kit its worker
|
|
1647
|
+
can't resolve declares every tool.
|
|
1648
|
+
- **Loads saved in the conversation.** A `find_tools` result on a chat host saves the tools its hit loads as
|
|
1649
|
+
`loaded: ["list_sessions", "mcp_fs_read"]` on its `tool_response` entry (wire names: a built-in's, an MCP tool's
|
|
1650
|
+
`mcp_<server>_<tool>`), whatever the host: a later turn on `api: anthropic` (after a `/model` switch, a resume) sends
|
|
1651
|
+
the load as references, any other host ignores it. A plugin's `ctx.load_tools` leaves a system entry
|
|
1652
|
+
`{"role": "system", "kind": "tool_change", "content": "[tools loaded: delegate (bundle)]", "tool_change": {"add":
|
|
1653
|
+
["delegate"], "by": "bundle"}}` after the turn's user message, only on a host that takes tool changes
|
|
1654
|
+
(`api: anthropic`; [wire details](internals/anthropic.md#tool-changes-ctxload_tools)). It is never the system head,
|
|
1655
|
+
counts as conversation, is hidden in the web and TUI histories and goes to no other wire. Either way the names stay
|
|
1656
|
+
deferred for the session's life, across respawns, `--resume` and forks.
|
|
1643
1657
|
|
|
1644
1658
|
## LLM context: the forget layer
|
|
1645
1659
|
|
|
@@ -1762,7 +1776,7 @@ its own). The first target is a long session such as a day-long coordinator, whe
|
|
|
1762
1776
|
|
|
1763
1777
|
`context.candidates.mode: audit` asks System 1 whether a session's work is about each candidate a bundle proposed
|
|
1764
1778
|
(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 `
|
|
1779
|
+
`offer_threshold` ([On mode](context.md#on-mode)). It uses `system_one.host` and `.model`, but its own mode: System
|
|
1766
1780
|
1's `mode` (approvals) can stay `off`. Jev, the hosted judgment model, is served through OpenRouter
|
|
1767
1781
|
(`/api/v1/systemone`), so OpenRouter can be the System 1 host:
|
|
1768
1782
|
|
|
@@ -1772,18 +1786,37 @@ hosts:
|
|
|
1772
1786
|
url: https://openrouter.ai/api/v1
|
|
1773
1787
|
api: openai
|
|
1774
1788
|
api_key_env: OPENROUTER_API_KEY
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
model: typesafe/jev-1.14
|
|
1789
|
+
system_one:
|
|
1790
|
+
host: openrouter
|
|
1791
|
+
model: typesafe/jev-1.14
|
|
1779
1792
|
context:
|
|
1780
1793
|
candidates:
|
|
1781
1794
|
mode: audit
|
|
1782
1795
|
```
|
|
1783
1796
|
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1797
|
+
The asks run beside the turn, on any host: they cost the session's cached prompt nothing on the model's own Splash
|
|
1798
|
+
either (see [prompt caching](internals/prompt-caching.md)).
|
|
1799
|
+
|
|
1800
|
+
|
|
1801
|
+
## Bundles' judgments
|
|
1802
|
+
|
|
1803
|
+
A bundle can declare its own cheap System 1 questions ([Judgments](plugins.md#judgments-chijudgment-and-ctxjudge)). Each is off until
|
|
1804
|
+
you set its mode under its full name, `<bundle>.<name>`, in `system_one.judgments`:
|
|
1805
|
+
|
|
1806
|
+
```yaml
|
|
1807
|
+
system_one:
|
|
1808
|
+
host: splash
|
|
1809
|
+
judgments:
|
|
1810
|
+
check-in.progress:
|
|
1811
|
+
mode: audit # off (the default) | audit | on
|
|
1812
|
+
host: openrouter # optional, this judgment alone; else system_one.host
|
|
1813
|
+
model: typesafe/jev-1.14 # optional, this judgment alone; else system_one.model, or on a host of its own that host's first model
|
|
1814
|
+
```
|
|
1815
|
+
|
|
1816
|
+
A name no loaded bundle declares gets a notice at the session's first turn. Core's judgments (`approvals.*`, `context.*`, `guardrails.*`,
|
|
1817
|
+
`toolkit.*`) take no settings here and warn if named: `SystemOne::Record` and `Similar` don't look at the model, so a
|
|
1818
|
+
model swapped for approvals alone would inherit a clean record and could auto-allow.
|
|
1819
|
+
A bundle's judgments on a hosted host aren't under any cost cap: they stay out of the session's spend, as all of System 1's do.
|
|
1787
1820
|
|
|
1788
1821
|
## Opening files from chi web
|
|
1789
1822
|
|
|
@@ -2114,17 +2147,19 @@ Both are read when chi web starts (restart it to apply a change). What it does,
|
|
|
2114
2147
|
it pushes the failed row's reason and stays quiet until a newer release (or you, with the button) tries again.
|
|
2115
2148
|
3. **Restarts** (`update.restart: idle`). Stale workers first, only those whose session is idle and untouched for
|
|
2116
2149
|
10 minutes (so nobody who is about to type loses their worker), and each worker still refuses by itself when
|
|
2117
|
-
something holds it ([sessions](sessions.md))
|
|
2118
|
-
idle exit or the session's **Restart**. Then chi web itself, once no turn runs anywhere: it first runs the
|
|
2150
|
+
something holds it ([sessions](sessions.md)). Then chi web itself, once no turn runs anywhere: it first runs the
|
|
2119
2151
|
restart's own command with `--version` (20 s at most) and restarts only if the newest chi answers with the
|
|
2120
2152
|
release's version; otherwise chi web stays up and the phone hears "chi X is installed; chi web didn't restart".
|
|
2121
2153
|
The restart is the **Restart chi web** one: same port, same token, same Tailscale Serve handler, the open page's
|
|
2122
2154
|
streams reconnect in a few seconds and a Reload toast follows. It doesn't wait for a page in front: the page isn't
|
|
2123
2155
|
reloaded by itself, so a draft in the composer stays. A **Send** or **Allow** pressed in those few seconds fails
|
|
2124
2156
|
with its error and leaves the text in the composer: press it again.
|
|
2157
|
+
The workers left are tried again every 5 minutes, by the same rule and from the restarted chi web too, for a day from
|
|
2158
|
+
the install; after that they wait for their own idle exit or the session's **Restart**. A newer release in that day
|
|
2159
|
+
installs as usual and takes them over.
|
|
2125
2160
|
4. **Says so.** The restarted chi web pushes "chi updated to X" ("chi web and 3 sessions restarted; 1 restarts when
|
|
2126
|
-
idle. Kept your edits in 2 files.")
|
|
2127
|
-
the workers move over when you restart them (the page's toast offers it). The push needs the phone set up
|
|
2161
|
+
idle. Kept your edits in 2 files."); the later restarts of those sessions push nothing more. With
|
|
2162
|
+
`update.restart: never` the push is "chi X is installed" and chi web and the workers move over when you restart them (the page's toast offers it). The push needs the phone set up
|
|
2128
2163
|
([Phone notifications](#phone-notifications-web-push)); without it the page's toasts and
|
|
2129
2164
|
`$XDG_STATE_HOME/samagotchi/update_check.json` (`auto`) are the record.
|
|
2130
2165
|
|
|
@@ -2190,12 +2225,13 @@ column says so, a `--kebab-name` flag. The maps (`hosts:`, `models:`,
|
|
|
2190
2225
|
| `guardrails.small_models` | `auto` | | Which models get the `models: small` rules: `auto` (32B or less by the size in the name, an MoE's active size), a list of globs, or `[]`. config.yml only. See [Guardrails](guardrails.md#rules-for-some-models). |
|
|
2191
2226
|
| `guardrails.parent_answers` | `soft` | | Which options a parent agent (`chi answer`) may pick on a session's question, by their effect: `hard` (a deny, a Stop, a plain answer), `standard` (+ Continue and other spending options), `soft` (+ "Allow once"); never a wider scope or an allow on chi's own config. An invalid value warns and is `hard`. A session's own `parent_answers` (`chi --parent-answers`, `/parent-answers`) may only tighten it. Replaces `guardrails.parent_approvals` and `turn.parent_continue`. config.yml only: no environment variable (a parent can still pick the config dir with `XDG_CONFIG_HOME`). A convention for an honest parent, not a security boundary. See [Guardrails](guardrails.md#answers-from-a-parent-agent). |
|
|
2192
2227
|
| `guardrails.system_one.mode` | `off` | | System 1, the cheap judgment that answers an ask before the user sees it: `off` (the default), `audit` (judge every ask, log it, never decide), `on` (also allowed to allow a call once, behind the gates in [System 1](guardrails.md#system-1-experimental)). An unknown value warns and is `off`. Experimental. config.yml only. See [Guardrails](guardrails.md#system-1-experimental). |
|
|
2193
|
-
| `guardrails.system_one.host` | none | | The `hosts:` entry serving `/v1/systemone` (a local Splash, or the hosted Jev API); unset: no judgment. config.yml only. |
|
|
2194
|
-
| `guardrails.system_one.model` | none | | The judgment model; unset uses the host's first model, and a host that names none has no judgment. config.yml only. |
|
|
2195
2228
|
| `guardrails.system_one.rules` | none | | The rule ids System 1 may answer for in `on` mode: `"git-push|git-rebase"` or a YAML list, parsed like `guardrails.small_models`. Nothing is auto-allowed while it is unset; the `chi-answer-piped`, `chi-answer-http` and `chi-broadcast` rules never are, however they are listed. config.yml only. |
|
|
2196
2229
|
| `guardrails.system_one.threshold` | `0.8` | | The probability an auto-allow needs. config.yml only. |
|
|
2197
2230
|
| `guardrails.system_one.min_record` | `5` | | How many clean records a rule needs before System 1 is trusted for it: labelled asks of that rule at the threshold the user allowed. config.yml only. |
|
|
2198
|
-
| `
|
|
2231
|
+
| `system_one.host` | none | | The `hosts:` entry serving `/v1/systemone` (a local Splash, or the hosted Jev API); unset: no judgment, by any use of System 1, so nothing auto-allows and every ask goes to the user. Moved from `guardrails.system_one.host`: while any of host, model and timeout_ms is still under `guardrails.system_one`, chi warns and nothing is judged. config.yml only. |
|
|
2232
|
+
| `system_one.model` | none | | The judgment model; unset uses the host's first model, and a host that names none has no judgment. Moved from `guardrails.system_one.model`. config.yml only. |
|
|
2233
|
+
| `system_one.timeout_ms` | `2000` | | Milliseconds one judgment may take; a slower one is no judgment and the ask goes to the user. Moved from `guardrails.system_one.timeout_ms`. config.yml only. |
|
|
2234
|
+
| `system_one.runs` | `on` | | Save each System 1 ask and what came of it, under the state dir, as long as sessions last (see [System 1's saved runs](system-one.md)); `off` stops saving. config.yml only. |
|
|
2199
2235
|
| `log.file` | state dir | yes | See "Debug Log File". |
|
|
2200
2236
|
| `log.disable` | `false` | yes | No file logging. |
|
|
2201
2237
|
| `log.level` | `info` | yes | `debug`, `info`, `warn`, `error`. |
|
|
@@ -2218,13 +2254,13 @@ column says so, a `--kebab-name` flag. The maps (`hosts:`, `models:`,
|
|
|
2218
2254
|
| `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). |
|
|
2219
2255
|
| `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). |
|
|
2220
2256
|
| `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 `
|
|
2257
|
+
| `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 `system_one.host` / `.model`. config.yml only. See [The judge](context.md#the-judge). |
|
|
2222
2258
|
| `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
2259
|
| `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
2260
|
| `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. |
|
|
2225
2261
|
| `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". |
|
|
2226
2262
|
| `toolkit.child` | `full` | | A delegate child's toolkit, unless its `delegate` call names one (`toolkit:`). See "Toolkits". |
|
|
2227
|
-
| `toolkit.suggest.mode` | `off` | | `audit` asks System 1 for a toolkit suggestion without changing the session; `on` waits for it (up to `
|
|
2263
|
+
| `toolkit.suggest.mode` | `off` | | `audit` asks System 1 for a toolkit suggestion without changing the session; `on` waits for it (up to `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 `system_one.*`. config.yml only. |
|
|
2228
2264
|
| `toolkit.suggest.threshold` | `0.5` | | Minimum confidence for a non-default toolkit suggestion. config.yml only. |
|
|
2229
2265
|
| `toolkit.suggest.defer_turns` | `3` | | Maximum owner-prompt number for another ask after `undecided` (the owner's own prompts: not steers, notes, reminders or `!` command output). config.yml only. |
|
|
2230
2266
|
| `toolkit.suggest.defer_tokens` | `5000` | | Maximum estimated conversation size for another ask after `undecided` (characters / 4). config.yml only. |
|
|
@@ -2235,7 +2271,9 @@ column says so, a `--kebab-name` flag. The maps (`hosts:`, `models:`,
|
|
|
2235
2271
|
| `hosts.<name>.models.<id>.served` | none | | The models the host may answer that id with (exact ids, any case), or `any`: no served-model warning for those. See "Models a host serves but doesn't list". |
|
|
2236
2272
|
| `hosts.<name>.models.<id>.price` | none | | The model's price on that host, USD per 1M tokens: `input`, `output`, optional `cache_read` and `cache_write`. Estimates the cost a provider doesn't report. See "Prices". |
|
|
2237
2273
|
| `hosts.<name>.remote` | by address | | `true`/`false`: treat the host as a remote provider or a local server. See "Remote or local". |
|
|
2238
|
-
| `
|
|
2274
|
+
| `memory.entry_warn_tokens` | `5000` | yes | The tokens one memory may hold (every read of it pays them; about 20K characters at the default `context.chars_per_token`) before a `memory_write`, `write` or `edit` that takes it over gets a note, once per crossing, asking the model to tighten it; `0`: no note. A memory that did not exist counts as 0 tokens. Not for a description-only write, a remove, `index`, a model overlay or a `model_notes_*` memory. Independent of `memory.index_warn_tokens`. See [Memory](memory.md). |
|
|
2275
|
+
| `memory.read_max_chars` | `0` | yes | The most characters one `memory_read` result holds. `0`: no fixed cap, a memory is read whole (`max_tool_output_chars` does not apply to `memory_read`, in any form: one name, a comma list, a blank name). A positive value cuts a longer result and ends it with `[cut: N of M chars; the rest is in the memory's .md file in <dir>: read it with start_line]`. `memory:` is its own section. See [Memory](memory.md). |
|
|
2276
|
+
| `max_tool_output_chars` | `10000` | yes | Characters of each tool output kept in the conversation (both loops). A longer one is cut: an `execute` result keeps its first and last lines with a gap line between them and is saved whole in the session's folder (`sessions/<id>/tool_output/`; the gap line names the file, and the model reads it there instead of running the command again); any other tool's keeps its head and ends with `[cut: N of M chars; read it in parts]`. `memory_read` is the exception: `memory.read_max_chars` caps it. See [Tool output guardrails](internals/tool-output-limits.md#the-runners-cut-max_tool_output_chars). A top-level key (see below). |
|
|
2239
2277
|
| `cache.warmup` | `auto` | | `auto`: after a turn, send the next turn's prompt (up to the next message) to a local llama.cpp host on the native loop, so the next turn prefills only its message; never a remote or `api: openai` host. `off`: never. See [prompt caching](internals/prompt-caching.md#the-turn-end-warm-up). |
|
|
2240
2278
|
| `cache.ttl` | `5m` | | How long Anthropic keeps the prompt-cache breakpoints of a Claude model on a remote host: `5m` (Anthropic's default) or `1h`. A 1h cache write costs 2× the input price (5m: 1.25×), a read the same 0.1×. See "Remote or local". |
|
|
2241
2279
|
| `cache.key` | `off` | | `session`: send the session id as `prompt_cache_key` to OpenAI's API and OpenRouter, which route and cache by it; no other host gets it. `off`: none. |
|
data/docs/context.md
CHANGED
|
@@ -126,10 +126,10 @@ pbpaste | chi context push clip --project
|
|
|
126
126
|
```
|
|
127
127
|
|
|
128
128
|
A Claude Code session can be a pushed source too: the
|
|
129
|
-
[claude-peer bundle](
|
|
129
|
+
[claude-peer bundle](bundles.md#the-claude-peer-bundle)'s `pair` script attaches
|
|
130
130
|
`claude-inbox` (Claude's inbox socket as the hint) and `claude-outbox`, where
|
|
131
131
|
Claude pushes its answers as JSON with `wake: true`. The
|
|
132
|
-
[codex-peer bundle](
|
|
132
|
+
[codex-peer bundle](bundles.md#the-codex-peer-bundle)'s does the same for a
|
|
133
133
|
Codex session: `codex-inbox` (Codex's thread id as the hint) and
|
|
134
134
|
`codex-outbox`.
|
|
135
135
|
|
|
@@ -273,7 +273,7 @@ back the same way, its note plain, and pauses wakes too.
|
|
|
273
273
|
|
|
274
274
|
### Peer sources: the peer loop
|
|
275
275
|
|
|
276
|
-
The claude-peer and codex-peer bundles ([
|
|
276
|
+
The claude-peer and codex-peer bundles ([Bundles](bundles.md#the-claude-peer-bundle)) pair the
|
|
277
277
|
session with a Claude Code or Codex session; the peer's answers come back as
|
|
278
278
|
the `claude-outbox` / `codex-outbox` pushed source (the peer's `scripts/pair`
|
|
279
279
|
attaches it). The bundle declares that source a peer's (`chi.peer_source`,
|
|
@@ -358,7 +358,7 @@ An archived session that nobody continued takes pushes as before.
|
|
|
358
358
|
|
|
359
359
|
### Peers and a continue
|
|
360
360
|
|
|
361
|
-
A peer's pairing ([claude-peer, codex-peer](
|
|
361
|
+
A peer's pairing ([claude-peer, codex-peer](bundles.md#the-claude-peer-bundle):
|
|
362
362
|
`<peer>-inbox` and `<peer>-outbox`, both pushed) stays with the old session,
|
|
363
363
|
and the peer pairs again with the new one. The continue keeps what stayed in
|
|
364
364
|
the new session (`left.json` beside its sources: each name, its last pushed
|
|
@@ -432,8 +432,8 @@ about each proposed candidate — "Is this session's work about the
|
|
|
432
432
|
candidate?" — and logs the answer, so you can see how it would do before
|
|
433
433
|
anything depends on it; `audit` attaches nothing. With `on` the answer acts
|
|
434
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
|
-
`
|
|
435
|
+
turn this on, whatever `guardrails.system_one.mode` says. The host and model are
|
|
436
|
+
`system_one.host` / `.model` (Jev through OpenRouter: see
|
|
437
437
|
[The candidate judge](configuration.md#the-candidate-judge)).
|
|
438
438
|
|
|
439
439
|
```yaml
|
|
@@ -462,11 +462,8 @@ What it asks, and when:
|
|
|
462
462
|
(a first "hi" doesn't count against it).
|
|
463
463
|
- **After a judged ask:** one re-ask once `reask_after_turns` more prompts of
|
|
464
464
|
yours came, with the conversation grown; then it is done.
|
|
465
|
-
- **Where it runs:** on
|
|
466
|
-
|
|
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.
|
|
465
|
+
- **Where it runs:** beside your turn, on any System 1 host. One session's
|
|
466
|
+
asks run one batch at a time.
|
|
470
467
|
|
|
471
468
|
### On mode
|
|
472
469
|
|
|
@@ -503,7 +500,10 @@ none at the thresholds then, with your prompts cut to 200 characters),
|
|
|
503
500
|
`p`), `attached` / `declined` with `by: "command"` (`/context attach|decline`,
|
|
504
501
|
the card's buttons), `attached` / `declined` / `detached` with `by: "user"`
|
|
505
502
|
(what you did otherwise, seen at your next turn's start; removing a source
|
|
506
|
-
declines it) and `withdrawn`.
|
|
503
|
+
declines it) and `withdrawn`. `chi sessions delete` drops a session's lines
|
|
504
|
+
from this log too, so the prompts it cut to 200 characters go with it; the
|
|
505
|
+
log's own size cap (5 MB, keeping the newest half) is what ages everything
|
|
506
|
+
else.
|
|
507
507
|
|
|
508
508
|
`chi context report [--days N]` counts it, with no prompts in the output
|
|
509
509
|
(this machine only):
|
data/docs/guardrails.md
CHANGED
|
@@ -11,7 +11,10 @@ are offered.
|
|
|
11
11
|
Who votes, in order:
|
|
12
12
|
|
|
13
13
|
1. `before_tool_call` hooks (Ruby; see [Hooks](hooks.md#guardrails-from-a-hook)).
|
|
14
|
-
2. Core checks: a required guardrail that failed to load, then
|
|
14
|
+
2. Core checks (`GuardrailWiring#checks`): a required guardrail that failed to load, then (a participant's turn only)
|
|
15
|
+
[the review boundary](#a-participants-review-boundary) or, for a pair turn,
|
|
16
|
+
[the pair boundary](#a-participants-pair-boundary), then protected paths, then (a `chi scratch` session only)
|
|
17
|
+
writes to the memories folder (rule `scratch-session`), then (a delegate child only)
|
|
15
18
|
[the child boundary](#a-delegate-childs-boundary).
|
|
16
19
|
3. YAML rules: `config.yml`'s `guardrails:` section, then installed bundles' rule files (by bundle name).
|
|
17
20
|
|
|
@@ -283,8 +286,9 @@ Built in, for `write`, `edit` and `memory_write` (symlinks resolved; see
|
|
|
283
286
|
[How paths resolve](#how-paths-resolve)):
|
|
284
287
|
|
|
285
288
|
- deny: the approval store's dir, installed bundles (`memories/.bundles/`),
|
|
286
|
-
|
|
287
|
-
source's command runs later, outside the gate; `chi context` changes them)
|
|
289
|
+
[attached context](context.md) sources (`<state dir>/context/`: a
|
|
290
|
+
source's command runs later, outside the gate; `chi context` changes them)
|
|
291
|
+
and [System 1's saved runs](system-one.md) (`<state dir>/system_one/`);
|
|
288
292
|
- ask (once or for the session): `config.yml`, `home.json` (the [chi home](configuration.md#the-chi-home): the Ruby every chi launch boots), the chi shim (`$XDG_STATE_HOME/samagotchi/bin/chi`, the `chi` every tool runs: `chi-shim`) and the plain hooks dir.
|
|
289
293
|
|
|
290
294
|
`execute` can still reach them; the guardrails bundle asks about shell
|
|
@@ -745,7 +749,7 @@ repo is in count as outside.
|
|
|
745
749
|
|
|
746
750
|
`touches: chi_dirs` (shell tools) matches a command that names a path in chi's
|
|
747
751
|
own folders: the config folder (`config.yml`, `memories/`), the hooks folder,
|
|
748
|
-
the approval store, installed bundles (`memories/.bundles`), the session repo's
|
|
752
|
+
the approval store, attached context, System 1's saved runs, installed bundles (`memories/.bundles`), the session repo's
|
|
749
753
|
git hooks (`core.hooksPath` honoured) or any `.git/hooks` (a submodule's `.git/modules/<name>/hooks` too)
|
|
750
754
|
outside a tmp folder.
|
|
751
755
|
Each word is read as a path against the folder the command is in by then
|
|
@@ -1045,25 +1049,32 @@ reaching them — see [Answering for the user](#answering-for-the-user-on-mode).
|
|
|
1045
1049
|
`Samagotchi::SystemOne` (lib/samagotchi/system_one/) speaks the TypeSafe
|
|
1046
1050
|
"System One" judgment API: `POST <host>/v1/systemone` with
|
|
1047
1051
|
`{model, state, questions}` and answers of type `noul` (a probability),
|
|
1048
|
-
`choice` or `score`.
|
|
1052
|
+
`choice` or `score`. A `score` answer's number is not a level: it is the
|
|
1053
|
+
probability-weighted level index (Σ index × its probability), so a two-level
|
|
1054
|
+
question's score is exactly the probability of its second level. The response
|
|
1055
|
+
also sends `legend` (level index => name) and `probabilities` per index; chi
|
|
1056
|
+
keeps the score as sent and reads the level with the most probability as
|
|
1057
|
+
`answer.level`. A score that isn't a number, or is past the last level, is no
|
|
1058
|
+
answer. The host is a `hosts:` entry with `api: openai` — a
|
|
1049
1059
|
local Splash server, or the hosted Jev API — and its key is that host's own
|
|
1050
1060
|
`api_key_env:`.
|
|
1051
1061
|
|
|
1052
1062
|
```yaml
|
|
1063
|
+
system_one: # what every use of System 1 shares
|
|
1064
|
+
host: splash # the hosts: entry serving /v1/systemone
|
|
1065
|
+
model: Qwen3.8-Flash-Next-GSQ-RCO-GGUF:Q2_0 # else the host's first model
|
|
1066
|
+
timeout_ms: 2000 # a slower judgment is no judgment
|
|
1053
1067
|
guardrails:
|
|
1054
|
-
system_one:
|
|
1068
|
+
system_one: # approvals' own
|
|
1055
1069
|
mode: off # off (default) | audit (judge, log, never decide) | on
|
|
1056
|
-
host: splash # the hosts: entry serving /v1/systemone
|
|
1057
|
-
model: Qwen3.8-Flash-Next-GSQ-RCO-GGUF:Q2_0 # else the host's first model
|
|
1058
1070
|
rules: [git-push, git-rebase] # the rule ids it may answer for
|
|
1059
1071
|
threshold: 0.8 # the probability an auto-allow needs
|
|
1060
1072
|
min_record: 5 # clean records a rule needs before it is trusted
|
|
1061
|
-
timeout_ms: 2000 # a slower judgment is no judgment
|
|
1062
1073
|
```
|
|
1063
1074
|
|
|
1064
|
-
`SystemOne::Client.from_config(host_registry:
|
|
1075
|
+
`SystemOne::Client.from_config(host_registry:, mode:)` reads these on every
|
|
1065
1076
|
call, so a config.yml change takes effect on the next ask. `mode: off` (the
|
|
1066
|
-
default) or no `host` means there is no client at all. Anything else is no
|
|
1077
|
+
default) or no `system_one.host` means there is no client at all. Anything else is no
|
|
1067
1078
|
judgment and one `Log.warn(:guardrails, "system_one_failed", …)`: an
|
|
1068
1079
|
unreachable host, a host that isn't `api: openai`, a status other than 200,
|
|
1069
1080
|
a body that isn't JSON, a question with no answer, a request longer than
|
|
@@ -1078,12 +1089,8 @@ not `guardrails.system_one.mode`. Audit never changes the session's toolkit;
|
|
|
1078
1089
|
on mode's turn waits for the answer (at most `timeout_ms`, cut by a Stop)
|
|
1079
1090
|
and may start the session on the suggested kit (configuration.md, Toolkits).
|
|
1080
1091
|
Its warnings use the `toolkit` tag and its records are written to
|
|
1081
|
-
`toolkit_suggestions.jsonl` beside the guardrail logs.
|
|
1082
|
-
|
|
1083
|
-
the System 1 host is the model's local host: the same `hosts:` name, or
|
|
1084
|
-
another entry for the same server root (scheme, host and port). There is no
|
|
1085
|
-
reliable single-slot signal, so this host-identity check is the available
|
|
1086
|
-
contention guard. The session's own checks come first; the kits and the
|
|
1092
|
+
`toolkit_suggestions.jsonl` beside the guardrail logs. The session's own
|
|
1093
|
+
checks come first; the kits and the
|
|
1087
1094
|
suggestion log are read only for a session that can be asked, the log only
|
|
1088
1095
|
after an earlier `undecided`.
|
|
1089
1096
|
|
|
@@ -1093,8 +1100,7 @@ questions per proposed candidate, "Is this session's work about the
|
|
|
1093
1100
|
candidate?" and "Has the user stated a task yet?", on the same host and
|
|
1094
1101
|
model, gated by its own mode alone. It logs to `context_candidates.jsonl`
|
|
1095
1102
|
with the `context` tag; in on mode `ContextCandidateChoice` acts on the
|
|
1096
|
-
answer (attach, card, or nothing).
|
|
1097
|
-
local host: it asks after the turn ends there. Both side judgments run
|
|
1103
|
+
answer (attach, card, or nothing). Both side judgments run
|
|
1098
1104
|
through `SideJudgments` (one ask in flight per kind, a failure is one warn,
|
|
1099
1105
|
shutdown waits up to a second).
|
|
1100
1106
|
|
|
@@ -1118,7 +1124,8 @@ offers no examples. A participant's turn (review or pair) is never judged:
|
|
|
1118
1124
|
there is no user there to ask, and its asks go to the owner. The judgment runs before the card appears, so an ask is
|
|
1119
1125
|
slower by up to `timeout_ms` (2000 ms by default).
|
|
1120
1126
|
|
|
1121
|
-
Each
|
|
1127
|
+
Each ask is also saved whole, with what the user answered, as a [run](system-one.md); the line's `id` is the
|
|
1128
|
+
run's. Each judgment is a line in `judgments.jsonl`, beside `approvals.json` in
|
|
1122
1129
|
`$XDG_STATE_HOME/samagotchi/guardrails/` (`SystemOne::Log`): 0600, appended
|
|
1123
1130
|
under an exclusive `flock` (several workers write it), and rewritten —
|
|
1124
1131
|
keeping the newest half of its lines — once it passes 5 MB. A line is never
|