Request Lifecycle
This is the central execution flow for OTerminus. The order is deliberate: OTerminus detects direct shell commands before applying natural-language ambiguity heuristics. Only non-direct, natural-language requests are checked for ambiguity before capability routing and planner calls.
Before request handling begins, OTerminus handles command namespaces that are explicitly outside
the request lifecycle. version, completion, and doctor exit through their own paths. The
oterminus config namespace also exits before runtime request setup; config path, show, init,
get, set, reset, validate, and edit do not construct the validator, executor, planner, audit
logger, or history store, do not run startup readiness checks, do not contact Ollama, and do not
start the REPL. config set writes only the validated user config JSON through the atomic config
save path. config reset removes only supported safe persisted keys through the same validated save
path. Neither command edits .env, exported environment variables, or shell startup files.
For a bare interactive launch, OTerminus inspects persistent config state before constructing
runtime services. If stdin is interactive and the config file is missing, it offers first-run
onboarding. Accepting runs the wizard, optionally selects an installed Ollama model, saves after a
summary confirmation, and then reloads effective config before the validator, executor, audit
logger, history store, and REPL are created. Declining saves safe defaults with
onboarding_completed: true and continues. Onboarding is not offered for one-shot requests,
--dry-run, --explain, doctor, version, completion, config commands, existing config
files, legacy config files, or non-interactive stdin.
For normal request handling, OTerminus resolves runtime configuration into AppConfig.
Resolution applies exported environment variables, current-directory .env, validated user config,
and built-in defaults in that order for supported settings. The persistent user config is a
schema-versioned JSON preference file; invalid JSON, unknown fields, unsupported schema versions, or
invalid security-relevant values fail startup with a bounded configuration error instead of being
silently ignored. OTERMINUS_CONFIG_PATH and OTERMINUS_ALLOW_DANGEROUS remain environment/.env
only. Terminal color mode is resolved as configuration, and one terminal style object is threaded
through OTerminus-owned preview, prompt, lifecycle, discovery/help, and diagnostic rendering.
NO_COLOR is applied at render time. ANSI styling must not enter audit events, history records,
subprocess stdout/stderr or their metadata, shell completion scripts, generated references, JSON
output, or other machine-oriented command output.
Stage details
1) User input
Input can be:
- the explicit diagnostics command (
doctor), which checks Ollama readiness, installed-model count, and model-selection consistency, then exits outside the normal request planning/execution lifecycle without sending planner or schema-probe prompts; active schema diagnostics are only run byoterminus models test - bare interactive launch (
oterminus), which may offer onboarding before REPL services are constructed when no config file exists - natural language (
"find large files here") - direct command (
"ls -lah")
2) Direct command detection
Direct command detection runs before ambiguity detection. If input already looks like a supported
command family invocation, OTerminus skips LLM planning and builds a direct proposal. Examples such
as chmod +x run.sh and rm -rf build are not intercepted as ambiguous natural language.
Direct proposals still continue through proposal parsing, structured rendering when available,
validation, policy checks, preview, and confirmation policy in execute mode. In --dry-run or
--explain one-shot mode, direct proposals do not require Ollama if direct detection succeeds.
Direct input is parsed into a structured proposal when the typed schema can represent its argv
exactly. When it cannot, only a constrained experimental direct-command fallback preserves the
exact argv for validation. Any opted-in safe inspection flag passthrough is considered after local
direct detection and only inside the normal validator/policy gate; it is never an execution bypass.
3) Ambiguity handling
Ambiguity detection runs only for non-direct natural-language requests. It looks for broad, destructive, or underspecified wording such as “clean this folder”, “delete unnecessary files”, or “repair permissions”. When such a request is ambiguous, OTerminus shows a short explanation and safe read-only inspection alternatives.
Ambiguous one-shot requests stop before planner setup, planner calls, validation, confirmation prompts, and
execution. Nothing is executed, including in dry-run or explain mode. Their audit events use
confirmation_result: "blocked_ambiguous" and include the ambiguity reason plus suggested safe
options. They also record planner skip diagnostics with planner_invoked: false,
planner_skipped: true, and planner_skip_reason: "ambiguity_blocked".
In REPL mode only, an ambiguous non-direct request may show one bounded clarification prompt before
any proposal is created. The prompt is deterministic: it lists safe inspection options from ambiguity
detection, asks for one complete replacement request, and accepts only one answer. Blank input,
cancel, interruption, EOF, or a still-ambiguous replacement records a completed source history/audit
entry and returns to the REPL prompt without planner setup, validation, confirmation, or execution. A
specific replacement records the original ambiguous source entry with clarification_outcome: "clarified", then re-enters the same lifecycle through handle_request() as a separate linked final
request. The parsed REPL run mode (dry-run or explain) is preserved, clarified requests never use
safe auto-execute, and execute-mode clarified requests still show the normal preview and confirmation.
Rerunning the final linked entry resubmits the final request; rerunning the original source resubmits
the original ambiguous text and encounters ambiguity again. Old answers are not silently replayed, and clarification is
not persistent conversational memory. Audit and persistent history redaction applies to ambiguity
reasons, safe options, prompts, answers, and clarified request text.
4) Capability router
A deterministic router classifies the request into categories like filesystem_inspect,
filesystem_mutate, text_search, process_inspect, etc.
Routing is metadata for audit, policy context, and prompt guidance. It is not the planner and does
not by itself choose a command.
5) Deterministic shortcuts
After routing, OTerminus may attempt deterministic shortcuts for a small set of explicit,
reviewable rules. This layer is controlled by deterministic_shortcuts; supported values are
minimal (default) and off. Shortcuts produce structured proposals only; they never emit
experimental command text and never execute directly.
Current recipes are limited to fixed zero-argument utility shortcuts: current-directory requests
(show current directory, where am i, print working directory) and clear-screen requests
(clear screen, clear the screen). The shared proposal builder respects disabled command packs
and platform-specific command availability through registry metadata, then lets structured argument
validation remain the final authority.
The shortcut layer is not a general natural-language parser. It does not extract paths, counts,
search terms, manual-page topics, process names, Git operations, or project-health operations.
Natural-language inspection requests such as show hidden files, show first 20 lines of README.md,
find python processes, and show last 5 commits continue to the LLM planner. Direct commands such
as ls -l, head -n 20 README.md, and git status --short still bypass the LLM through direct
command detection.
6) LLM planner + parsing
Normal natural-language requests reach the LLM planner unless blocked as ambiguous or matched by one
of the retained deterministic shortcuts. The planner asks Ollama for JSON Schema-constrained output and
validates the returned JSON against the Proposal schema. The schema supports only two first-class
modes: structured and experimental. If the model returns malformed JSON or valid JSON with
invalid proposal fields, OTerminus makes one bounded repair request and rejects the output if the
repaired JSON still fails validation. Repaired output must pass the same schema and structured
argument checks before preview, validation, confirmation, or execution.
Planner and parser prefer structured mode when command family + arguments can be represented deterministically. Experimental mode is used only when structured support is unavailable or unsuitable for a constrained single-command proposal.
7) Structured or experimental proposal handling
For structured proposals, Python renders final command strings/argv from typed arguments instead of trusting command text. Direct commands may also be normalized into structured arguments when a parser is available. Experimental proposals may carry command text, but they remain constrained by parsing, registry, validator, policy, preview, and stronger confirmation.
Normal experimental previews use plain user-facing wording:
Experimental command: this was not rendered from typed structured arguments. Review it carefully before running.
Verbose previews may add the architecture diagnostic:
Experimental mode stays outside deterministic structured rendering and uses stricter confirmation.
Some trusted direct commands may remain experimental when the typed schema cannot represent the
user's argv exactly. For example, ls -ltrh is detected locally, skips Ollama planning, preserves
["ls", "-ltrh"], and reaches validation with direct-command origin. Natural-language requests such
as "show files sorted by modification time" still go through the LLM planner and can only produce
typed structured arguments.
8) Validation and policy
Validator enforces:
- curated command-family allowlist
- operand/flag shape checks
- blocked operators/redirection/chaining
- path safety checks (including allowed roots)
- risk + policy mode compatibility
9) Preview and run mode
OTerminus renders preview details (command, mode, risk, warnings/rejections).
The normal execute mode requires explicit confirmation after a successful preview by default.
Experimental mode uses very-strong confirmation text and requires the exact phrase
EXECUTE EXPERIMENTAL. Failed validation or policy checks stop before execution.
If OTERMINUS_AUTO_EXECUTE_SAFE=true, OTerminus evaluates a narrow local policy after preview and
after dry-run/explain have already returned. The confirmation prompt may be skipped only for
validated, warning-free, structured, exact-safe commands from direct detection or the deterministic
shortcut layer. LLM-planned proposals, experimental proposals, network-touching commands, write or
dangerous commands, project-health commands, archive extraction/creation, commands with warnings,
history reruns, dry-run, and explain mode never qualify. The executor still runs only after the
preview has been printed.
One-shot --dry-run and --explain modes still use direct detection and, for specific
natural-language requests, planning, validation, policy checks, and preview rendering. Ambiguous
natural-language requests stop earlier in every run mode. Dry-run and explain intentionally skip
confirmation and execution after successful validation. The REPL dry-run <request> and
explain <request> built-ins provide the same inspection behavior inside an interactive session.
10) Execution
Executor runs command argv via subprocess, with special local handling for cd and clear.
11) Audit logging
When enabled, OTerminus writes a JSONL event with request lifecycle fields (routing, mode,
validation, confirmation result or safe auto-execute skip, exit code, duration). Ambiguous requests record the ambiguity outcome and
blocked_ambiguous status without planner, validation, confirmation, or execution fields. Dry-run
and explain requests record skipped execution status instead of an execution exit code.
12) Evals and tests
Deterministic fixture evals and unit tests assert lifecycle invariants and prevent regressions.
REPL history-aware commands in lifecycle terms
In REPL mode, history, history <n>, and explain <history_id> are local inspection commands
for the current process session and do not execute shell commands.
rerun <history_id> does not shortcut execution. It submits the original user input back into the
same request lifecycle described above, including ambiguity handling, planning/direct detection,
validation/policy, preview, and explicit execute confirmation. Reruns are never eligible for safe
auto-execute, even when the original request would otherwise qualify.
Timing observability
When audit logging is enabled, lifecycle stages record approximate local latencies in timings_ms using time.perf_counter() (milliseconds). These metrics are for debugging and contributor observability; they do not include command stdout/stderr content.