Skip to content

0.116.0: Hosted keyboard input, E2B sandbox ceiling, bounded run reads, run header, TUI live starts

Choose a tag to compare

@danielgwilson danielgwilson released this 09 Oct 00:57
· 218 commits to main since this release
fae37be

humanish 0.116.0 delivers a hosted participant's arrow keys and punctuation, lets the operator
raise the E2B sandbox lifetime, and reads run files within size limits. On hosted E2B desktops,
ARROWDOWN, Page Up, Page Down, ?, / and other names missing from @e2b/desktop's key table
reached xdotool unchanged, which ignored them while the run recorded the keypress as completed;
both desktops now translate key names through one table and refuse a name outside it.
HUMANISH_E2B_MAX_SANDBOX_MINUTES sets the longest sandbox lifetime the planners allow, 60 minutes
when unset and up to 1440 on E2B's Pro plan. A refusal names the value that admits the study, and
humanish doctor shows the ceiling. A route's sandbox kill, and the kills, checks and listings of
humanish reclaim, carry the run's E2B key. verify reads at most 32 MiB of a run file and lists
a larger file, or a run past 10,000 entries, as unscanned, and every contained read tells a missing
file from one it refused. A run whose analysis did not complete reads live run finished; the analysis did not complete, a run refused before it was created prints no analysis: line, and a
desktop-cli run names its product on the subject: line and in run.json. In humanish tui, the
cursor follows the selected row through a refresh, a live start of a mode: dry-run file says
needs mode: live, Run again on a live run asks for a second Enter, the confirm prompt restates
the study's cost, and c lists every provider key. NO_UPDATE_NOTIFIER turns the update check
off.

This is a minor release because behaviors change for the same input. The first line of humanish run changes when only the analysis did not complete. verify grades a run with a file over 32 MiB
or more than 10,000 entries local_only where 0.115.0 could grade it share_ready, and other
commands refuse a file over their read limit that they read whole before. A desktop-cli run records
subject.source: desktop-cli, which 0.115.0 cannot read. NO_UPDATE_NOTIFIER turns the update
notice off. A hosted keypress whose name is outside the key table is refused before dispatch.
runtime setup with one of --memory and --cpus on a Lima VM that lists no size now stops. In
the TUI, a live start of a mode: dry-run file is refused, and Run again on a live run needs a
second Enter. The release removes and renames no command, flag, study field, bundle field or
library export; the package exports the same 13 values and 31 types as 0.115.0 and adds one
environment setting. These outputs change for the same input, which a script could notice:

# 0.115.0 0.116.0 What to do
1 A run whose own result was ok and whose analysis did not complete (refused at admission, failed or cancelled) printed humanish run <study>: live run failed, exit 2. humanish run <study>: live run finished; the analysis did not complete, exit 2. The JSON keeps ok: false and runOk: true. A run whose own result is not ok still prints live run failed. (#1685) Read the exit code and the JSON's ok and runOk; do not match the first line.
2 A run refused before it was created printed an analysis: line: analysis: skipped because the run's evidence could not be read for a live study (no keys), analysis: skipped for dry runs for a dry run the planner refused. No analysis: line; the output ends with the refusal and its code: line. --json keeps automaticAnalysis skipped with AUTOMATIC_ANALYSIS_SOURCE_UNAVAILABLE. A refused run started with --run-id still prints the old line. (#1711) Read automaticAnalysis from --json.
3 The subject: line was empty for a desktop-cli study, and for any computer-use study the CLI refused for an option such as --port 99999. subject: humanish (desktop-cli): the product and its source; the refused studies print their URL. (#1711) Nothing.
4 A computer-use run of a desktop-cli study recorded subject: {source: "app-url", ...} in run.json, the JSON result and lanes[].subject, and its subject event read Subject app declared at with no URL. {source: "desktop-cli", product: "humanish", state: {...}}, and the event reads Subject product declared: humanish, used from a terminal window inside the desktop sandbox. npm 0.115.0 refuses such a run: verify says "one or more run.json sections have the wrong shape" (exit 2, blocked) and review exits with HUMANISH_INVALID_RUN_BUNDLE. Runs saved with app-url still open on 0.116.0. (#1716) Read subject.source and subject.product. Read 0.116.0 desktop-cli runs with 0.116.0 or later.
5 doctor had no sandbox ceiling row. doctor and doctor --json add e2b sandbox ceiling: "60 minutes, E2B's Hobby limit. ..." unset, or "120 minutes, from HUMANISH_E2B_MAX_SANDBOX_MINUTES. ..." when set. A value outside 1 to 1440 (or not a whole number) fails the row, doctor exits 2, and the planners refuse hosted studies with their existing codes. (#1707) Read doctor checks by name. Set HUMANISH_E2B_MAX_SANDBOX_MINUTES only to the lifetime your E2B plan allows.
6 A study whose sandbox deadline passed 60 minutes was refused with "... a sandbox may not live longer than 60m. ...". The same refusal and code, with the ceiling in use and one more sentence: "If your E2B plan allows longer sandboxes (Pro allows 1440 minutes), set HUMANISH_E2B_MAX_SANDBOX_MINUTES to 90 or more." With the setting raised, the study plans, and a computer-use clone or local-tree study without execution.timeoutMs gets a session of up to 30 minutes where 60 minutes left 20. (#1707) Match the refusal by its code, HUMANISH_COMPUTER_USE_SUBJECT_INVALID, HUMANISH_SHARED_WORLD_INVALID or HUMANISH_TERMINAL_CAPS_INVALID.
7 verify read every run file whole and skipped a folder it could not list. A run with a 33 MiB text file, or with 10,001 more files, graded share_ready. verify reads at most 32 MiB of a run file. A larger file, a folder the scan cannot list and a scan stopped at 10,000 entries are listed under UNSCANNED_ARTIFACT, and the run grades local_only (in the smoke: "...: extras/big.txt" and "...: extras/many/ (the scan stops after 10000 entries)"). An adapter artifact over 32 MiB that the bundle cites grades blocked. A run.json, review.json, review.md or cleanup.json over the limit is named with the limit, and an unfinished run whose sandbox-receipts.ndjson cannot be read has its sandboxes called unconfirmed. (#1691) Read shareSafety.status. Run verify again on a run you plan to share.
8 Other commands read their files whole, and a file that was there but refused (a link, a folder, a special file) read as missing in several places. Limits: 64 KiB for .humanish/runs/latest.json, 4 MiB for a study, persona or scenario file, package.json, AGENTS.md or a scorer entry, 65,536 bytes for comms.yaml and 1 MiB for the comms study copy. A larger file is refused unread with an error naming it and the limit. A persona or scenario candidate that is a link stops the study with its name (it was skipped for a lower-priority file). --run latest with a linked pointer says so (it said "run not found"). humanish reclaim stops with HUMANISH_RECLAIM_RECEIPTS_UNREADABLE before it kills or writes when an earlier reclaim-receipt.json cannot be read. The end-of-run sandbox id sweep fails, naming each text file it could not read. comms configure refuses a local study copy over 1 MiB that it would replace. (#1691) Match errors by code; read the file name and limit from the message.
9 On a hosted E2B desktop, a key name missing from @e2b/desktop's table (ARROWDOWN, PAGEDOWN, ?, /, ...) went to xdotool unchanged; xdotool ignored it and the keypress was recorded completed. Both desktops translate names through one table, which adds the 20 shifted punctuation keys. A name outside it is refused before dispatch (action_rejected, not_dispatched) and the participant is told so. Control+a is split into its keys. A key xdotool reports as unknown is recorded as a failed desktop command with xdotool's words. A hosted participant's arrows and ? now reach the screen, so the same study can take a different path. (#1713) Compare hosted runs across this version with that in mind; see "Hosted keyboard input" below.
10 NO_UPDATE_NOTIFIER was not read. Set to any value, an empty one, 0 or false included, it turns the update check and its notice off, as update-notifier reads it. (#1693) Nothing.
11 keys set <name> for a name outside the store listed "(OPENAI_API_KEY, ANTHROPIC_API_KEY, E2B_API_KEY, ...)". The list names E2B_API_KEY before ANTHROPIC_API_KEY. (#1688) Match the refusal by its first sentence.
12 runtime setup --memory N or --cpus N alone, on a Mac whose humanish Lima VM lists no size, took the other value from a new VM's default. It stops and asks for both values. Both flags resize as before, and no flags start the VM as before. (#1688) Pass both --memory and --cpus.
13 A shared-world study whose persona file had an invalid background failed on its keys first. When execution.egressAllow was ignored together with a concurrency-cap or inbox warning, the egressAllow warning came first. The persona error comes before the key checks, as on computer use; the egressAllow warning follows the other two. (#1687) Match warnings by text; their order can change.
14 A terminal run's review, no-spend statement and terminal-ledgers.json provider line called the participant's tokens unpriced. They give run.json's token estimate: "Provider tokens (162,862 input, ...) are estimated at 0.225069 USD, the participant's model cost, which caps.maxUsd does not count." The provider line keeps usd: null and adds estimatedUsd with source estimated-token-usage; knownTotalUsd, the maxUsd check and noSpend.satisfied are unchanged. (#1715) Read estimatedUsd for the estimate; usd stays the measured figure.
15 The known-value scrubs searched base64 and hex forms from 8 characters. A received link of 32,768 characters or more failed the analysis with analysis_validation_failed_unexpected. Forms are searched from 6 characters, so abcd written YWJjZA is found; an identifier that holds a short value's base64, such as aMTIzNAz with the code 1234 registered, loses that part. Run evidence whose result still holds a value in any reading becomes [REDACTED_SECRET] whole. Long values are searched directly when Node refuses the regular expression. (#1684) Run verify again on a run you plan to share.
16 In humanish tui: "Start a live run" on a study whose file says mode: dry-run armed, restated a spend and started a dry run; Run again on a live run started one on one Enter; the confirm prompt said "$3 admission estimate limit"; c opened the AgentMail screen only; the cursor kept its row number when a refresh reordered rows. The live row reads needs mode: live and Enter names the file to change; Run again on a live run arms and needs a second Enter; the prompt restates the live history, the caps or no participant cap set, and the analysis line humanish run prints; c lists every provider key humanish keys lists; the cursor stays on the chosen row, and Enter on a run action that went away does nothing and says so. (#1709, #1720) Nothing.

Added

  • HUMANISH_E2B_MAX_SANDBOX_MINUTES sets the longest E2B sandbox lifetime the planners allow: 60
    minutes (E2B's Hobby limit) when unset, up to 1440 for E2B's Pro plan. A study whose sandbox
    deadline passes it is refused before any sandbox is created, and the refusal gives the setting
    value that would admit it. humanish doctor shows the ceiling on a new e2b sandbox ceiling
    row, and a value outside 1 to 1440 fails that row and refuses hosted studies. Raising it also
    raises the default session of a computer-use clone or local-tree study without
    execution.timeoutMs, from 20 minutes to as much as 30 (rows 5 and 6). (#1707)

Changed

  • A computer-use run of a desktop-cli study records subject.source: "desktop-cli" and the
    declared product name as subject.product in run.json, the JSON result and each participant's
    lanes[].subject. It recorded app-url before. Its subject event names the product, where it
    said Subject app declared at with no URL. verify, observe, review and export read both,
    so runs saved with app-url still open; npm 0.115.0 cannot read the new runs (row 4). (#1716,
    fixes #1712)
  • An adapter artifact larger than 32 MiB (state, log, trace or filesystem output) now grades a run
    local_only when nothing in the bundle cites it, and blocked when the bundle cites it as
    evidence. verify read and scanned such a file whole before (row 7). (#1691)
  • NO_UPDATE_NOTIFIER, the variable the update-notifier package reads, now turns off the update
    check and its notice, as HUMANISH_NO_UPDATE_CHECK=1 does. As in update-notifier, any value
    turns it off, including an empty one, 0 or false (row 10). (#1693)
  • Before a live start, the humanish tui study screen shows what a live run of the study is known
    to cost: the median of its live runs, its participant caps, or no participant cap set for a
    computer-use study that declares none, and the analysis line humanish run prints at a live
    start. The confirm prompt restates all three, in place of its own $3 admission estimate limit
    wording (row 16). (#1720, fixes #1699)
  • humanish runtime setup with only --memory or only --cpus, on a Mac where limactl list
    shows no size for the humanish Lima VM, now stops and asks for both values. It used to take the
    value not given from the default size of a new VM, which could change the VM's CPUs or memory
    (row 12). (#1688)
  • The refusal of humanish keys set for a name that is not a provider key now lists
    E2B_API_KEY before ANTHROPIC_API_KEY (row 11). (#1688)
  • A shared-world study whose persona file has an invalid background now stops with that error
    before the route checks its keys, as a computer-use study already did. When study check or a
    run warns that execution.egressAllow is ignored and also warns about a concurrency cap below
    the roster or about participants without an inbox, the egressAllow warning now comes after
    those two (row 13). (#1687)
  • The computer-use docs say what a stop rule's grade means beside the participant's closing
    account, which speaks from its own mission because it is not told the rule matched. (#1694)
  • Six refactors give one owner to the run clock that places reviewer notes (#1686), the
    persona-background warnings, the participant summary sentence and the latest.json path
    (#1687), the provider key table, the Lima VM size rule and the capacity tests' runtime (#1688),
    the findings text (#1689), the Observer's analysis limits and the debrief's closing ask (#1692),
    and the TUI's frame text, project data, screen body and launch (#1695). Note clocks and Observer
    timelines were byte-identical over 1,666 retained run bundles, and no golden changed. doctor's
    key rows now come from the provider key table (#1693).
  • The TUI is built with ink 8.0.0 and reads the terminal size from ink's useWindowSize. The
    package's own dependencies are unchanged. (#1690)

Fixes

  • On hosted E2B desktops, a computer-use participant's arrow keys, Page Up and Page Down, and
    punctuation keys such as ?, / and - now reach the screen. The executor passed key names to
    @e2b/desktop's press(), which handed names missing from its own table (ARROWDOWN,
    PAGEDOWN, ?) to xdotool unchanged; xdotool ignored them and exited 0, and the run recorded the
    keypress as completed. Both the hosted and the local desktop now translate key names through one
    table, which also gains the shifted punctuation (?, !, : and the rest), so ? works on the
    local desktop too. One name joined with +, such as Control+a, is split into its keys on both
    desktops. A name outside the table is refused, and the participant is told the action was
    rejected. A key xdotool still reports as unknown is recorded as a failed desktop command (row 9).
    (#1713, fixes #1697)
  • A route's kill of the E2B sandbox it created now carries the API key the create used. It carried
    none, so the E2B SDK used E2B_API_KEY from process.env: a library caller whose key was only
    in RunStudyOptions.env, or whose process.env held another key, got a kill that failed or
    reached another account, and the sandbox ran until its create-time timeout, which
    HUMANISH_E2B_MAX_SANDBOX_MINUTES can set to 24 hours. The kills, checks and tag search of
    humanish reclaim and of the run's interrupt handler now carry E2B_API_KEY and E2B_DOMAIN
    from the environment by name. (#1717, fixes #1708)
  • When a study's analysis does not complete (refused at admission, failed or cancelled) and the
    run's own result is ok, the first line of humanish run reads humanish run <study>: live run finished; the analysis did not complete. It read live run failed, which sent a reader to the
    participants. The exit code stays 2 and the JSON keeps ok: false and runOk: true. A run
    whose own result is not ok still reads live run failed (row 1). (#1685, fixes #1673)
  • A run refused before it was created, such as a live study with no keys, no longer ends its
    humanish run output with analysis: skipped because the run's evidence could not be read. The
    output ends with the refusal and its code. The JSON keeps the automaticAnalysis record (row 2).
    (#1711, fixes #1704)
  • The subject: line of humanish run names a desktop-cli subject by its product and source,
    as in subject: humanish (desktop-cli). It was empty, as it was for every computer-use study the
    CLI refused for an option such as --port 99999; those now print the study's URL (row 3).
    (#1711, fixes #1705)
  • humanish reads at most 32 MiB of one run file, 64 KiB of .humanish/runs/latest.json and 4 MiB
    of a project file (study, persona and scenario YAML, package.json, AGENTS.md, a scorer
    entry), and refuses a larger file without reading it. It read every file whole before. A file
    that is there and refused is never taken for a missing one, and the refusal names the file and
    the limit:
    • humanish verify lists a larger run file under UNSCANNED_ARTIFACT, names the limit for a
      larger run.json, review.json, review.md or cleanup.json and for a larger file the
      bundle cites as evidence, and calls an unfinished run's sandboxes unconfirmed when it
      cannot read sandbox-receipts.ndjson.
    • humanish reclaim stops before it kills or writes anything when the reclaim-receipt.json
      an earlier reclaim wrote cannot be read, so its recorded outcomes are kept.
    • A persona or scenario file that cannot be read stops the study with an error naming it. It
      used to be skipped for a lower-priority file of the same name, or for the persona id alone.
    • --run latest with a larger pointer and feedback list with a larger draft say so. The
      sandbox id sweep at the end of a run fails, naming each text file it could not read, and so
      does a run whose sandbox-receipts.ndjson is a link or cannot be read: without its ids, the
      sweep cannot find them in the run's other files.
    • export --format bundle reads each source file within what is left of --max-bytes and
      refuses one that changes as it is read.
    • A run file swapped for a FIFO while a command reads it no longer leaves the command waiting
      for a writer (rows 7 and 8). (#1691, item 2 of #1669)
  • humanish verify lists a run folder it cannot list under UNSCANNED_ARTIFACT, and stops its
    public-safety scan after 10,000 files and folders with the stop listed there too, so neither run
    grades share_ready. A folder it could not list was skipped before. export --format bundle
    already refused a run with more than 10,000 entries (row 7). (#1691)
  • humanish comms configure refuses a local study copy over 1 MiB that it would replace, where
    it now cannot read the copy whole (row 8). (#1691)
  • In humanish tui, the cursor stays on the row the person selected when a refresh reorders the
    rows: a study that goes live and moves to the top of the studies list, a newer run listed above
    the selected run, or a run that finishes, where Open in Observer moves up a row and Run again
    takes its place. The cursor used to keep its row number, so Enter could open a different study
    or start a new run. Escape back to the studies list also returns to the selected study after the
    list reordered. When the action the person chose on a run's screen goes away under the cursor
    (Cancel analysis once the analysis ends, Stop once the run ends), Enter now does nothing and says
    so; it used to act on the row now there, which could be Run again (row 16). (#1709, fixes #1696)
  • The humanish tui study screen no longer shows keys ✓ for a study whose file sets
    mode: dry-run on a machine with no keys. It checks the keys a live run of the study needs,
    whatever its mode, and shows the live plan's refusal for a study that can only run dry, such as
    first-run. humanish run runs a file in the mode it sets, so "Start a live run" on a dry-run
    file armed, restated a spend and then started a dry run. That row now reads needs mode: live,
    and Enter on it names the file to change; Run again on a live run of such a study does the same
    (row 16). (#1720, fixes #1698)
  • "Run again" on a live run in humanish tui asks for a second Enter, as a live start does, and
    its prompt shows the same cost. It started a live run on one Enter. A dry rerun still starts on
    one Enter (row 16). (#1720, fixes #1710)
  • The humanish tui study screen wraps the study's whole description within the content width.
    It cut the description to one line of at most 96 columns, even in a wide terminal. A description
    longer than the rows the terminal leaves it ends in …; the studies list keeps its one-line
    preview. (#1720, fixes #1700)
  • c keys and accounts in humanish tui lists each provider key humanish keys lists, with the
    line humanish keys prints for it, and Enter on a key asks for its value with hidden input and
    stores it as humanish keys set does. The AgentMail email connection is a row of that screen.
    c opened the AgentMail screen only, so the OpenAI and E2B keys a study needs could not be set
    there (row 16). (#1720, fixes #1706)
  • A run whose received email held a link of 32,768 characters or more no longer fails its analysis
    with analysis_validation_failed_unexpected. The scrub of the run's known values builds one
    regular expression of them, which Node refuses once a value is that long; it then searches each
    value directly and replaces the same text (row 15). (#1684, part of #1646)
  • The known-value scrubs find the base64 of a value of 4 or 5 bytes, such as the code 7439
    written NzQzOQ, and a 5-byte value inside a longer base64 run. Base64 and hex forms are
    searched from 6 characters instead of 8. A 4-byte value inside a longer base64 run is still not
    found, and an identifier that holds a short value's base64, such as aMTIzNAz while the code
    1234 is registered, loses that part (row 15). (#1684, part of #1646)
  • Run evidence is checked after its known values are replaced. When the result still holds a value
    in any reading verify uses, as when the marker written for one value spells another, the whole
    text becomes [REDACTED_SECRET] (row 15). (#1684, part of #1646)
  • Scrubbing run evidence takes time linear in the text's terminal escape sequences. A run of
    operating-system commands with no terminator took 3.4 s at 64 KiB. (#1684)
  • Redacting a local path that holds a long run of backslashes takes time linear in the run. A path
    holding 40,000 backslashes and then a letter took 1.4 s. (#1715)
  • A terminal run's review, its no-spend statement and the provider line of
    terminal-ledgers.json now give the participant's token estimate that run.json's cost summary
    gives, for example "Provider tokens (382,595 input, ...) are estimated at 0.37157 USD, the
    participant's model cost, which caps.maxUsd does not count." They used to call the tokens
    unpriced. The provider line keeps usd: null and adds estimatedUsd with source
    estimated-token-usage, so knownTotalUsd, the maxUsd check and noSpend.satisfied are
    unchanged. Tokens of a declared model with no rate are still unpriced, and the note now names
    that model (row 14). (#1715, fixes #1703)

Hosted keyboard input

Before this release, every hosted (execution.target: e2b-desktop) computer-use run dropped a
participant's ARROWDOWN, ? and SHIFT / keypresses and recorded them as completed, and the
other arrow names, PAGEUP, PAGEDOWN and punctuation @e2b/desktop 2.4.0's table lacks took the
same path. A hosted finding from an earlier release that a page or app ignores arrow keys, Page Up
or Page Down, ? or / may be an artifact of this harness defect. #1713 checked the two evidence
documents in this repository that name such keys:

  • docs/evidence/computer-use/persona-contrast-live-2026-09-01.md quotes a keyboard-first
    participant on drawDB: "Arrow keys and Enter cannot select a database". That participant sent
    no arrow key, so the claim was not caused by dropped keys. The third run in the same document
    has one dropped ARROWDOWN in its keyboard-first participant, whose report says the code editor
    was not keyboard-accessible.
  • docs/evidence/computer-use/persona-axis-phone-2026-09-03.md: the drawDB keyboard-first
    participants sent no arrow keys; the mouse newcomers in one run sent ARROWLEFT and ARROWUP
    while nudging overlapped tables after a failed drag, and those were dropped.

Neither document is changed in this release. The local guest desktop already refused a name
outside its own table before dispatch, so it never dropped a key silently; ? and the other
shifted punctuation were refused there and now go through.

Known gaps

  • Two contained-file races from #1669 remain. They need a second local process, running as the
    same user, to swap a directory in the run between two filesystem calls: temporary-file cleanup
    still unlinks by path (item 1), and the reviewer-notes listing still lists notes/ by path and
    can follow a swapped directory (item 3). Storage validation and the scan still list each folder
    whole before the 10,000-entry cap applies, verify has no total read budget, and a legitimate
    sandbox-receipts.ndjson over 32 MiB is refused. (#1669)
  • Coding agents still do not tell their person about humanish tui. #1718 added a sentence naming
    it to init, bare humanish, doctor, AGENTS.md and SKILL.md and measured 15 live terminal runs:
    0 reports named the TUI with the sentence, and 0 without it, so it was closed unmerged. (#1701)
  • Path redaction in terminal transcripts still removes the text after a path up to the next space,
    such as a line break and the next header after cwd:. Two fixes in #1715 were taken out after
    security reviews; the redesign in #1702 reads the full codex exec --json stdout at the end of
    the run and redacts each JSON line's decoded strings. Nothing leaks; text a reviewer needs is
    lost. (#1702)
  • In the TUI's run screen, Stop stays armed when the cursor moves to another action, so a later
    Enter on Stop stops the run without the confirmation shown again. (#1722)
  • From the 10-08 audit: observer/app.tsx (1,029 lines) is over the 700-line guideline, and
    impressionsNotCollected keeps a one-line copy of the closing-ask label. (#1677)
  • A hosted computer-use participant cannot type keysyms outside US printable ASCII (é, €) as
    keys; it has to type them as text. (#1713)
  • study check passes a study whose sandbox deadline passes the ceiling; humanish run refuses it
    at plan time. A shared-world study with an explicit execution.timeoutMs whose participant
    sandbox passes the ceiling has no plan-time refusal. (#1707)
  • The terminal route's teardown check calls Sandbox.getInfo with no key after a keyed kill, and
    the routes still take E2B_DOMAIN from process.env on create and ignore one in
    RunStudyOptions.env. (#1717)
  • A desktop-cli dry run still says Dry run: 1 participant would use ., and a local-app subject
    on the in-process route still records app-url. (#1716)
  • The TUI's live median leaves out analysis spend, where a finished run's card shows the total with
    analyses; the analysis line's expected range can pass its own admission limit; and after a key is
    entered on the keys screen, Esc returns to the studies list. (#1720)
  • verify's message for a scan stopped at 10,000 entries counts the stopped folder as "1 file", and
    while Run again is armed in the TUI, the hint line still reads "Enter select esc back".
  • From #1646, after #1684: a 4-byte value inside a longer base64 run is not found, two further
    decodings at a marker edge are not read, RunSecrets.spans (the terminal route's per-chunk
    replacement) has no final check, and a value that is part of a marker nests markers. (#1646)
  • Design findings cannot say that text or a click target is too small by measure. (#1638)
  • The impressions ask describes its kinds in visual terms, which can steer a participant toward
    visual critique whatever its persona. (#1654)
  • Nothing Mac-specific has run on a Mac: the Lima VM sizing, runtime setup --memory --cpus and
    this release's refusal of one flag on a VM that lists no size.

Package

humanish 0.116.0 packs to 2.5 MB, 7.8 MB unpacked, 962 files (npm pack on release/0.116.0 at
2e08fc1, shasum 3f1bd049ef43bf0b659bbf090e45b293c920107f). Against 0.115.0 it adds
dist/analysis/analysis-limits, dist/cli/findings-text, dist/run/escape-sequences,
dist/run/run-clock and dist/substrates/e2b/connection (.js and .d.ts each) and drops
nothing. The package exports only ., with the same 13 values and 31 types as 0.115.0 (pnpm api:proof). Its dependencies are the same as 0.115.0's. It needs Node 22.19 or newer, as before,
and @e2b/desktop 2.3.2 or newer as an optional peer.

Checked before release

A live smoke on a tarball packed from main a318993 in fresh projects under /tmp with a fresh HOME
and npm cache, DO_NOT_TRACK=1, and @e2b/desktop 2.4.0 beside humanish. Keys came from the user
key store through key discovery, with XDG_CONFIG_HOME pointing at it; no --dotenv was passed.
The store's OpenAI organization accepts server-side conversation state, so every participant ran
threaded, and the E2B project is on E2B's Pro plan. Controls ran the same CLI commands on npm
0.115.0 against copies of the main runs or the same study files. Priced spend: $2.32 for the smoke's
live runs, $1.39 of it in analysis, then $0.23 for the dogfood run and $6.14 for the benchmark,
$4.42 of it in analysis.

  • init --yes writes the same files as npm 0.115.0, and doctor and doctor --study try-live
    print the same apart from the new ceiling row: 60 minutes unset, 120 from the setting, and a
    failed row with exit 2 at 1441 (row 5).
  • try-live, as init writes it: reached the goal in 10 participant turns, input growing every turn
    from 2,888 to 18,143 tokens, then 18,509 for the impressions request. $0.25 run. Its automatic
    analysis was admitted at an expected $1.02 (admittedCostUsd $1.13, worst case $2.01, cap $3) and
    billed $0.62. It gave 5 impressions (unclear, unclear, unfinished, liked, liked).
  • humanish/studies/tui-self-study.yaml live, with only mode: live changed (the desktop ran npm
    0.115.0's TUI): passed in 12 participant turns, $0.33 run and $0.77 analysis (expected $1.07).
    Four ARROWDOWN keypresses each moved the selection: three ESC, ARROWDOWN, ENTER rounds
    opened cua-browser, first-run, local-browser and try-live in turn, and a lone ARROWDOWN moved
    try-live's cursor to "Start a live run". The participant did not press ?, so a copy whose
    mission adds "Also find out which keyboard shortcuts the interface offers." ran once with analysis
    off ($0.31): its lone ? opened the "Keyboard shortcuts" panel, and three ARROWDOWN moved the
    list cursor from row 1 to row 4. Both runs print subject: humanish (desktop-cli) and record
    subject.source: desktop-cli with product: humanish. Input grew every turn in both.
  • A study whose sandbox deadline is 90 minutes is refused at the default before a run is created,
    naming HUMANISH_E2B_MAX_SANDBOX_MINUTES to 90 or more, and plans as a dry run at 120; npm
    0.115.0 refuses it at both with no setting named. study check passes it on both versions. A live
    example.com study with an 80-minute session ran with the setting at 120: E2B listed its sandbox
    with a lifetime of 90.00 minutes while it ran, the run's receipt records timeoutMs 5400000, and
    the run killed it at the end. $0.04.
  • A live scripted run on a loopback page with review.analysis.maxCostUsd: 0.01: first line live run finished; the analysis did not complete, exit 2, run.json outcome.ok true; npm 0.115.0
    prints live run failed. With the store hidden, both versions print the same lines as with it.
  • try-live with the store hidden prints no analysis: line and ends with code: HUMANISH_COMPUTER_USE_KEYS_MISSING; npm 0.115.0 prints analysis: skipped because the run's evidence could not be read.
  • verify, review and runs (text and --json) on copies of the six live runs: byte-identical
    on main and npm 0.115.0 for the four runs that are not desktop-cli. npm 0.115.0 fails verify on
    the two desktop-cli runs with "one or more run.json sections have the wrong shape" and refuses
    review with HUMANISH_INVALID_RUN_BUNDLE (row 4). On dry runs given a 33 MiB file or 10,001
    more files, main grades local_only with UNSCANNED_ARTIFACT and npm 0.115.0 share_ready; a
    mode-000 folder fails the storage check on both (row 7).
  • The TUI under a pseudo-terminal sized on that pty only, replayed through @xterm/headless: with
    the cursor on first-run, a dry run started from another process moved first-run to the top and the
    cursor moved with it, and Enter opened first-run; npm 0.115.0 kept row 2 and opened cua-browser.
    cua-browser's live row reads needs mode: live, and Enter on it names
    humanish/studies/cua-browser.yaml; npm 0.115.0 armed a live start. try-live's armed prompt
    restates the caps and the analysis line. On the finished try-live run, one Enter on Run again
    armed "run again live? ... Enter again to confirm", and Esc cancelled it; no run started. c
    lists the four provider keys with humanish keys's lines.
  • After every run, reclaim --check exited 0 with clean. Raw sandbox ids appear only in
    sandbox-receipts.ndjson, E2B listed 0 tagged sandboxes after the smoke and after the benchmark,
    and no key value from the store appears in any run or kit file, as written, base64 or hex.

On the release branch:

  • pnpm release:check on the release head d0efb58, which adds the benchmark result: exit 0 in 4.0
    min with the same counts as below, a public-surface scan of 3,014 text files and the same shasum.
    On the release commit 2e08fc1 before it: exit 0 in 3.8 min, 499 test files passed and 10 skipped,
    7,856 tests passed and 12 skipped; TUI 176 tests; lint 436 warnings at its cap of 436; api:proof
    "13 values and 31 types match"; public-surface scan of 3,012 text files and 523 binary assets;
    npm pack --dry-run 962 files with shasum 3f1bd049ef43bf0b659bbf090e45b293c920107f. pnpm docs:generate there wrote 0.116.0 into cli.mdx.
  • pnpm release:dogfood on 2e08fc1 (the script run with Node, keys read from the user store by
    Node's --env-file into its environment, and a temporary HOME): "release:dogfood ok", verdict
    passed (goal_satisfied), no-spend satisfied, $0.23. The participant ran init --yes, study list, the free four-participant dry run, verify ("Verification passed all 16 checks and
    reported share_ready") and review on the installed 0.116.0, and stopped at the credentials the
    gate withholds. verify on the run: share_ready, 16 of 16; reclaim --check clean. Its review
    gives the participant's tokens as "estimated at 0.225069 USD" (row 14).
  • The post-publish check on the release tarball from 2e08fc1 (TMPDIR=/tmp, HUMANISH_SPEC the
    tarball): 106 of 106 passed. Its 8 new rows cover doctor's ceiling row and a 90-minute deadline
    refused at 60 and planned at 120 (#1707), NO_UPDATE_NOTIFIER=0 (#1693), the run header with a
    one-cent analysis cap (#1685), a desktop-cli dry run's subject line and run.json (#1711, #1716), a
    keyless run with no analysis line (#1711), verify on a 33 MiB file, 10,001 entries and a mode-000
    folder (#1691), and the TUI's needs mode: live (#1698). The same script on npm 0.115.0 passed 98
    and failed exactly those 8 rows. A first pass on the release tarball passed 104 of 106; both
    failures were in the new rows' own scripts (a grep pattern starting with -, and a desktop-cli
    fixture with no publicSurfaces), and both passes ran again.
  • The consumer check: the 0.115.0 check's library and CLI consumer, plus 14 CLI lines for this
    release. Typecheck 0 errors on both versions. The library steps and every CLI line from the
    0.115.0 check are the same on npm 0.115.0 and the release tarball, except the two keys set
    refusals, which list E2B_API_KEY before ANTHROPIC_API_KEY (row 11). The new lines differ as
    rows 1 to 7 and 10 say; the update notice without NO_UPDATE_NOTIFIER, verify on the desktop-cli
    dry run and the mode-000 folder read the same on both.
  • pnpm bench on 2e08fc1 with its defaults (3 runs per arm, openai-computer-use, neutral
    mission), committed in d0efb58: report recall 9/15, analysis recall 8/15, 0 invented on either
    arm, $6.14 estimated. 0.115.0 scored 10/15 and 8/15, and 10/15 for analysis read by hand. Two
    lines the rubric left unresolved are D5, the first planted report's and the third planted
    analysis's, which puts report recall at 10/15 and analysis recall at 9/15 read by hand. Against
    0.115.0's table, the reports found D1 once where 0.115.0's found it twice, one planted report says
    Clear completed removed a task (a false assurance), no analysis listed D1 (0.115.0: 2/3), and
    analyses listed D4 3/3 and D5 2/3 (0.115.0: 2/3 and 1/3). Each analysis's cap was the dry run's
    admittedCostUsd ($1.11 to $1.23 against bills of $0.61 to $0.85), and none was refused or
    skipped. The participants pressed Enter, Ctrl+A, Ctrl+R and End, the same keys as 0.115.0's and
    all in @e2b/desktop's own table, so #1713 changed no keypress in the benchmark. No planted
    participant typed more than 30 characters in one action, so none met D2. Every participant ran
    threaded, ended on its own and gave 6 impressions; E2B listed 0 tagged sandboxes after it.

Not verified

  • macOS and Windows. Every check ran on Linux x64 with Node 24.12.
  • A live run on the published package: the live smoke ran on a main tarball, and the post-publish
    rows are offline dry runs, refusals and local scripted runs.
  • A key name outside the table on a live hosted desktop: no participant sent one, so the refusal and
    its hint were seen only in tests. The local guest desktop was not run, so ? there was not sent
    live.
  • The kill with the run's key for a library caller whose key is only in RunStudyOptions.env
    (#1717): the CLI puts the key in process.env, where the old kill found it too, so the smoke
    cannot tell the two apart.
    tests/substrates/e2b/connection.test.ts covers it against a local stand-in for E2B's API.
  • A study longer than 60 minutes: the 90-minute sandbox ran for about a minute. A Hobby key refusing
    a sandbox past an hour was not tried.
  • Run again on a live run in npm 0.115.0's TUI: one Enter starts a live run there, so it was not
    pressed.
  • The scan's own path for a folder it cannot list (#1691): a static fixture fails the storage check
    first, on both versions. FIFO swaps and growth during a read are covered only by mocked tests.
  • The TUI's Enter guard on a run action that goes away under the cursor, the all-runs screen and the
    keys screen's key entry: the TUI tests cover them; they were not driven at a pseudo-terminal.
  • A live Codex participant, the impressions and closing records in explicit-context mode, the local
    VM, email capture and receiving, local-agent participants and the shared-world route: not run live
    on 0.116.0. The terminal route ran live only as the dogfood run.