| 2026-07-09 |

Navi Code TUI: show final answer below tools, not scrolled out of view
...
The assistant answer bubble was created at stream_start (the first event of a
turn), placing it at the TOP of the turn — above the thinking blocks and tool
cards that follow. chat_panel._refresh() calls scroll_end, so the view pinned to
the bottom (tools/thinking) and the answer at the top scrolled out of view.
Users saw tool results, planning, and thinking, but not the final answer.
Fix in chat_model.handle_ws_event (client-only, no protocol/server change):
- stream_start no longer eagerly adds an empty assistant bubble; it resets the
current-assistant pointer so the first stream_delta opens the bubble lazily
at the position where text actually arrives.
- tool_started/tool_call reset the current-assistant pointer so the next
stream_delta opens a fresh bubble BELOW the tool cards — the final answer
lands at the bottom, visible after scroll_end.
- stream_end purges empty assistant/thinking bubbles and resets pointers.
Tests: stream_start creates no empty bubble; final assistant_message renders
after the last tool_call with no empty bubbles; empty bubbles purged on
stream_end. 574 passed, 1 skipped.
Co-Authored-By: Claude <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
1 day ago
|
test(tui): mock backend api so TUI tests are server-independent
...
test_escape_stops_active_stream failed without a live server on :8000:
_startup calls api.create_session/get_session and _refresh_sessions calls
api.list_sessions, but only stop_session was mocked, so _ctx.session_id
stayed None. The whole file silently hit a real server (slow, flaky).
Add an autouse fixture mocking create_session/get_session/list_sessions.
Per-test stop_session mocks stay (own call lists). 571 passed, 0 failed.
Co-Authored-By: Claude <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
1 day ago
|
agent: cwd-aware memory fact filter for bounded autonomy
...
Long-term memory stored context-dependent path facts (e.g. "project_root
→ /home/.../navi-1") as global user facts. search_facts injected them into
any session, so when working in another project the agent was told "the
project root is navi-1" and drifted there.
When scope_boundary_enabled and a session cwd is set, _memory_facts_msg now
drops facts whose value is an absolute path outside the session cwd tree.
Facts are kept when working inside that path (then they are correct), and
non-path/relative facts always pass. Free flight stays reproducible by
toggling the flag off. No facts deleted, extractor untouched.
Co-Authored-By: Claude <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
1 day ago
|

agent: bounded autonomy — scope boundary + observe-vs-act
...
navi_code had unwanted "free flight": an observe request ("look at a
directory") triggered the full Phase 3 plan with milestones + auto-todo,
and goal_anchoring then drove the agent to finish those steps, climbing
into sibling projects and executing milestone docs it found.
Two toggleable, default-off profile flags (on for navi_code):
- scope_boundary_enabled: injects a standing system message keeping the
agent within the literally requested scope; forbids acting on
discovered TODO/roadmap/milestone docs (report only).
- observe_skips_plan_enabled: Phase 1 classifies MODE: observe|act; an
observe request skips Phase 2/3 — no multi-step plan, no auto-todo, no
"execute step by step" prompt. The agent just gathers info and answers.
Independent of force_plan (observe on the first message still skips).
Free flight stays reproducible by flipping both flags off.
Co-Authored-By: Claude <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
1 day ago
|
fix(ws): include session_id/profile_id in session_sync, guard renderer
...
The server sent {"type": "session_sync"} without session_id/profile_id,
crashing the terminal client (render.py did None[:8]). Add the fields to
both session_sync sends and guard the renderer against a missing id.
Co-Authored-By: Claude <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
1 day ago
|
docs(websocket): record deferred WS auth-message hardening
...
Move task #248 (accept the API token as the first WS frame instead of a
?api_token query param, which leaks into access logs) into the websocket
docs as a Future work section with rationale, protocol sketch, and scope.
Eugene Sukhodolskiy
committed
1 day ago
|
navi-code wrapper: fix symlink resolution and bash docstring
...
The wrapper had a Python-style triple-quote docstring at the top, which bash
parses as an empty string + an opening quote — the whole block becomes one
giant 'command name' bash tries to execute, so the script broke before
reaching any logic. Replaced with # comments.
Also resolve symlinks (readlink -f) before computing PROJECT_ROOT so the
wrapper finds the repo/.venv correctly when invoked via a PATH symlink, and
run the client with the venv python + PYTHONPATH=PROJECT_ROOT (no cd, no
pip install -e . required) so the user's cwd is preserved and sent to the
server for per-project path resolution.
Eugene Sukhodolskiy
committed
1 day ago
|
session store: lazy persistence — no empty sessions in DB
...
POST /sessions no longer inserts a DB row. The Session is registered in an
in-memory _pending registry on PgSessionStore and only upserted on the first
save() (first user message / meaningful state change). Empty sessions that
never receive a message never reach the DB and vanish on server restart or
via the hourly pending sweep.
- pg_session_store: _pending dict + lock; create() registers, get() checks
_pending first, save() upserts the sessions row (INSERT ... ON CONFLICT)
and pops _pending so the session_messages FK is satisfied; sweep_pending()
drops abandoned entries; pending_sweep_loop() background task.
- main.py: start/cancel pending_sweep_loop in lifespan.
- tests: 7 new tests for create/get/save/list/sweep semantics; updated
existing save() test comments for the upsert.
Eugene Sukhodolskiy
committed
1 day ago
|
| 2026-07-08 |
profiles: add gemma4:12b-it-qat-128k as top-priority model
...
New local QAT model added at the head of the model priority list across
all profiles, so it is preferred first with cloud fallback.
Eugene Sukhodolskiy
committed
2 days ago
|
Add MIT license
...
Project is going open source under a permissive MIT license.
- LICENSE: MIT, Copyright (c) 2026 Eugene Sukhodolskiy
- pyproject.toml: license field, OSI classifier, allow-direct-references for the git dependency
- README.md: license pointer
- .gitignore: ignore .env, venv, build artifacts, local db/workspace files
Eugene Sukhodolskiy
committed
2 days ago
|
| 2026-06-26 |
Remove CLAUDE.md from repo and add to .gitignore
...
CLAUDE.md is now local-only and will not be tracked by git.
Co-Authored-By: Claude <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
14 days ago
|
Navi Code: stop via Esc + project cwd propagation
...
- TUI: Esc stops active stream cooperatively via POST /sessions/{id}/stop
- TUI: render stream_stopped as status message
- CLI/WebSocket: send shell cwd in client->server message field
- Orchestrator stores cwd in session.session_metadata
- ContextBuilder injects [Working directory] into LLM context
- Agent sets current_working_directory ContextVar per turn
- tools/base: ToolContext gains cwd field
- filesystem/terminal/code_exec resolve relative paths against session cwd
- Add bin/navi-code wrapper for PATH symlink; document in README.md
- Update docs/websocket.md and tests
Full pytest: 544 passed, 1 skipped.
Co-Authored-By: Claude <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
14 days ago
|
compressor: structured summaries, profile-aware compression, adaptive keep_recent
...
- Replace free-form summary with strict Markdown template (Goal, Active Files,
Decisions, Completed Work, Pending Work/Todo, Errors, Key Values).
- Keep filesystem/code_exec/terminal tool results and messages with
is_compression_critical=True verbatim during compression instead of 300-char truncation.
- Make compression profile-aware: AgentProfile gains compression_keep_recent,
compression_max_tokens, compression_prompt_file. navi_code uses dedicated
compression prompt and larger keep_recent/max_tokens.
- Adaptive partition_messages(): important turns (user corrections, errors,
critical tools) survive longer; filler/social turns compress sooner.
- Increase default context_summary_max_tokens from 3000 to 4000.
- Propagate active profile changes to ContextCompressor and SubAgentRunner.
Co-Authored-By: Claude <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
14 days ago
|
agent: skip planning for casual greetings + strengthen DIRECT shortcut in Phase 1
...
- Add fast _is_casual_message heuristic in navi/core/agent.py. Greetings and
social chat (e.g. 'привет', 'как дела', 'hi', 'thanks') bypass planning even
on the first session message, unless planning_mandatory is enabled.
- Strengthen Phase 1 planning prompt in navi/core/planning.py: explicitly
require DIRECT output for greetings, simple questions, and one-step
instructions.
- Fix broken ContextCompressed import in navi/core/compressor.py.
- Add unit tests covering the new heuristic and DIRECT prompt.
Co-Authored-By: Claude <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
14 days ago
|
Navi Code TUI: fix input box layout, command palette duplicate IDs, status renderer, and WS input loop
...
- clients/terminal/tui/widgets/input_box.py: switch Horizontal to Vertical with width: 100% for Input so it renders and accepts input in real terminals; add refresh on Input.Changed.
- clients/terminal/tui/screens/command_palette.py: remove fixed ListItem IDs to avoid DuplicateIds on fast filter.
- clients/terminal/tui/chat_model.py + renderers/status.py + widgets/chat_panel.py: render backend status events as dim system messages instead of raw dicts.
- clients/terminal/tui/ws_bridge.py: start NaviWebSocketClient.input_loop so enqueued user messages are actually sent to the backend.
- clients/terminal/tui/tui_app.py: focus InputBox synchronously in on_mount so typing works immediately.
- tests/clients/test_tui_app.py: regression test for visible input text.
Co-Authored-By: Claude <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
14 days ago
|
| 2026-06-24 |
Fix MCP names and profile API format consistency
...
- Replace stale mcp__navi_web__* / mcp__navi_3d__* names with canonical
mcp__navi-web__* / mcp__navi-3d__* across prompts and key_tools.
- Update /agents/profiles and /admin/profiles endpoints to expose
tools.agent / tools.subagent instead of deprecated enabled_tools fields.
- Update docs/mechanics.md to reference the new tools structure.
- Archive stale docs/visual.html.
Co-Authored-By: Claude <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
16 days ago
|
docs: update docs for tools.agent/tools.subagent and Navi Code TUI
...
- profiles.md: document tools.agent/tools.subagent structure, deprecate enabled_tools
- tools.md: move web tools to MCP section, fix mcp__navi-web__* names, add create_mcp_server/test_mcp_tool/mcp_status/recall tools
- api.md: update /agents/profiles and /admin/profiles/{id} response schemas, fix MCP examples
- navi_code.md: correct navi_code tool list (MCP disabled)
- navi_code_cli.md: add /thinking, /compact, correct TUI layout
- index.md: add navi_code, terminal client, pydantic-settings
- testing.md: refresh test directory layout, replace stale coverage roadmap
- agent.md: mention tools.agent/tools.subagent in loop
Co-Authored-By: Claude <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
16 days ago
|
docs: update docs for tools.agent/tools.subagent and Navi Code TUI
...
- profiles.md: document tools.agent/tools.subagent structure, deprecate enabled_tools
- tools.md: move web tools to MCP section, fix mcp__navi-web__* names, add create_mcp_server/test_mcp_tool/mcp_status/recall tools
- api.md: update /agents/profiles and /admin/profiles/{id} response schemas, fix MCP examples
- navi_code.md: correct navi_code tool list (MCP disabled)
- navi_code_cli.md: add /thinking, /compact, correct TUI layout
- index.md: add navi_code, terminal client, pydantic-settings
- testing.md: refresh test directory layout, replace stale coverage roadmap
- agent.md: mention tools.agent/tools.subagent in loop
- archive obsolete eval_system_design.md, plan_navi_code.md, plan_navi_code_tui.md
Co-Authored-By: Claude <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
16 days ago
|
Update Navi Code profile: config, prompts, docs, and env example
...
- Sync navi_code profile tools with current codebase (memory, schedule_recall, manage_recall, switch_profile, list_profiles)
- Remove image_view and MCP tools from navi_code; keep local terminal focus
- Update system prompt and persona for terminal-first coding assistant
- Update docs/navi_code.md, docs/profiles.md, docs/config.md for new tool set
- Refresh .env.navi_code.example with current config variables
- Remove stale CLI prototype directories (cli/, navi_code_cli/)
Eugene Sukhodolskiy
committed
16 days ago
|
Navi Code TUI: review fixes for Phase 5
...
- Fix raw CLI session API fields (session_id/name/preview)
- Add --mouse/--no-mouse flags and persistent TUI settings coercion
- Make attach_session/apply_theme public, add ChatPanel.clear()
- Deduplicate session selection handlers and editor error handling
- Update docs and tests
Eugene Sukhodolskiy
committed
16 days ago
|
Navi Code TUI: Phase 5.2 — SessionsPanel, /export, integration tests
...
- Add right-side SessionsPanel widget (DataTable) listing server sessions.
- Wire SessionsPanel into TUI layout and session selection flow.
- Add SessionSelected / SessionListUpdated events and refresh logic.
- Implement /export slash command: markdown rendering + $EDITOR.
- Update /new, /sessions, /switch, /profile to use session_id/name/preview.
- Add integration tests for SessionsPanel and /export; update layout test.
- Update docs/navi_code_cli.md with new panel and command.
Co-Authored-By: Claude <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
16 days ago
|
| 2026-06-23 |
Navi Code TUI: Phase 5.1 — config, mouse, themes, status
...
- Add TuiSettings persisted in ~/.navi_code/tui.json (theme, mouse, scroll_speed, diff_style, keybinds).
- TUI applies saved theme/mouse on startup; CLI gets --theme override.
- Add /themes picker with live preview and /mouse toggle command.
- Extend StatusPanel with backend URL, current theme, tokens/iter placeholders.
- Fix TuiContext.app() to use Textual active_app ContextVar.
- Add unit tests for settings, themes, and status panel.
513 passed, 1 skipped. Ruff clean.
Signed-off-by: Eugene Sukhodolskiy <eugene.sukhodolskiy@gmail.com>
Eugene Sukhodolskiy
committed
16 days ago
|
Navi Code TUI: fix Phase 4 review critical/medium issues
...
- PermissionEngine: always-deny returns None via check(); is_always_deny() exposed for explicit rejection; default rules for code_exec/ssh_exec/shell; extract_target() made public.
- ShellRunner: set ShellResult.truncated when output is actually truncated.
- File refs: restrict paths to base_dir/home, block sensitive files/dirs, skip binary, support glob brackets, shared guess_language.
- Permission dialog: deny now renders synthetic tool_call before stopping; shell ! commands require permission with always-allow/deny persistence.
- Tests: add permission tests, fix file_refs/shell tests, add __init__.py to fix pytest name collisions, update websocket integration for AgentSessionOrchestrator.
504 passed, 1 skipped. Ruff clean.
Signed-off-by: Eugene Sukhodolskiy <eugene.sukhodolskiy@gmail.com>
Eugene Sukhodolskiy
committed
16 days ago
|
Navi Code TUI: complete Phase 4
...
- @ file references with glob/dir support and size limits
- ! shell commands with timeout and output truncation
- inline permission dialog for destructive tool calls
- diff and artifact renderers with theme-aware highlighting
Tests: 40 client tests passing
Eugene Sukhodolskiy
committed
17 days ago
|
Navi Code TUI: command palette and themed markdown
...
- Add CommandPaletteScreen modal with fuzzy filtering and keyboard navigation.
- Bind Ctrl+P to push the palette; selected commands execute via registry.
- Make MarkdownRenderer theme-aware: headings, inline code, links, and code blocks use gnexus palette.
- Pick dracula/github-light code theme based on active theme brightness.
Co-Authored-By: Claude <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
17 days ago
|
Navi Code TUI: apply gnexus theme to widgets and renderers
...
- Register Navi themes as Textual themes so $tui-* CSS variables resolve.
- Update ChatPanel, StatusPanel, InputBox to use palette colors.
- Update all content renderers to draw from the active theme.
- Add set_active_theme/get_active_theme helpers for runtime color access.
Co-Authored-By: Claude <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
17 days ago
|
Navi Code TUI: extend theme with selection and link colors
...
Add selection (magenta) and link (teal) for cursor line, active selection and URLs.
Tests still green.
Co-Authored-By: Claude <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
17 days ago
|
Navi Code TUI: add gnexus-ui-kit color theme support
...
- Extract exact gnexus-ui-kit cyberpunk palette from
webclient/vendor/gnexus-ui-kit/src/scss/_palette-colors.scss.
- Add clients/terminal/tui/themes.py with Theme dataclass, ThemeRegistry,
and gnexus-dark / gnexus-light themes.
- Wire theme into NaviCodeTui via _apply_theme() on mount; default is
gnexus-dark.
Tests: 463 passed, 1 skipped (excluded unrelated websocket test).
Co-Authored-By: Claude <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
17 days ago
|
Navi Code: Phase 3 — Textual TUI skeleton (OpenCode-style)
...
- Add clients/terminal/tui package with micro-architecture:
- events, context, chat_model, ws_bridge, permissions engine.
- widgets: ChatPanel, StatusPanel, InputBox.
- renderers: user/assistant messages, thinking, tool calls, errors,
markdown, plain — registry-based and extensible.
- slash commands: /help, /new, /sessions, /switch, /profile, /thinking,
/compact, /quit — registry-based and extensible.
- Wire navi-code to launch TUI by default; keep click-CLI via --raw.
- Add textual>=0.70 dependency.
- Add TUI smoke tests via Textual Pilot.
- Add docs/plan_navi_code_tui.md with full Phase 4/5 roadmap.
Tests: 463 passed, 1 skipped (excluded unrelated websocket test).
Co-Authored-By: Claude <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
17 days ago
|
Docs: actualize navi_code tool lists and key_tools
...
- docs/navi_code.md and docs/profiles.md now correctly list native tools,
MCP navi-web tools, and excluded tools.
- image_view is documented as enabled for the agent (loads and describes
images for the model, not shown to the user).
- web_search/http_request are documented as MCP navi-web tools, not native
disabled tools.
- navi/profiles/navi_code/config.json: updated full_description.key_tools to
match actual resolved tool names.
Tests: 459 passed, 1 skipped.
Co-Authored-By: Claude <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
17 days ago
|