# Changelog All notable, user-facing changes to the Nosis Harness (`nh`) are documented in this file. The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). The initial public release is `0.1.0`. Its tag is created only after the reviewed release commit passes local and remote gates. ## [Unreleased] ### Added - Plan and Change modes in the full-screen interface. Plan is read-only: the model is offered only the read and search tools, and edits, commands and remote tools are refused by the program. Change is the previous behavior and remains the default for new sessions. Switch with Shift+Tab, `/plan` or `/change`, only between turns; the mode is shown as text on the input line, the model is told before its next request, and a resumed session reopens in the mode it last worked in. - Guided `nh mcp connect`, offline `status`, explicit metadata-only `check`, and offline `disable` commands. New connections require tool review before use; setup preserves existing settings and uses vault entry names for API-key authentication. - `nh chat --measure-efficiency` records each ordinary task separately, including the current model's usage and price context. Slash commands are excluded; measurement defaults off and is not enabled when resuming a session. - Optional efficiency records report consecutive identical tool calls and returned errors without saving arguments or results. Offline reports keep missing older measurements explicit. Repeated calls still execute normally. - Per-server MCP tool selection and definition review through `nh mcp review`. Existing integrations need a one-time review; new or changed tools stay disabled until selected and approved. Normal send, credential and action approvals remain. - A first text-edit exercise bundled in Windows packages built from rc.3 source, with an expected result and no Git, Python, Node.js or Rust prerequisite. - A live `/review` view of published file fragments and observed command outcomes, with scrollable details and explicit truncation, omission and expiry labels. It is not a complete workspace diff, durable verification record or undo feature. - Typed provider recovery guidance in the full-screen interface. Failed or interrupted work preserves drafts and no longer automatically dispatches queued text; continuing requires a deliberate action. Existing usage stops still apply. - Opt-in local efficiency measurements and experimental ranged file reads for `nh run`, with an offline task-cost report and comparison protocol. Billing gaps remain explicit and correctness is judged separately from loop completion. - Optional session-bound retrieval for large scrubbed observations, plus run-only extractive context and compact identity experiments. All default off; no overall savings or unchanged model quality is claimed. `nh init` adds ignore entries for the new local artifacts while preserving existing project rules. - Optional MCP schema discovery for new chat sessions, preserving original remote tool approval and trust checks. Registries sort tool names and reject ambiguous duplicates; local measurement can report schema drift without recording prompts. - Provider-first guided setup with catalog price and capability summaries, an explicit all-models option, and an optional bounded read-only first task. Declining key entry ends setup without offering a provider request. - Shorter beginner instructions, an audit map, and installation and usability checklists that distinguish observed results from work still to be verified. - Tool-reported file publication and command outcome messages, plus a reminder to inspect and check results. Timeline completion is labeled `completed`; it is not a task-correctness verdict. Historical receipts do not record verification. - Read-only `nh run` tasks with guarded local reading and searching. Editing, shell execution and remote tools are unavailable to the model. Normal provider charges and local receipt writes still apply. - MiMo 2.6 Flash/Pro and GLM 5.3/Flash routes, with provider-specific reasoning handling and migration from the previously bundled catalog. Existing explicit model choices are preserved. - Three small practice tasks with Python acceptance checks and instructions for comparing completed work, cost and required intervention across assistants. ### Changed - The `mimo-v2.5` and `mimo-v2.5-pro` routes are removed from the catalog ahead of Xiaomi's retirement of those model IDs on October 21, 2026 at 10:00 UTC+8. `/provider mimo` now selects `mimo-v2.6-flash`; before this change a price tie selected the retiring route. A saved model choice that names a removed route is reported with the commands to choose another; resuming a session recorded on a removed route is refused with an explanation. MiMo currently has no route advertised for image input. See [model updates](docs/MODEL_UPDATES.md#existing-mimo-users). - The commented llama.cpp template in `catalog.toml` now uses port 9931, the `llama-server` default from build b11521 (October 9, 2026). Older builds and the official Docker image still use 8080. - Session resume and listing refuse a ledger above 64 MiB without changing it or replaying a partial history. Listing reads each ledger once and keeps summary state instead of assembling a conversation that will not be displayed. - Tutorials include a reusable task brief and evidence table, and distinguish the current setup overview from opening an editing chat. - Guided setup goes directly from project confirmation to model selection and key connection. Detailed diagnostics and the free local price comparison are available through printed commands. Skipping a key explains how to return; the first model request still requires explicit read-only-task consent. - Outbound MCP client setup rejects literal link-local addresses, including the common IPv4 metadata endpoint, for both server and OAuth token destinations before connecting. Loopback and LAN configuration remain supported; this does not provide DNS-level isolation. - Full-screen help now wraps and scrolls in smaller terminals. Shortcut hints prioritize Help and current actions; the header shows a fitted project name, with the folder path in Help. F1 closes Help without stopping work or approving a hidden request. Stop/close hints reflect the active state. - Full-screen approval requests wrap and can be scrolled while waiting. Repeat approval is limited to identical, untransformed shell commands in this session. Redacted/escaped requests, file actions and remote MCP calls cannot reuse a rule. - Run, chat and TUI omit the shell tool when session policy proves all commands blocked, and explain the limit. Resumed sessions receive capability corrections without rewriting history; partial restrictions retain existing approvals. - Beginner guides now link to a separate configuration and catalog-upgrade reference. - File staging, creation and edit-publication helpers are grouped in one module for easier auditing, with their existing behavior and concurrency limits retained. - Tool contexts require an explicit policy guard and output scrubber at construction, removing an implicit permissive default for future callers. This changes the `ToolCtx::new` Rust API signature. ### Fixed - Malformed MCP server and OAuth token URLs are refused before credential access or network requests, preventing differences between destination permission checks and HTTP URL parsing. Status hides these URLs and gives repair guidance. - Outbound MCP result and JSON-RPC error redaction includes credentials used by the connection. Invalid response-type diagnostics no longer echo remote values. - MCP structured-only results are no longer lost. Mixed text/JSON and error results preserve useful data, with secret redaction before JSON serialization and an explicit omission notice if redacted object keys collide. - Provider responses with empty or whitespace-only tool IDs/names, or duplicate tool IDs, are rejected before any call in that response executes. Available usage is retained on the error path; malformed responses are not retried. - Anthropic requests preserve later system corrections at system authority and reject unsupported message roles instead of silently converting them to users. Structured system-message parts are refused instead of silently dropped. A late correction that would become assistant prefill is refused before HTTP. - New receipt/session JSONL files and runtime directories request private Unix creation modes. Existing permissions and Windows inheritance are preserved. - Direct `nh init` now shares guided setup's preflight checks for `.nosis`, the project catalog, policy and ignore files. Symbolic links, junctions and wrong file types are refused before writing; existing files remain untouched on refusal. - Setup recognizes an unchanged older bundled catalog and points to the explicit catalog migration command. Migration still requires review and consent, keeps a backup and does not automatically trust a custom catalog. - Durable session, receipt and Fleet records scrub decoded JSON strings and keys before encoding, including OpenAI-style `tool_calls[].arguments`. This protects active literal credentials and known key shapes at those boundaries. Arbitrary JSON embedded in other strings is still treated as text. Provider error JSON is decoded before scrubbing; unstructured bodies are omitted. Existing records are not rewritten. - Provider replies cannot introduce non-assistant message roles into conversation history. Refused tool calls retain paired non-execution results for later turns, and an empty normal completion is recorded as partial. - Long-session compaction preserves appended system corrections, including changes to the selected route and available tools. - Plain run/chat approvals require the fresh code shown for that request; queued `y/yes`, stale codes, piped input and random-generation failure cannot approve. - Full-screen approvals use F2 (once), F3 (eligible repeat) and F4 (decline), so ordinary typing or pasted text cannot approve a newly arriving request. Draft editing and queuing remain available while waiting. - Windows protected-path rules also check ASCII case variants of paths and rule patterns, closing a bypass for existing uppercase files. Unix path matching keeps its prior case-sensitive behavior. - MiMo routes and Kimi K3 send the requested output ceiling through their documented `max_completion_tokens` field. Other routes retain their existing cap field. Requested token ceilings are not a guarantee of a fixed final bill. ## [0.3.0-rc.1] - 2026-09-22 ### Added - Explicit `nh catalog migrate` for recognized older bundled catalogs, with a destination/change preview, default-no confirmation and a retained versioned backup. Custom catalogs are refused. Migration is not crash-atomic. - Opt-in remembered model selection in user configuration through setup or `nh model set/show/clear`. Explicit `--model` wins; an invalid saved choice fails rather than silently switching providers. - Multiline full-screen input with paste review, cursor editing and explicit newline shortcuts. Enter sends; pasting alone does not send. - Three practice walkthroughs, terminal controls and an executable-generated command reference checked in Windows CI. - Release candidates require successful exact-commit Windows, macOS and supply-chain checks. A separate job prepares and verifies GitHub build provenance for the tested executable and ZIP. This does not provide Windows publisher signing. ### Fixed - New-file creation publishes without replacing a competing destination. Filesystems without hard-link support fail closed. Edits refuse detected concurrent content or metadata changes; this remains a best-effort check rather than complete isolation from other writers. - MCP HTTP requests carry the modern metadata and matching headers. Replies are bounded and checked against the request, including SSE replies. The local server rejects malformed or mismatched requests before dispatch. Unsupported legacy configuration fails explicitly. - A cancelled model response no longer starts new tool actions. Cancellation is also checked before file mutations, shell launch and MCP tool requests, including after approval. Usage reported by a late response is retained. Completed changes are not rolled back. - Provider retries respect `Retry-After` without shortening its delay. Later attempts use the remaining retry window, while the first request keeps its allowance for long reasoning. Request timeouts are not retried. - A TUI session with a token budget stops new tasks when usage becomes unknown or incomplete. Budget messages now explain that the active task may finish above the observed-token limit. - Resuming a new TUI session preserves its original budget. Older TUI sessions without a saved budget setting require a new session. An incomplete final session record makes restored usage uncertain and stops budgeted dispatch. - Local-route output identifies a loopback endpoint without claiming that computation stays on the device or is unbilled. Such turns leave session money totals incomplete. - Shell termination reports failed process-tree cleanup even when the shell itself exits, so a surviving descendant is not hidden behind a successful cleanup message. ## [0.2.2] - 2026-09-20 ### Added - `nh setup` guides interactive users through project confirmation, model selection, a no-key preview, secure key entry, and an optional chat with the selected model. Running `nh` without arguments opens the same guide. Existing configuration and keys are preserved. Piped input cannot authorize setup. - DeepSeek Flash image input through `--image` and chat's `/image`. The existing `deepseek-v4-flash` route now sends the current provider model ID `deepseek-flash`. PNG/JPEG limits and read approvals still apply. DeepSeek Pro remains text-only. ## [0.2.1] - 2026-09-20 ### Security - Update rustls to 0.23.45 to fix TLS handshake encryption-level validation ([RUSTSEC-2026-0285](https://rustsec.org/advisories/RUSTSEC-2026-0285.html)). ### Added - Windows x64 portable executable and ZIP with SHA-256 checksums and a getting-started guide. A manual GitHub Actions workflow builds and checks the package. WinGet manifests are provided for catalog review; the WinGet listing is not available yet. - `nh doctor` reports what is set up and what is not, and it needs no API key. It names the running binary, whether `nh` is on `PATH`, whether the `nh` on `PATH` is a different copy, where the route catalog was read from, how many routes and providers are available, which key entries are stored, whether output is going to a terminal, and where configuration lives. On Windows it also reports the console code page. It then prints a short list of only the things that are wrong, and each line states the fix. It exits 0 whenever it can produce a report, because it is a report and not a test. - `nh doctor` never prints a key value. It reports only whether an entry is stored. If the key store itself cannot be reached, it says so, because that is a different problem with a different fix. - `nh doctor` now reports which display mode is actually in effect, Unicode or ASCII fallback, and whether that mode was forced with `--ascii` or chosen because output is not going to a terminal. It was previously the only command that reported the inputs to that decision without ever reporting the result. ### Fixed - DeepSeek cost estimates use the current Flash and Pro rates and apply peak pricing only during the provider's weekday peak windows. Weekends stay off-peak. Catalog peak tables can select weekdays; tables without a weekday selection keep their existing daily behavior. - DeepSeek `--think low` enables low-effort reasoning and preserves the reasoning needed for tool replay. It previously disabled thinking. `--think none` still disables thinking. - `nh` now starts on a clean Windows install. The Windows build linked the C runtime dynamically, so it needed the Visual C++ Redistributable, which a fresh Windows machine does not have. The program could not start there, and it could not tell you why, because the failure happened before any of its own code ran. The C runtime is now built into the binary. One consequence travels with the fix and belongs next to it: Windows Update no longer patches that C runtime, so a C runtime security fix reaches you only when you install a newer `nh`. `SECURITY.md` says so under Supported Versions. - The warning shown when the bundled law cannot be parsed now states what actually happens. It said that safe defaults were kept. The bundled law is omitted instead, so its block lists and credential audiences stop applying, while your own user and command line settings still do. The old wording was most reassuring at the moment it should have been least reassuring. - Text that nosis did not write is no longer rewritten for ASCII terminals. A model answer, the task you typed, and the command in an approval prompt now keep the characters they were written with. Only nosis's own interface glyphs are replaced when the terminal cannot show them. This matters most in an approval prompt: the command shown to you is the command that will run, so the two must never differ. Credential redaction and control character escaping are unchanged and still apply to all of it. - Tool refusals and tool failures now redact credentials before the text enters the conversation. - Provider error snippets now redact known credential shapes as well as the active provider key. - `read_file` now refuses files whose first bytes contain a NUL and tells you to use a binary-aware tool. - `read_file` now reports when it replaces invalid UTF-8 bytes instead of returning the changed text silently. - The approval prompt for creating a file now names the path that will actually be written. A directory can be a link to another directory, in which case the requested path and the written path differ. The prompt, the refusal line and the success line now all name the written path, and they add the requested path when the two are not the same. Editing a file already behaved this way. Creating a file now matches it. - The lines printed when a file is edited now name the path that was actually written. Editing reported the path you typed. It now reports the written path, and adds the typed path when the two are not the same. Creating a file and editing a file now build this text with the same code, so the two cannot drift apart again. - Every display now removes invisible characters from untrusted text. Some characters take no space on the screen but still change how a line reads. Approval prompts already removed them. Other displays used a weaker rule that only made control characters visible. There is one rule now, and it is used everywhere. - The generated API documentation now lists all nine commands the program ships: `init`, `key`, `run`, `chat`, `doctor`, `why`, `tui`, `fleet` and `mcp`. It listed four. - The warning that drops an MCP server now always names the destination it refused. If the server's URL could not be parsed, the line stopped after "is not approved for" and named nothing at all, so you were told a destination was rejected without being told which one. It now reads ``, the same wording the credential store already used for that case. ## [0.2.0] - 2026-08-09 This release is a source install. No binaries are attached. The install command is unchanged: ```sh cargo install --locked --git https://github.com/nosistech/nosis-harness nh-cli ``` Platform status: Windows is supported. macOS is in testing. Linux builds from source and is not yet verified. ### Added - Interrupt one turn without ending the session. `Esc` cancels the turn in progress. The request already in flight still completes, so the cancelled turn still receives its true measured cost, and the transcript states that the provider may still bill for it. - A prompt typed during a cancelled turn stays queued. It is sent only after the abandoned request returns, so it cannot overlap with it. - Receipts record how long a turn took, in whole milliseconds. The figure is wall clock for the whole turn, including tool calls, retries and compaction. Older receipts have no duration and still load. - The live status compares the current turn against how long the route usually takes, for example `WORKING - 24s, typically ~18s`. The typical figure is a median over your own receipts for that route and needs at least five of them, so it is absent until you have run a route several times. - Completed turns and the detail pane show the measured duration. - A pre-send preview estimates the prompt cost before you press Enter. It is display only and never reaches a receipt, a usage total or the ledger. - Prompt history recall on `Ctrl+P` and `Ctrl+N`. `Up` and `Down` still scroll the transcript and are unchanged. ### Changed - `Ctrl+C` is now a ladder rather than an immediate quit: it interrupts a running turn, clears a non-empty input, and exits only on two presses within 1500 milliseconds. - The approval prompt shows the full command it is about to run. A command that cannot be displayed in full is refused instead of being shown in a shortened form. - An unknown `--profile` now exits non-zero from `run`, `chat` and `tui`, before any provider call. It previously warned, substituted a default and spent money. - An unknown key in a law file is now a hard error that names the key. It previously parsed without complaint, which left a policy silently absent. ### Fixed - Wrapped transcript lines keep their hanging indent. - The status line no longer clips mid-word at 79 columns. - Key hints and the help overlay now appear while an approval is pending, not only while a turn is running. - The approval legend no longer labels `[n]` and `[Esc]` as one action. `n` declines one command and the turn continues. `Esc` declines it and cancels the whole turn. - `nh init` outside a work tree now reports that it omitted the pre-commit hook, instead of omitting it silently. - The policy matcher splits a command on a newline, so the second line of a two-line command is tested as its own fragment. - An interrupted shell command reports that it was cancelled instead of reporting a timeout. ### Security - Every repository-controlled configuration file is read through one guarded reader. The reader inspects the path without following it, refuses anything that is not a regular file, requires the resolved path to stay under the repository root, caps the size, and opens the file with a no-follow flag so that a file swapped for a symlink between the check and the open is refused. This covers project instructions, project memory, the policy file, the profile file, the MCP server file and the route price table. - Two of those readers previously had no size limit and none refused a symlink. A repository could commit a symlink and have it followed. Where the resulting file failed to parse, the parser quoted the offending line back into a warning printed on standard error. Such warnings are never added to the model context and are never sent to a provider, but they could reach your terminal and your logs. - The no-follow flag is fixed for each supported platform. On a target we have not verified, the build fails rather than falling back to an open that follows links. ## [0.1.0] - 2026-08-06 This release is a source install. No binaries are attached. One command installs it: ```sh cargo install --locked --git https://github.com/nosistech/nosis-harness nh-cli ``` That builds `nh` and puts it on your `PATH`. It needs Rust 1.96.0 or newer. Note that `cargo install` does not read this repo's `rust-toolchain.toml`, so check `rustc --version` if the build fails. To build inside a clone instead, run `cargo build --release`; there the toolchain pin does apply. Platform status: Windows is supported. macOS is in testing. Linux builds from source and is not yet verified. ### Added - `nh init` - scaffold `.nosis/` in the current repo: receipts directory, `.gitignore`, a secret-pattern pre-commit hook, and a starter `catalog.toml`. - `nh key add ` - store API keys in the OS-native vault (Windows Credential Manager / macOS Keychain / Linux Secret Service). Keys are never echoed and never written to files. Env fallback for CI/headless: `NH__KEY`. - `nh key remove ` - remove an entry from the OS-native vault; environment/CI fallbacks remain an explicit operator responsibility. - `nh run ""` - run one agent task with `--model`, `--max-turns`, `--think`, `--autonomy`, and `--profile`. Defaults: `deepseek-v4-flash`, 20 turns, `balanced`. Every turn is logged to the local receipt ledger `.nosis/receipts.jsonl`. - `nh chat` - interactive session. `/model` and `/provider` switch routes mid-session with history and cumulative usage preserved; `/price` quotes the current route at the current clock time, including its peak / off-peak window. - `nh resume` - resume a chat or TUI session that was interrupted. `nh resume` lists the interrupted sessions; `nh resume ` restores that one. Conversation history is written turn by turn to a crash-safe session ledger under `.nosis/sessions/`, so a session survives a crash or a closed terminal rather than only a clean exit. Cost totals are replayed from the ledger rather than stored as money, and the restored session reports `resumed`. - `nh why` - explain the cheapest capable route for a task; `--model` compares a specific route against the cheapest capable one. - `nh profile` - list the execution profiles (`frugal` / `balanced` / `max-quality`) and their effective caps for a model. - `nh tui` - full-screen terminal UI (`--model`, `--budget`, `--profile`). - `nh fleet run ` and `nh fleet resume [run_id]` - durable, resumable worker fleet for independent tasks (`--max-workers`, required `--budget` unless `budget_tokens` is in the task file, `--escalate`, `--defer-offpeak` on `run`; `--max-workers` on `resume`). Resume picks up the latest incomplete run, or a specific run id. Fleet state lives locally under `.nosis/fleet/`. - `nh mcp serve` - **preview** local MCP endpoint. Binds `127.0.0.1` (loopback) exclusively; bearer-token guarded. Metered-service tools: `why` (cheapest capable route + savings), `route_cost` (price a specific route), and `receipts` (the server's own recent metered receipts), alongside `route_resolve`, `fleet_run`, and `fleet_status`. The routing, pricing, and receipts tools return MCP `structuredContent` next to their text. **Do not expose this endpoint on a public interface.** It is a preview in `0.1.0`: loopback-only and bearer-guarded, and public source availability does not authorize exposing it. This is not a restriction that lapses on a date. - Honest metered route advice: execution uses the route the operator explicitly selects; `nh why` estimates the cheapest capable catalog route without dispatching it. Receipts record reported usage, while peak/off-peak and no-cache comparisons use catalog price data. Stale price data is flagged, never guessed. - Metered context compaction. When long context is compacted, the effect is reported as a **net** figure for the next call, because compaction also discards the cached prefix and therefore has a cost side as well as a saving side. When the net effect is negative it is reported as negative rather than hidden. Compaction figures are estimates, are marked with a leading `~`, and are never written into recorded usage. - Route catalog (`catalog.toml`) for open-weight providers: DeepSeek V4 (`deepseek-v4-pro`, `deepseek-v4-flash`), Kimi (`kimi-k3`, `kimi-k2.7-code`, `kimi-k2.7-code-highspeed`, `kimi-k2.6`), MiMo (`mimo-v2.5-pro`, `mimo-v2.5`), and GLM (`glm-5.2`, plus the free rate-limited `glm-4.7-flash`, `glm-4.6v-flash`, and `glm-4.5-flash`). - Context occupancy on every metered surface. The TUI footer, the `nh run` token line and the `nh chat` footer report the last request's prompt size against the route's declared context window as `ctx N%`. It measures the **last request**, not a buffer that only grows, so it drops after a compaction. A route that declares no window prints no segment at all rather than a guessed denominator; usage a provider never reported prints nothing rather than `0%`; a lower-bound figure inherits the same leading `~` the token counts use; and a prompt exceeding the declared window reports the real ratio instead of clamping to 100%, because that ratio is evidence the catalog window is wrong. - Transcript search in the TUI. `Ctrl+F` - or `/search` - finds text anywhere in the session, with a match counter, wrapping navigation, highlighting of every visible hit, and `Esc` restoring the exact prior scroll position. Search reads only the transcript as it is displayed, after credential scrubbing and escaping, so text that is redacted on screen cannot be found by searching for it. Matching folds case for ASCII only, which preserves byte length and therefore highlights exactly; non-ASCII text matches literally, so `é` does not match `É`. - Type-ahead while a turn is running. Text typed during generation is kept and editable instead of discarded, `Enter` marks it `[queued]` rather than sending, and it dispatches itself once when the turn ends. A queued `/command` runs as a command rather than being sent to the model. Approval prompts are unaffected and still answer by single key. - Law-based approval guardrails: every shell command stops at a y/N prompt that defaults to deny. - No Nosis-operated telemetry, analytics, beacons, or crash reporting. Provider requests go directly to the selected approved origin; operator-approved MCP tools and shell commands can create additional egress. Receipts stay local by default. See [PRIVACY.md](PRIVACY.md). ### Changed - Reverified every production catalog price against first-party provider documentation on 2026-07-26, normalized current routes to USD, and removed unsupported historical DeepSeek peak windows. - Route prices no longer expire. Nothing in the build ages, expires, or warns about a route price, and there is no recheck deadline to satisfy. A hand-serviced deadline cost more than it bought for providers that move prices two to four times a year. The accepted tradeoff is stated plainly: if a provider changes a price silently, the meter is wrong until a human updates the catalog. FX-rate staleness is a separate mechanism and remains - a stale rate still refuses to convert rather than guessing. - The meter now distinguishes what a provider actually reported from what it did not, and carries that distinction through every surface instead of substituting zero. Token counts that are only a lower bound print with a leading `~`; usage a provider never reported prints as unknown rather than as `0`; and a cost is refused outright when it cannot be derived honestly. A missing usage figure can no longer be read as a free call. - A cost is now bounded rather than refused when a provider reports prompt and output tokens but omits the cached-token split. Kimi and MiMo omit that field entirely on a cold cache and send it only once the prefix is warm - six of the twelve catalog routes, measured on the wire - so on a first run those routes previously printed no cost at all, and one such turn made a whole TUI session total read as unavailable. The meter now prints `cost at most - cache split not reported by provider`. The bound evaluates both ends of the feasible range and takes the larger, so it stays correct regardless of whether a route's cache-hit price is below its cache-miss price. No savings percentage is shown against a bound, no cached-token count is invented to fill the gap, and a session total that includes a bounded turn stays a bound even if later turns are exact. - Repository catalogs are accepted only when byte-identical to the bundled catalog or to an exact operator-reviewed user-global copy. - Active credentials now share one zeroizing registry across provider, Fleet, TUI, CLI, and MCP paths instead of bulk-materializing every catalog key into ordinary strings. - GitHub Actions now pins third-party actions by commit, disables persisted checkout credentials, adds macOS to Windows/Linux checks, uses locked dependencies, sets timeouts, and is paired with weekly Dependabot updates. - Security, privacy, architecture, release, and operations documents now distinguish current implementation from historical/aspirational plans. - Internal workspace crates are marked `publish = false`; public v0.1 is distributed from the reviewed source release rather than as independently publishable crates.io packages. - Provider credentials, runtime path containment, TUI terminal ownership, and TUI worker lifecycle now live behind shared modules instead of being duplicated across UI surfaces. - TUI, Core, Fleet, MCP, tools, routing, law, CLI, and vault tests are organized into named responsibility modules while preserving public commands, APIs, wire formats, and ledgers. - Provider wire formats, catalog validation, cache-safe context compaction, trusted CLI configuration, OAuth refresh, Fleet scheduling, and TUI input/render/worker state now live in explicit responsibility modules behind the same public facades. - Recoverable HTTP-construction, synchronization-poisoning, process-result, token-generation, and worker-join failures now return bounded errors instead of panicking. Strict warning-free rustdoc is part of both CI and the local release gate. ### Removed - Removed Telegram notification code, configuration, credential access, HTTP dependency, background sender, and documentation from public v0.1. The local bell/taskbar signal remains. ### Security - Fail-closed audience checks on key egress: a key is released only to its verified provider destination; anything unverifiable is refused. - Application-controlled terminal, receipt, tool-result, and MCP-result paths redact known key shapes plus active literal credentials. - Fleet state is guarded by a single-writer lock; readers never mutate state. - Bearer-token auth on the MCP preview uses constant-time comparison. - Repository catalogs cannot redefine credential destinations or spend metadata unless they exactly match the bundled catalog or an operator-reviewed user-global catalog. - Default interactive output is capped at 16,384 tokens per provider call; MCP Fleet runs require a positive budget and enforce a 1,000,000-token request ceiling. - The generated pre-commit guard now shares the runtime key-shape registry and reports, without overwriting, an existing user hook that needs manual chaining. - Tool calls execute only when the provider's termination reason confirms tool use. If the reason is absent or unrecognized, the requested calls are refused and the run is reported as partial with the reason stated, instead of acting on an unconfirmed instruction. - The Fleet echo test provider is compiled only under the non-default `test-provider` Cargo feature and is absent from ordinary builds, which refuse `NH_FLEET_TEST_PROVIDER` rather than honoring it. It previously existed in a default build and could write fabricated `pass` receipts into the same `.nosis/receipts.jsonl` that real runs write to. When the feature is enabled its receipts are confined to their own directory and can no longer reach the canonical ledger. - Report vulnerabilities per [SECURITY.md](SECURITY.md) - info@nosistech.com, 5-business-day response SLA. [Unreleased]: https://github.com/nosistech/nosis-harness/compare/v0.3.0-rc.1...HEAD [0.3.0-rc.1]: https://github.com/nosistech/nosis-harness/compare/v0.2.2...v0.3.0-rc.1 [0.2.2]: https://github.com/nosistech/nosis-harness/compare/v0.2.1...v0.2.2 [0.2.1]: https://github.com/nosistech/nosis-harness/compare/v0.2.0...v0.2.1 [0.2.0]: https://github.com/nosistech/nosis-harness/compare/v0.1.0...v0.2.0 [0.1.0]: https://github.com/nosistech/nosis-harness/releases/tag/v0.1.0