Commit Graph

49 Commits

Author SHA1 Message Date
Dhanji R. Prasanna
14112ff92e Remove client-side plan approval interception
Let approval input flow through the LLM instead of being
short-circuited in the REPL. The LLM calls plan_approve
itself, which is cleaner (single input path) and more
flexible (no hardcoded misspelling list).
2026-02-06 20:16:11 +11:00
Dhanji R. Prasanna
31bdcb651b feat(cli): add multiline input support with Alt+Enter
- Enable custom-bindings feature in rustyline
- Bind Alt+Enter to insert newlines in interactive and accumulative modes
- Update calculate_visual_lines() to handle embedded newlines correctly
- Add tests for multiline visual line calculation

Note: Shift+Enter is not distinguishable in standard terminals, so Alt+Enter
is used as the multiline input trigger.
2026-02-06 14:09:12 +11:00
Dhanji R. Prasanna
bcd50190c6 Add explicit [plan mode] indicator to interactive prompt
- Change plan mode prompt from ' >> ' to ' [plan mode] >> ' for clarity
- Add magenta syntax highlighting for [plan mode] text in prompt
- Add tests for prompt highlighting behavior
2026-02-06 11:31:07 +11:00
Dhanji R. Prasanna
d978032044 Remove redundant AGENTS.md heading from startup output
The loaded status line (✓ AGENTS.md ✓ Memory) already indicates that
AGENTS.md was loaded, so the separate '>> AGENTS.md - Machine Instructions'
heading line was redundant.

- Remove print_project_heading() function from display.rs
- Remove extract_project_heading call from interactive.rs
- Clean up unused imports
2026-02-05 21:38:47 +11:00
Dhanji R. Prasanna
19162b1fe6 Exit plan mode when plan is completed or blocked
When a plan reaches a terminal state (all items done or blocked) in
interactive mode, automatically exit plan mode and return to normal
prompt.

Changes:
- Add Agent::is_plan_terminal() method to check if plan is complete
- Add check_and_exit_plan_mode_if_terminal() helper in interactive.rs
- Call the helper after each execute_user_input() to detect completion

Fixes issue where plan mode prompt ' >> ' persisted after plan completion.
2026-02-05 20:31:24 +11:00
Dhanji R. Prasanna
b2fbcf33d0 Fix plan approval gate and add "Create a plan:" prefix for first message
- Fix build warnings: add #[allow(dead_code)] to unused deserialization fields
- Fix plan approval gate bug: block file changes when no plan exists (not just
  when plan exists but is unapproved)
- Add "Create a plan: " prefix to first user message in plan mode
- Add prepare_plan_mode_input() helper function for testability
- Reset is_first_plan_message flag when entering plan mode via /plan command
- Add tests for approval gate (no plan + no changes, no plan + changes)
- Add tests for prepare_plan_mode_input (happy, negative, boundary cases)
2026-02-05 19:43:38 +11:00
Dhanji R. Prasanna
39e586982c feat: Externalize research tool as embedded skill
Replaces the built-in research/research_status tools with a portable
skill-based approach:

- Add embedded skills infrastructure (skills compiled into binary)
- Add repo-local skills/ directory support (highest priority)
- Create research skill with SKILL.md and g3-research shell script
- Script extraction to .g3/bin/ with version tracking
- Filesystem-based handoff via .g3/research/<id>/status.json
- Remove PendingResearchManager and all research tool code
- Update system prompt to reference skill instead of tool

Benefits:
- No special tool infrastructure needed (just shell + read_file)
- Context-efficient (reports stay on disk until needed)
- Crash-resilient (state persisted to filesystem)
- Portable (skill can be overridden per-workspace)

Breaking change: research tool calls now return a deprecation message
pointing to the research skill.
2026-02-05 13:23:26 +11:00
Dhanji R. Prasanna
6228001bfc Remove automatic session resume suggestion on startup
- Remove the interactive prompt that asked users to resume in-progress sessions
- Remove unused new_session parameter from run_interactive()
- Remove unused info_inline() function from G3Status
- Explicit --resume <session_id> flag still works
2026-02-05 12:40:27 +11:00
Dhanji R. Prasanna
25ad198b83 Sync agent plan mode state on CLI startup
CLI starts in plan mode by default (when not in agent mode), but was not
calling agent.set_plan_mode(true) at initialization. This meant the gate
check would not run until the user explicitly entered plan mode via /plan.
2026-02-05 11:47:38 +11:00
Dhanji R. Prasanna
0f919237ea Make plan approval gate only active in plan mode
- Add in_plan_mode flag to Agent struct
- Add set_plan_mode() and is_plan_mode() methods
- Gate check now only runs when in_plan_mode is true
- CLI calls set_plan_mode(true) on /plan command and EnterPlanMode
- CLI calls set_plan_mode(false) on approval and CTRL-D exit
- Update integration test to enable plan mode
- Fix test YAML to use Vec<Check> for negative/boundary checks
2026-02-05 11:41:52 +11:00
Dhanji R. Prasanna
f8448e5622 feat: Plan Mode interactive flow with approval shortcuts
- Start g3 in plan mode with ' >>' prompt and welcome message
- Add is_approval_input() to detect 'approve', 'a', 'yes', etc. and misspellings
- Allow trailing punctuation (!, ., ,) on approval words
- Call plan_approve tool directly without LLM when approval detected
- Add synthetic assistant message after approval for LLM context
- Exit plan mode after successful approval, return to 'g3>' prompt
- CTRL-D in plan mode exits plan mode first, then exits g3
- /plan command enters plan mode and shows welcome message
- Agent mode (--agent) does not start in plan mode
- Add CommandResult enum to signal plan mode entry from commands
2026-02-02 16:59:52 +11:00
Dhanji R. Prasanna
f93d05f444 Add real-time research completion notifications
When background research completes, g3 now immediately prints a status
message instead of waiting for the next user interaction:

- Added ResearchCompletionNotification and broadcast channel to
  PendingResearchManager for push-based notifications
- Added spawn_research_notification_handler() in interactive mode that
  listens for completions in a background task
- When idle (at prompt): clears line, prints status, reprints prompt
- When busy (processing): prints status inline (interleaving is fine)
- Added G3Status::research_complete() for consistent formatting
- Added enable_research_notifications() method to Agent

Output format: "g3: 1 research report ... [done]"
2026-01-30 13:35:35 +11:00
Dhanji R. Prasanna
b252ff443d Merge sessions/interactive/9681cb67 2026-01-30 13:01:00 +11:00
Dhanji R. Prasanna
5ab1598e03 feat: async research tool - runs in background, returns immediately
The research tool now spawns the scout agent in a background tokio task
and returns immediately with a research_id placeholder. This allows the
agent to continue working while research runs (30-120 seconds).

Key changes:
- New PendingResearchManager for tracking async research tasks
- research tool returns immediately with placeholder containing research_id
- research_status tool to check progress of pending research
- Auto-injection of completed research at natural break points:
  - Start of each tool iteration (before LLM call)
  - Before prompting user in interactive mode
- /research CLI command to list all research tasks
- Updated system prompt to explain async behavior

The agent can:
- Continue with other work while research runs
- Check status with research_status tool
- Yield turn to user if results are critical before continuing
2026-01-30 13:00:02 +11:00
Dhanji R. Prasanna
4e1694248f Add input formatting for interactive CLI
When users type prompts in interactive mode, the input is now
reformatted in place with enhanced highlighting:

- ALL CAPS words (2+ chars) become bold green (e.g., FIX, BUG, HTTP2)
- Quoted text ("..." or ...) becomes cyan
- Standard markdown formatting is also supported

New module: input_formatter.rs with 10 unit tests
Integrated into interactive.rs for both single-line and multiline input
2026-01-30 12:03:36 +11:00
Dhanji R. Prasanna
5c1e0630b5 Merge sessions/interactive/664ee473 2026-01-29 11:14:28 +11:00
Dhanji R. Prasanna
7bfb9efa19 Remove automatic README loading from context window
README.md is no longer auto-loaded into the LLM context at startup.
This saves ~4,600 tokens per session while AGENTS.md and memory.md
still provide all critical information for code tasks.

Changes:
- Delete read_project_readme() function
- Remove readme_content parameter from combine_project_content()
- Rename extract_readme_heading() -> extract_project_heading()
- Rename Agent constructors: *_with_readme_* -> *_with_project_context_*
- Update context preservation to only check for Agent Configuration
- Remove has_readme field from LoadedContent
- Update all tests to use new markers and function names

The LLM can still read README.md on-demand via read_file when needed.
2026-01-29 11:07:41 +11:00
Dhanji R. Prasanna
5ea43d7b39 Add --project CLI flag for loading projects at startup
Adds a new --project <PATH> flag that loads project files (brief.md,
contacts.yaml, status.md) at startup, similar to the /project command
but WITHOUT auto-executing the project status prompt.

Changes:
- Add --project flag to cli_args.rs
- Add load_and_validate_project() helper in project.rs (shared by both
  --project flag and /project command)
- Modify run_interactive() to accept optional initial_project parameter
- Wire up --project in lib.rs to load project before interactive mode
- Refactor /project command to use shared helper (reduces duplication)
- Add 4 new tests for load_and_validate_project()
2026-01-29 11:06:08 +11:00
Dhanji R. Prasanna
d6a986ce0f refactor(cli): extract execute_user_input() to eliminate duplication
Both multiline and single-line input paths in interactive.rs had identical
code for:
- Template processing (process_template)
- Task execution (execute_task_with_retry)
- Auto-memory reminder with error handling

Extracted to a single execute_user_input() helper function that handles
all three steps. This eliminates code-path aliasing where the two paths
could drift over time.

File reduced from 401 to 393 lines (-2%).
All 106 g3-cli tests pass.

Agent: fowler
2026-01-26 15:59:55 +11:00
Dhanji R. Prasanna
57f04a77aa Add template expansion to interactive prompts
Apply {{today}} and other template variables to user input in:
- Interactive mode (single and multiline)
- Accumulative mode requirements
2026-01-26 15:43:39 +11:00
Dhanji R. Prasanna
067c69723b fix(cli): use plain text prompt without ANSI colors
ANSI color codes in rustyline prompts cause various issues:
- \x01...\x02 markers break cursor movement
- Separate prefix printing causes gaps or disappearing text

Simplified to plain text prompt: 'butler | finances> '
This ensures reliable cursor positioning and tab completion.
2026-01-22 10:27:27 +05:30
Dhanji R. Prasanna
cb1f99c41c Revert "fix(cli): use '> ' as readline prompt when project active"
This reverts commit 4d9399f737.
2026-01-22 10:24:21 +05:30
Dhanji R. Prasanna
4d9399f737 fix(cli): use '> ' as readline prompt when project active
Previously used empty string as readline prompt after printing colored
prefix, which caused cursor positioning issues (large gap between
project name and cursor).

Now the prefix contains 'butler | finances' (colored) and readline
gets '> ' as its prompt, so cursor appears immediately after '> '.
2026-01-22 10:18:15 +05:30
Dhanji R. Prasanna
28dd60d4fc fix(cli): separate colored prefix from readline prompt
Rustyline's \x01...\x02 markers for ANSI codes didn't work correctly,
causing cursor positioning issues and breaking line editing.

New approach: build_prompt() returns (prefix, prompt) tuple where:
- prefix: colored text printed before readline (contains ANSI codes)
- prompt: plain text passed to readline (no ANSI codes)

This ensures rustyline correctly calculates line length while still
showing the colored project name.
2026-01-22 09:59:52 +05:30
Dhanji R. Prasanna
be35fa2a7f fix(cli): wrap ANSI codes in prompt for rustyline compatibility
Rustyline needs ANSI escape codes wrapped in \x01...\x02 markers
to correctly calculate visible prompt length. Without this, tab
completion breaks because rustyline miscalculates cursor position.
2026-01-22 08:30:30 +05:30
Dhanji R. Prasanna
3001df3b1a style(cli): simplify project prompt format
Change from: butler |[finances]>
Change to:   butler | finances>
2026-01-22 08:15:18 +05:30
Dhanji R. Prasanna
022f5c70a6 feat(cli): show active project name in interactive prompt
When a project is loaded via /project, the prompt now shows:
  agent_name |[project_name]>

where the |[project_name]> part is displayed in blue.

Examples:
- Default: g3>
- With project: g3 |[myapp]>
- Agent mode: butler>
- Agent + project: butler |[myapp]>

The prompt automatically resets when /unproject is called.

Added build_prompt() function with 7 unit tests covering all prompt states.
2026-01-22 07:24:00 +05:30
Dhanji R. Prasanna
feb7c3e40d Add /project and /unproject commands for project-specific context
- Add Project struct in crates/g3-cli/src/project.rs with file loading logic
- Load brief.md, contacts.yaml, status.md from project path
- Load projects.md from workspace root for cross-project context
- Project content appended to system message (survives compaction/dehydration)
- /project <path> loads project and auto-submits prompt asking about state
- /unproject clears project content and resets context
- Add set_project_content(), clear_project_content(), has_project_content() to Agent
- Add new_for_test_with_readme() for testing with custom README content
- Add 6 unit tests for Project struct
- Add 9 integration tests for project context behavior
2026-01-21 14:53:30 +05:30
Dhanji R. Prasanna
dec22f5e58 refactor(g3-cli): extract commands module and fix test organization
- Extract handle_command() from interactive.rs to new commands.rs module
  (320 lines, 15 match arms for /help, /compact, /thinnify, etc.)
- Fix orphaned tests in completion.rs that were outside mod tests block
- Add #[allow(dead_code)] to with_include_prompt_filename() (used in tests)
- interactive.rs reduced from 595 to 290 lines

Agent: fowler
2026-01-20 14:30:50 +05:30
Dhanji R. Prasanna
710c54105b refactor(cli): extract display utilities to eliminate code duplication
Created display.rs module with shared display functions:
- format_workspace_path() / print_workspace_path()
- LoadedContent struct for tracking loaded project files
- print_loaded_status() for status line display
- print_project_heading() for README heading

Updated interactive.rs and agent_mode.rs to use the new module,
eliminating duplicated workspace path formatting and loaded items
status line logic.

Results:
- interactive.rs: 641 → 595 lines (-46)
- agent_mode.rs: 312 → 288 lines (-24)
- New display.rs: 197 lines with 5 unit tests

Agent: fowler
2026-01-20 14:22:46 +05:30
Dhanji R. Prasanna
dd3db0227d Add tab completion for commands and file paths
Implement tab completion in interactive mode using rustyline:

- Command completion: /<TAB> shows all commands, /com<TAB> -> /compact
- File path completion: /run <TAB> completes file/directory paths
- Supports tilde expansion for home directory

Architecture is extensible for future semantic completions:
- /resume <TAB> -> session IDs (Phase 2)
- /rehydrate <TAB> -> fragment IDs (Phase 2)

New module: completion.rs with G3Helper struct implementing
rustyline's Completer trait.
2026-01-20 10:57:33 +05:30
Dhanji R. Prasanna
4db2150386 Change /run status message from 'running' to 'loading' 2026-01-20 10:34:06 +05:30
Dhanji R. Prasanna
6873f980a1 Use G3Status for /run command output
Change from custom emoji format to consistent g3: status message:
'g3: running <path> ... [done]'
2026-01-20 10:27:26 +05:30
Dhanji R. Prasanna
f24ea333f1 Add /run command to execute prompts from files
New interactive command: /run <file-path>
- Reads the specified file and executes its content as a prompt
- Supports tilde expansion for home directory paths
- Behaves exactly like pasting the file content into the g3> prompt
- Shows helpful error messages for missing files or empty content
2026-01-20 10:23:24 +05:30
Dhanji R. Prasanna
182f5f98fe Centralize g3 status message formatting
Extract a new g3_status module in g3-cli that provides consistent formatting
for all 'g3:' prefixed system status messages.

Key changes:
- Add G3Status struct with methods for progress, done, failed, error, etc.
- Add Status enum with Done, Failed, Error, Resolved, Insufficient, NoChanges
- Add ThinResult struct in g3-core for semantic thinning data
- Update UiWriter trait with print_thin_result() method
- Refactor context thinning to return ThinResult instead of formatted strings
- Update all callers to use the new centralized formatting
- Session resume/decline messages now use G3Status
- Compaction status messages now use G3Status

This maintains clean separation of concerns: g3-core emits semantic data,
g3-cli handles all terminal formatting and colors.
2026-01-20 09:50:55 +05:30
Dhanji R. Prasanna
07bff7691a Make /resume session prompt more compact
Output is now a single line:
  Session number to resume (Enter to cancel): 1 ... resuming scout_88871653e8e5f4f7 [done]

- Session ID displayed in cyan
- [done] displayed in bold green
- [error: ...] displayed in bold red on failure
- Added print_inline() to SimpleOutput for inline prompts
2026-01-18 18:41:24 +05:30
Dhanji R. Prasanna
8dad00bdd0 Colorize session name in cyan in continuation prompt 2026-01-17 15:58:46 +05:30
Dhanji R. Prasanna
0d6a66a252 Compress session continuation prompt to single line
- Combine session info and resume prompt on one line
- Show result inline after user input (y/n)
- Green '... resuming ... [done]' on successful resume
- Dark grey '... starting fresh' when declining
- Yellow '... failed: <error>' on restore failure
2026-01-17 15:56:05 +05:30
Dhanji R. Prasanna
5622e5b21e refactor(cli): show only loaded items in startup status line
Changes the startup status line to only display items that were
actually loaded, instead of showing dots for missing items.

Before: "   · README  · AGENTS.md  ✓ Memory"
After:  "   ✓ Memory"

Also adds include prompt to the status line when specified:
"   ✓ prompt.md  ✓ Memory"

The order matches the load order: README → AGENTS.md → include prompt → Memory
2026-01-17 15:35:37 +05:30
Dhanji R. Prasanna
0e33465342 Add print_g3_progress/print_g3_status methods for consistent status messages 2026-01-16 20:28:24 +05:30
Dhanji R. Prasanna
95f89d3f8e Simplify compaction status messages 2026-01-16 20:26:35 +05:30
Dhanji R. Prasanna
1f6a5671b2 Use agent name as prompt in --agent --chat mode (e.g., "butler>")
Changed run_interactive() parameter from bool to Option<&str> agent_name.
When agent_name is Some, use it as the prompt instead of "g3>".
2026-01-16 13:58:45 +05:30
Dhanji R. Prasanna
2e6bef4b24 Auto-memory: call once on exit for --agent --chat, per-turn for single-shot
When running g3 --agent <name> --chat:
- Skip per-turn memory checkpoint calls (too onerous)
- Call memory checkpoint once when exiting (Ctrl-D)

When running g3 --agent <name> (single-shot):
- Preserve existing behavior: call memory checkpoint after each turn

This keeps the auto-memory feature useful without being intrusive
in interactive agent sessions.
2026-01-16 13:35:40 +05:30
Dhanji R. Prasanna
6068249827 Simplify --agent --chat startup: minimal output, no session resume
When running g3 --agent <name> --chat, the output is now minimal:
- Workspace path (-> ~/path)
- Status line (README/AGENTS.md/Memory)
- Context progress bar
- Prompt (g3>)

Skipped in this mode:
- Session resume prompts
- "agent mode | name (source)" header
- "g3 programming agent" welcome
- Provider info display
- Language guidance messages

Added from_agent_mode parameter to run_interactive() to control
whether verbose welcome and session resume are shown.
2026-01-16 13:31:10 +05:30
Dhanji R. Prasanna
996dc357b4 Skip session resume prompt when --new-session flag is passed
When users explicitly pass --new-session, they want a fresh session.
Previously g3 would still prompt to resume an existing session.
Now the resume check is skipped entirely when the flag is set.
2026-01-14 08:54:35 +05:30
Dhanji R. Prasanna
389ed6a554 Compact project info display in interactive mode
Before:
  🤖 AGENTS.md configuration loaded
  📚 detected: G3 - AI Coding Agent
  🧠 Project memory loaded
  workspace: /Users/dhanji/src/g3

After:
  >> G3 - AI Coding Agent
     ✓ README | ✓ AGENTS.md | ✓ Memory
  -> ~/src/g3
2026-01-13 14:32:24 +05:30
Dhanji R. Prasanna
af3aa840db Compress session continuation UI prompt 2026-01-13 14:29:54 +05:30
Dhanji R. Prasanna
f10374c925 Remove machine mode entirely from g3
- Delete machine_ui_writer.rs
- Remove --machine CLI flag from cli_args.rs
- Remove run_machine_mode(), run_interactive_machine(), run_autonomous_machine() functions
- Remove handle_machine_command() function
- Simplify OutputMode enum to just use SimpleOutput directly
- Simplify SimpleOutput struct (remove machine_mode field)
- Remove machine_mode parameter from setup_workspace_directory()
- Remove test_machine_option_accepted test
- Disable ACD by default in agent_mode (requires --acd flag)
- Change 'memory checkpoint' message formatting
- Remove dehydration status message
2026-01-12 06:01:31 +05:30
Dhanji R. Prasanna
b9cdb99557 refactor(g3-cli): break lib.rs into focused modules
Extract 7 modules from the 2966-line lib.rs:
- cli_args.rs (133 lines): CLI argument parsing with clap
- autonomous.rs (785 lines): coach-player feedback loop
- agent_mode.rs (284 lines): specialized agent execution
- accumulative.rs (343 lines): iterative requirements mode
- interactive.rs (851 lines): REPL with command handling
- task_execution.rs (212 lines): unified retry logic
- utils.rs (91 lines): display and workspace helpers

Key improvements:
- lib.rs reduced from 2966 to 415 lines (86% reduction)
- Eliminated duplicate retry logic between execute_task and execute_task_machine
- Each module has a single responsibility
- Easier to reason about and maintain

Agent: fowler
2026-01-12 05:35:08 +05:30