Repository navigation
wiki: config layers page after #170–#172 - #173
Conversation
Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01LHQAfXHofy6QkAgmfmJava
Ingest decision-model and Ollama research, add the decision-models concept page, note ollama.com cloud auth and stale defaults on the providers page, and link the fast lane from action-terminal mode. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01LHQAfXHofy6QkAgmfmJava
Ingest a read of Hermes upstream at bed0d535 and record how it mixes models (fallback chain plus per-task auxiliary models), where embeddings live (memory plugins), and how its 14 community Jev plugins work. Add comparison rows and point decision models and plugin hooks at the revised #148/#149 scope. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01LHQAfXHofy6QkAgmfmJava
llama3.2 (3B) is weak at tool calling; qwen3:8b is the common local pick for agents. Switch the README, docs, persona example and the setup wizard default to qwen3:8b, keeping llama3.2 as the low-memory note. The Ollama provider already sends a Bearer header when api_key or api_key_env resolves, so Ollama cloud works today. Document it (LICH_BASE_URL=https://ollama.com, LICH_API_KEY_ENV=OLLAMA_API_KEY) and replace "unused by ollama" with "optional for ollama". Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01LHQAfXHofy6QkAgmfmJava
Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01LHQAfXHofy6QkAgmfmJava
…press Optional `models` block names provider chains per role. `chat` sets the main loop's failover order; `compress` routes context compression and falls back to the chat chain on failure. ProviderRouter.for_role shares built clients. Without `models`, behavior is unchanged. The TUI labels the first chat-role provider. Part of #149. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01LHQAfXHofy6QkAgmfmJava
… fallback Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01LHQAfXHofy6QkAgmfmJava
…hook
Plugin entries may be { path, settings?, models? } beside a bare path.
Hooks and plugin tools receive the frozen settings and models.chat(role,
...), which refuses roles the entry was not granted. A new
before_llm_call hook may return a note that is capped, sent as a
trailing system message on that one main-loop call, and never saved to
history; throwing hooks fail open.
Part of #149.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01LHQAfXHofy6QkAgmfmJava
…, deep-freeze loader settings Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01LHQAfXHofy6QkAgmfmJava
…gin host features Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01LHQAfXHofy6QkAgmfmJava
Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01LHQAfXHofy6QkAgmfmJava
Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01LHQAfXHofy6QkAgmfmJava
A plugin-owned client for Ollama's local /v1/systemone endpoint asks one choice question per enemy action (and target) before each LLM turn. Shadow mode logs one JSONL line per decision; act mode queues orders through game_bridge's enemy_actions tool and meteor veto when every answer clears the threshold, else the LLM decides. Requests are checked against Ollama's limits before sending; failures fall back and are logged. bench.mjs replays saved snapshots for latency, coverage and agreement with the LLM. Part of #148. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01LHQAfXHofy6QkAgmfmJava
…old, keep log under .lich/game Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01LHQAfXHofy6QkAgmfmJava
Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01LHQAfXHofy6QkAgmfmJava
Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01LHQAfXHofy6QkAgmfmJava
…ed; no tools on the last turn - A tools_enabled list (top-level or gateway) now applies to plugin tools, including the gatekeeper's git_commit. The commander persona lists its three game_bridge tools explicitly. - A before_tool_call hook that throws blocks the call (blocked_by_plugin: hook_error) instead of allowing it. - Tool calls on the max_turns turn are not executed; they are closed with a turn_budget_exhausted result so history stays valid. Part of #133. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01LHQAfXHofy6QkAgmfmJava
…pts persist them Also document the last-turn skip in docs/architecture/agent-loop.md. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01LHQAfXHofy6QkAgmfmJava
…st-turn tool skip) Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01LHQAfXHofy6QkAgmfmJava
Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01LHQAfXHofy6QkAgmfmJava
…tool ids, MCP name collisions - http_request returns ok:false (error http_<status>) for non-2xx, keeping status and body in output. - terminal defaults its command timeout to config terminal_timeout_ms. - The path guard rejects only .. and ../ prefixes, so names like ..notes.txt inside work_dir are allowed. - OpenAI-compatible tool calls without an id get a unique generated id. - MCP names that collide after sanitizing log a warning; first wins. - Backoff comment and provider docs no longer claim the deterministic jitter desynchronizes simultaneous callers. Part of #133. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01LHQAfXHofy6QkAgmfmJava
…st note Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01LHQAfXHofy6QkAgmfmJava
…view; wiki #163 - godot.md and the persona orchestrator README said the CLI webhook binds 0.0.0.0; it binds 127.0.0.1 unless LICH_GATEWAY_HOST is set, and a non-loopback bind requires LICH_GATEWAY_TOKEN. - docs/architecture/overview.md named 0.8.0 as the current package; point to CHANGELOG instead of a version that goes stale. - wiki: S-11 holes fixed by #163. Part of #133. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01LHQAfXHofy6QkAgmfmJava
) openai, anthropic and ollama carried byte-identical copies of the fetch skeleton (abort signal, request init, do_fetch, body read, success JSON, Retry-After, status mapping, http error) plus is_record / is_abort_like. Move them into src/providers/http.ts; ollama passes its wider overflow regex to to_http_error. failover.ts reuses is_abort_like. Anthropic's explicit 529 check is dropped as redundant (529 >= 500 already maps to rate_limit). No behavior change. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01LHQAfXHofy6QkAgmfmJava
- CLI one-shot and chat pass an abort signal to agent.run. Ctrl+C aborts the one-shot run (exit 1) or the running chat turn (session kept); at the chat prompt it ends chat. A second Ctrl+C while cancelling exits 130. - TUI: Esc cancels a running turn; an aborted run shows "run cancelled". - write_lich_config update writes a temp file and renames it into place, keeping the existing mode, so readers never see a partial config. - gatekeeper, tools, run_tests, skills_search and kanban_audit tests remove the dirs they create under test/.tmp. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01LHQAfXHofy6QkAgmfmJava
…old reply On abort the loop's `final` is the last assistant so far (often the previous turn's reply) and `messages` ends with the cancelled user line. Chat and the TUI now show only the cancel notice and keep history_after_abort(messages), which drops trailing user lines. The config temp file is created with the existing mode. Tests cover a second Ctrl+C (exit 130) and the chat turn after a cancel. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01LHQAfXHofy6QkAgmfmJava
reply_after_abort(outcome) returns `final` only when it comes after the last user line, i.e. this run wrote it. Chat prints it and the TUI shows it before the cancel notice; an earlier turn's reply is still skipped. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01LHQAfXHofy6QkAgmfmJava
Roadmap map lists #133 (P0), #134 (P1), #117 (P2), #144, #148 and #149 with their wiki pages; the kanban skill names the phase children. Supersedes the stale #135. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01LHQAfXHofy6QkAgmfmJava
…fig (#117) Phase 0 + 1 of #117. Discovery is now project .lich/config.json merged over ~/.lich/config.json (shallow, project wins per key). A project providers array replaces the global one and drops the global models unless the project sets its own. The global layer ignores work_dir and session_dir, and its relative plugin paths resolve against ~/.lich/. ~/.config/lich/config.json is read only when ~/.lich/config.json is absent, with a hint to move it; nothing writes there. --config still replaces the whole chain. Bare lich no longer pins an existing config as --config when it skips the wizard, so the merge applies there too. first_run tests use an empty HOME instead of mocking the home lookup. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01LHQAfXHofy6QkAgmfmJava
…n is absent With work_dir = home the global file is the project file; the legacy ~/.config/lich file was then picked as the base under it. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01LHQAfXHofy6QkAgmfmJava
…117) lich init --global writes the starter config to ~/.lich/config.json (never overwrites; no work_dir/session_dir). The setup wizard ends with "Save as the global default?" (default no). Yes writes the answers to ~/.lich/config.json; discovered .lich/plugins entries stay in the project file since they are project paths. The wizard no longer pins its written file as --config, so discovery merges project over global. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01LHQAfXHofy6QkAgmfmJava
…s home With work_dir = home the project file is ~/.lich/config.json, so the plugins-only project write hit "already exists" and dropped plugins. Test also asserts the merged TUI plugins. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01LHQAfXHofy6QkAgmfmJava
…json from home Other projects load that file as the global layer and resolve relative plugin paths against ~/.lich, so .lich/plugins/x would become ~/.lich/.lich/plugins/x. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01LHQAfXHofy6QkAgmfmJava
Phase 2 of #117. ~/.lich/profiles/<name>.json, plus an optional <name>.md used as the system prompt, merges between the global and the project config (global < profile < project). Selection: --profile, then LICH_PROFILE, then a project `profile` key, then the default in ~/.lich/config.json. Profile plugin paths resolve against ~/.lich/profiles; work_dir/session_dir in a profile are ignored. New `lich profile list|show|create|use`: create runs the wizard into the profile file (never overwrites), use sets `profile` in the global file. A requested profile skips the first-run wizard; --profile with --config is an error. File tools now refuse .lich/profiles/. tui/chat/serve/gateway no longer replace every config error with "no model configured"; only that case gets the hint. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01LHQAfXHofy6QkAgmfmJava
…t_dir/disk_usage - work_dir = home: ~/.lich/config.json is the project file, so the profile now merges over it instead of under it. - "profile not found" / "already exists" errors carry no absolute path. - list_dir and disk_usage check the root with assert_file_tool_access, and list_dir skips denied entries, so .lich/profiles is not listed. - Docs: LICH_PROFILE is ignored with --config. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01LHQAfXHofy6QkAgmfmJava
…children The home-dir branch now applies only when ~/.lich/config.json exists, so a legacy ~/.config/lich file stays the base. disk_usage leaves out entries file tools may not read (.lich/profiles, .lich/config.json). Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01LHQAfXHofy6QkAgmfmJava
New entities/lich-config.md: global < profile < project merge, writers, file-tool guard, and config profile vs runtime Profile. Guardrails page and runtime-profile-session updated; index providers line fixed (#165). SCHEMA gains the `config` tag. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01LHQAfXHofy6QkAgmfmJava
There was a problem hiding this comment.
Stale comment
PR #173 — Risk: MEDIUM (wiki-only: 6 files, +66/−6;
wiki/is outside the LOW allowlist of README/CHANGELOG/docs prose, comments, and new test files)Findings: Critical 0 / Warning 0 / Suggestion 2
wiki/entities/lich-config.md:35—write_lich_configwrites.lich/config.json;lich profile createwrites the profile JSON withwriteFileSync(src/cli_profile.ts:101). Fix: scope the sentence to.lich/config.json.wiki/entities/lich-config.md:53—invalid config jsonandconfig not foundstill include the file path and pass througherror_for_mode. Fix: limit the path claim to profile not-found and already-exists.Regressions of settled findings: none
Not reviewed: none
Action: escalated to @Moikapy
Log: 2026-10-05T02:45Z COMMENT,needs-review, MEDIUM wiki page; auto-merge left off@Moikapy The three-dot diff against
ab0f508is the new config-layers page plus index, schema, guardrails, runtime-profile, and log updates. Layer order, home-dir profile-over-global, the file-tool deny,list_dir/disk_usageskips,lich init --global, and the providershttp.tsindex line match that SHA. CI typecheck (20/22), ossuary, wiki_lint, and WIP passed. Auto-merge stays off. Head commit author login isclaude.Sent by Cursor Automation: PR REVIEW
Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01LHQAfXHofy6QkAgmfmJava
There was a problem hiding this comment.
PR #173 — Risk: MEDIUM (wiki-only: 6 files, +66/−6 vs ab0f508; wiki/ is outside the LOW allowlist of README/CHANGELOG/docs prose, comments, and new test files)
Findings: Critical 0 / Warning 0 / Suggestion 0
Regressions of settled findings: none
Not reviewed: none
Action: escalated to @Moikapy
Log: 2026-10-05T03:31Z COMMENT, needs-review already present, MEDIUM wiki page; auto-merge left off. Delta 49574528..0d9590e scopes the writer and error-path sentences. Both prior suggestion threads fully_addressed.
@Moikapy Re-review of 0d9590e. The writers sentence now limits write_lich_config to .lich/config.json and names lich profile create (src/cli_profile.ts:101@ab0f508). The errors sentence limits the no-path claim to profile not found and profile <name> already exists, and notes that config not found and invalid config json still name the file. Both match ab0f508. CI typecheck (20/22), ossuary, wiki_lint, AccessLint, and WIP passed. Auto-merge stays off. Head commit author login is claude.
Sent by Cursor Automation: PR REVIEW


Records the shipped #117 work (#170, #171, #172) in the wiki. Code citations are pinned at
ab0f508.Changes
wiki/entities/lich-config.md:write_lich_config,init --global, the wizard,profile create, andlich mcp, which writes only the project file.entities/lich-tools-and-guardrails.md: file tools now deny.lich/profiles/for reads and writes, andlist_dir/disk_usageskip it.concepts/runtime-profile-session.md: a note that config profiles are not the runtime Profile.index.md: a newlich-configentry. The providers line no longer says the helpers are duplicated, since refactor(providers): share HTTP/error helpers in providers/http.ts #165 moved them intoproviders/http.ts.SCHEMA.md: adds aconfigtag to the subsystem tags.log.md: two lines.Checks
node wiki/scripts/lint.mjs: 0 errors. Its one warning is the existing note about old code-citation SHAs.🤖 Generated with Claude Code
https://claude.ai/code/session_01LHQAfXHofy6QkAgmfmJava
Generated by Claude Code