|
| 1 | +# Noah Code v0.2.4 |
| 2 | + |
| 3 | +This release is a security and reliability hardening pass across the permission engine, checkpoint |
| 4 | +capture, workspace edits, budgets, and the terminal interface, plus dependency and CI updates. |
| 5 | + |
| 6 | +## Security |
| 7 | + |
| 8 | +- Closed a hard secret-deny bypass through Git object syntax: `git show HEAD:.env` (and `:path` |
| 9 | + forms generally) is now classified by the path component and denied like `cat .env`, in build, |
| 10 | + plan, and `--auto` modes alike. |
| 11 | +- Unscoped patch-output Git commands (`git log -p`, bare `git show`/`git diff`) no longer ride the |
| 12 | + read-only auto-allow bump; they ask, since they can dump committed secrets without naming a path. |
| 13 | +- Expanded secret classification to common credential stores: `.npmrc`, `.pypirc`, `.netrc`, |
| 14 | + `.pgpass`, `.envrc`, `.kube/config`, `.docker/config.json`, `.aws/credentials`, and Java/JCEKS |
| 15 | + key stores. |
| 16 | +- Joined short-flag values are now scanned as paths, so `grep -f/etc/passwd`, `rg -f.env`, and |
| 17 | + `tail -F~/log` can no longer evade the external-path and secret checks. |
| 18 | +- Git checkpoint capture no longer stages secret-classified paths into `refs/noah-code/checkpoints/*` |
| 19 | + and no longer executes repository clean filters — capture uses filter-free plumbing |
| 20 | + (`hash-object --no-filters` + `update-index --cacheinfo`), preserving executable bits and storing |
| 21 | + symlinks as links. |
| 22 | +- Non-interactive `noah run --auto` now rejects elevated-risk commands (file removal, downloads, |
| 23 | + `find -delete`/`-exec`, and similar) instead of silently approving them; interactive behavior is |
| 24 | + unchanged. |
| 25 | +- Plan mode can no longer be crossed without confirmation: `mode`/`model` front matter in |
| 26 | + repository custom commands is ignored (user commands keep it), and `plan.exit_to_build()` is |
| 27 | + never auto-approved. |
| 28 | +- `find -delete`/`-exec`/`-execdir` joined the elevated-risk floor, and `rg --hostname-bin` is no |
| 29 | + longer treated as read-only. |
| 30 | + |
| 31 | +## Reliability and correctness |
| 32 | + |
| 33 | +- The main edit path (`replace`/`edit`) is now atomic and newline-preserving: byte-level splice, |
| 34 | + exactly-one-match enforcement, and temp+fsync+rename writes — CRLF files no longer flip to LF |
| 35 | + when one hunk changes, and a crash mid-edit cannot leave a truncated file. |
| 36 | +- Reads are bounded: whole-file reads above `max_file_bytes` require an explicit line range, ranged |
| 37 | + reads stream instead of loading the file, binary files fail cleanly, and durable pre-images above |
| 38 | + `undo_blob_limit` degrade to hash-only instead of ballooning the session database. |
| 39 | +- Background-job durable logs rotate at 4 MB keeping the newest lines, and log paging tail-reads |
| 40 | + instead of loading the whole file. |
| 41 | +- Live model switches (`/model`, `/reasoning`, `/providers use`) now rebuild the full retry and |
| 42 | + fallback pipeline — switches no longer silently drop transient retries and fallback models. |
| 43 | +- The WAIT path can no longer hang: background-job terminal events always fire even if the runtime |
| 44 | + write fails, and the host wait is bounded with state re-checks; a job finishing between WAIT and |
| 45 | + wake no longer fails the run spuriously. |
| 46 | +- Cost budgets work: per-response cost is recovered from provider-reported cost or LiteLLM's |
| 47 | + pricing table, so `max_cost_usd` enforces real charges and `/tokens` reports real cost instead of |
| 48 | + `$0.000000`. |
| 49 | +- Ctrl+C under `asyncio.run` exits cleanly with the designed double-press flow instead of a |
| 50 | + traceback; one press at an idle prompt hints, a second exits, and mid-turn cancellation renders |
| 51 | + once. |
| 52 | +- Configuration is validated strictly: unknown keys and invalid values or TOML fail every command |
| 53 | + with a one-line error naming the file and field — no more tracebacks from `noah doctor`. |
| 54 | +- `noah run` no longer exits 0 without doing anything when an auto-update installs; non-interactive |
| 55 | + runs print the update notice and proceed. |
| 56 | +- Fixed atomic-patch rollback ordering (fsync failure no longer strands a renamed file), new-file |
| 57 | + permissions (umask default instead of `0600`), grep-harvested edit anchors after `cd`, |
| 58 | + stale-anchor detection without a prior read, double-`close()` wiping the undo journal, stale |
| 59 | + interrupted runs resurrecting, and checkpoint metadata clobbering newer session metadata. |
| 60 | + |
| 61 | +## Interface |
| 62 | + |
| 63 | +- Fixed priority keybindings that hijacked basic editing keys: Skills picker moved to `Ctrl+G`, |
| 64 | + return-to-live moved to `Ctrl+]`, and `End`/`Ctrl+K` work normally inside the composer again. |
| 65 | +- `Cmd+C`/`Ctrl+C` in the composer copies the composer's own selection; keyboard (shift-arrow) |
| 66 | + selections are copyable. |
| 67 | +- `@`-mention suggestions no longer rescan the whole workspace per keystroke: directory pruning |
| 68 | + plus a short-lived cache keep the composer responsive in large repositories. |
| 69 | +- One Ctrl+C now renders a single "turn cancelled" entry, and question-modal "Other" collects a |
| 70 | + free-text answer instead of submitting the literal string `other`. |
| 71 | + |
| 72 | +## Packaging and CI |
| 73 | + |
| 74 | +- LiteLLM re-pinned to `>=1.96.0,<1.99.0` (resolved 1.98.0): upstream restored macOS wheels, so |
| 75 | + provider and security fixes from 1.92–1.98 now reach installs. |
| 76 | +- Added upper bounds for end-user installs (`textual`, `pydantic`, `click`, `rich`, `PyYAML`, |
| 77 | + `packaging`), which resolve fresh and ignore `uv.lock`. |
| 78 | +- Unified the duplicated dev-dependency declarations into the single `dev` extra. |
| 79 | +- The default test suite is now hermetic by construction (pytest-socket blocks network sockets); |
| 80 | + CI runs on `v*` tags, type-checks in the release pipeline, collects macOS coverage, and runs the |
| 81 | + network integration tests as a non-blocking job. |
| 82 | +- Expanded the hermetic suite to 565 passing tests. |
| 83 | + |
| 84 | +## Upgrade |
| 85 | + |
| 86 | +Existing managed installations can run: |
| 87 | + |
| 88 | +```bash |
| 89 | +noah update |
| 90 | +``` |
| 91 | + |
| 92 | +New installations can use the one-command installer from the README. |
| 93 | + |
| 94 | +**Full changelog:** https://github.com/skundu42/noah-code/compare/v0.2.3...v0.2.4 |
0 commit comments