Repository navigation
Release v0.22.0: native viewing and editing, Semantic Output, /track and input ownership - #444
Draft
raiseCatError wants to merge 209 commits into
Draft
raiseCatError wants to merge 209 commits into
raiseCatError wants to merge 209 commits into
Conversation
…w redraws #403: an interactive Fish on a fresh home starts its man-page completion generator detached; it outlived test shells and raced home removal. Test homes now mark that generation as done (Fish 3 and 4 locations), and the runner no longer passes ambient XDG data, cache and state directories to tests. A regression asserts no generator starts. #408: newer shell knowledge resolved in-flight classifications as unknown, so a stored queued command could keep the unclassified color. A superseded lookup is now asked again against the new knowledge (bounded); stale answers are still never cached. The highlight tests wait for the shell's startup knowledge and for the lookups they started instead of one event-loop turn. #388: the output parser ignored row movement, so every frame of a multi-row progress display stayed in the transcript. Programs can now redraw their own recent rows (cursor up/down, save/restore, partial erases), never above NMSh's lines or more than a screen height; absolute positioning keeps the previous behavior.
/view <path> reads a regular file relative to the shell's directory, /view N completed output N (numbered as /copy), /view alone the latest output; block Actions gain View output. Markdown files render (m shows the source), source files get syntax roles and line numbers, diffs read as diffs. Find, go to line, wrap or horizontal scroll, copy all. Files are opened non-blocking and only regular files are read: at most 8 MiB and 200,000 lines, binary and UTF-16 refused, invalid UTF-8 shown with a note. Drawing is bounded to what is visible, and every control or format character is drawn as a visible mark. Viewing never writes to the file or transcript.
/edit <path> (or e in /view) opens one small text file in a full-height panel: typing, multi-line, caret by character/word/line/page, Shift selection, Ctrl+Z/Ctrl+Y undo and redo (bounded, coalesced), Ctrl+F find, Ctrl+C/Ctrl+X copy and cut, Ctrl+S save, Esc closes and asks about unsaved changes. Ctrl+Y now decodes as redo (it was dropped before). Only files that can be saved back exactly are opened: regular UTF-8 text up to 1 MiB, owned by this user, one hard link, writable file and folder, one kind of line ending (BOM and final newline kept); a missing path in a writable folder opens empty. Saving writes beside the original (exclusive create, its mode and group), syncs, re-checks that the original is still the file opened (device, inode, size, time, content hash) and renames over its real path; a symlink stays a symlink. A changed, replaced or deleted original is a conflict: Keep editing, Overwrite, or Reload. A new file never replaces one that appeared meanwhile.
…#386) A completed block whose output a recognizer is sure of gets one overview row with the counts the tool printed and, when it listed failures or diagnostics, a details row that opens them (verbatim lines, at most 20 plus a count). Recognizers: Node's test runner (spec, TAP), Jest, Vitest, pytest, cargo test, go test, TypeScript, Rust and GCC/Clang diagnostics (diagnostics only from build commands or failed ones). Short passing output gets nothing. Readings are derived per record, never stored: the transcript lines, raw folding, find, selection and plain /copy are unchanged, and derived rows are skipped by find and selection. Details start open when the raw output is folded; a click on the details row or Actions -> Show or hide details toggles them. /copy --semantic and --both copy the reading (raw once for an output without one, said in the note). Settings -> Transcript -> Semantic Output.
A security review found patterns that could backtrack quadratically on crafted output (trailing-whitespace stripping, the Jest summary, TAP directives, GCC/TypeScript location prefixes), and recognition runs when a block is first drawn. Lines over 2,048 characters are no longer read, trailing whitespace is removed with trimEnd, and those formats are parsed with string operations and end-anchored bounded patterns. A test runs eight adversarial outputs (up to 2 MB each) and bounds each one's time; behavior is unchanged.
/track <command> (or --every 5s -- <command>) writes the command and a note once, then draws a status row and the latest completed result under them, replaced on every refresh with a stable height. Live rows are derived: never stored, found, selected or copied, so nothing accumulates per refresh. /track copy, refresh, pause, resume and stop; stopping leaves the last result in the transcript once. /watch keeps its manager and behavior. The shared scheduler takes draft PR #394's hardening as written (strict cadence parsing; refusing substitutions, background jobs and heredocs; UTF-8-safe bounded capture with a truncation flag; visible timeouts and spawn errors; completion on stdio close; a stop grace period; at most 8 trackers), and its tests. Samples now use the live shell's PATH. The derived-row flag from Semantic Output is generalized for both.
…mings (#364, #365) Bun's requested version comes from .bun-version or package.json (packageManager, engines.bun) and the active one from its install location; the Nix shell module reads IN_NIX_SHELL; the container module names Docker, Podman, a dev container or Codespaces from marker files and host variables. Nothing is run. IN_NIX_SHELL, REMOTE_CONTAINERS and CODESPACES join the shell's allowlisted environment report. A Context Pack may now require 24 capabilities (as many as its modules), since the project pack needed a 17th. /modules explain and /modules timings write plain-text reports from the engine's snapshots: each configured module's surface, visibility reason and sources' state, age and timing; or the slowest last collections. No value is shown and nothing is collected to produce them.
Twelve variants with colors copied exactly from each project's MIT-licensed source at a recorded revision (sources, revisions, licenses and role mapping in docs/design/theme-families.md). Every role fill keeps 4.5:1 module text contrast; light variants keep NMSh's text tiers. Existing ids and saved choices are unchanged; Lavender stays the default. Oxocarbon (grays computed at runtime in HSLuv), GitHub Primer (values from a built primitives release), Material/Palenight and Monokai (licensing not verified) are deferred with reasons. Theme Studio's Built-in list gains / to filter by name, family or dark/light; Esc clears the filter before closing.
…release readiness Refs #410
…on its own target Review of #416/#420 found commands that /track (and /watch) started at once and repeated every interval without asking: - `echo x > ~/.zshrc 2>/dev/null`: the shared classifier excused every redirect in a command once `>/dev/null` appeared anywhere; `>|` was split as a pipe. Paste review labelled the same text read-only. - `env rm -rf …`: `env` is read-only on its own but runs its operand. - Anything classified network: `npm publish`, `npm login`, `npm audit fix`, `npm x`/`pnpm dlx`/`bun x`, `ssh host rm …`, `scp`, `rsync`, `curl -X POST`, `curl -o file`, plain `wget`. - `git -c core.fsmonitor=… status`, `GIT_EXTERNAL_DIFF=… git diff`, `--ext-diff` (run arbitrary programs) and `git log --output=…` (writes files). pasteGuard now judges each redirection's target (descriptor duplication and the null/standard-stream devices are not files) and treats `>|` as a redirection. repeatSafety.ts adds the repetition gate on top of the classifier: network commands start at once only as read-only probes; env prefixes, wrappers and git program options ask first; file-writing options, --fix/--write/snapshot updates, --watch modes, scp/rsync and power control are refused. `2>&1` is no longer mistaken for a background job. Network targets are remote unless they are this computer. Refs #393, #416, #420
… after wiring - When a sample's shell exits, the close handler cancelled the KILL fallback even if other members of its process group were still running. A child that ignored TERM and closed its output survived `/track stop` (verified with a pid probe; the new test fails without the fix), and a stray process left by a finished sample piled up on every refresh. On close, anything still in the group now gets TERM, then KILL after the grace period; that timer keeps a closing window alive for at most the grace period so nothing is left behind. - #420's refresh-start event now fires after the sample's handlers are attached, so a listener that throws cannot leave a child without them. - A tracker whose directory disappeared said `spawn /bin/sh ENOENT`; it now names the directory and keeps trying at its interval. Refs #393, #416, #420
…esult rows - Above the composer each active tracker had its own row, repeating its block's status; eight trackers took eight rows. More than two now share one summary row (`4 trackers · 1 failing · /track opens the manager`). - The state marks (◉ ■ ‖ ◌) ignored Safe glyphs; they now use ASCII there, in the block and the manager. - Live rows split and sanitized the whole 200 kB result on every frame (1–3 ms per frame with eight large trackers); the first rows and line count are now computed once per result (~0.5 ms). - The confirmation for an unknown /track command says "Track …?", not "Watch …?". - Live PTY tests: four trackers at once (slow, failing, missing command, large output) with `refreshing…`, a resize and `/track stop all` ending every process; Bash and Fish trackers finding a PATH change made after startup. Refs #393, #416, #420
…eature/v022-arcade-games
…ture/v022-arcade-games
…ure/v022-arcade-games
…eature/v022-arcade-games
…g, with a fake engine
… feature/v022-browser
…bs in the session, /browser parsing and the Real browser setting
…ure/v022-arcade-games
…nt preview server, Markdown preview
…o feature/v022-browser
… wired into the app; lazy BrowserHost; marked dependency
…ture/v022-arcade-games
…integration/v022-final
…t change made while starting is reconciled; image tests follow the workspace
…y new row NOT RUN
… and the arcade and browser commands
v0.22.0 final scope: multiline modes, images, text sizing, document workspace, /browser and the Vespyr Arcade
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Draft: do not merge. This is the release PR for v0.22.0. It follows the v0.20.0 flow (#392): one release branch, merged into
masterwith a regular merge commit, and the tag created on that merge commit. It merges only after the gates below are met and the maintainer authorizes the release.It supersedes v0.21.0. The maintainer chose to ship the latest stable version rather than every planned one. v0.21.0 (#429) is never tagged or published, and its work ships here. #429 is closed as superseded when this merges, never merged itself. The changelog has no
[0.21.0]section;[0.22.0]covers everything since v0.20.0.What it carries
devdev=a8b383c2(v0.21 ledger)/vieweditor test (#434 with #439)[0.22.0]changelog section (candidate), README, ROADMAP and AGENTS status, the consolidated physical QA walkthrough, the v0.22.0 runbook, ledgersmaster(6af5cbab) is an ancestor of this branch, so there are no conflicts. The branch does not containrelease/v0.21.0's two commits; they held only metadata (version 0.21.0 and a[0.21.0]section), which this branch replaces.Conflicts while integrating:
CHANGELOG.md, for /open: choose a terminal editor when VISUAL and EDITOR are unset (#366) #439 and Ask: optional command suggestions from the local model, Copy/Insert only (#432) #440. Every line was kept, with the incoming bullets placed at the end of their section.tests/typingAfterRead.test.ts, for Tests: live tests wait for NMSh's journal, not screen text (CI races seen on #441 and #442) #442. Tests: live tests wait for NMSh's journal, not screen text (CI races seen on #441 and #442) #442's version was taken; it also carries Input ownership: prompt hooks and stale questions never eat type-ahead (#436) #437's held outcome.Apart from today's commits, the code equals the CI-green v0.22 candidate
567cf533. Those commits are:6486d9c5: the security fix;292583ae: the matching test update;/vieweditor test.Security review (hidden input, #426)
The candidate still had two ways for a password to run as a shell command. Both are fixed in #437 (
6486d9c5). Details are in the v0.22 ledger and #437.567cf533with real zsh and Bash; with the fix, the password is in neither NMSh's journal nor the shell's history file.Regressions:
tests/inputOwnershipSecrets.test.ts: 10 tests; 6 fail without the fix.tests/inputOwnershipSecretsLive.test.ts.The remaining limits are listed in the changelog.
Gates (in order)
docs/testing/v022-physical-qa.mdrecorded on the candidate build. One walkthrough covers v0.21's and v0.22's work. Not run yet.llms.txtat v0.22.0. Then dispatch CI on that exact head.docs/development/v022-release-runbook.md). Then close Release v0.21.0: native viewing and editing, Semantic Output and /track #429 as superseded and let the v0.22 PRs close as merged.Package version:
0.22.0. There is no npm publication (private). The release has no uploaded assets: the source archive is GitHub's tag archive, which the Homebrew formula uses.