atomic: 0.9.15 -> 0.9.16 - #2877
Merged
Merged
Conversation
Run via `nix run .#update-atomic`, which resolved npm's latest dist-tag to 0.9.16 (next is 0.9.17-alpha.1, out of scope: the script consumes the stable tag by construction and takes no version argument). All four artifacts the script derives moved together: manifest.json, the src hash, npmDepsHash, and a regenerated npm-dist-repairs.patch carrying 21 references to 0.9.16 and no 0.9.15 remnants. Fix the tests.help usage assertion, which upstream falsified. atomic 0.9.16 documents a `--` end-of-options separator, so the usage line at packages/coding-agent/src/cli/args.ts:262 went from atomic [options] [@files...] [messages...] to atomic [options] [--] [@files...] [messages...] The literal grep therefore failed while --version and the other two help assertions passed. Updating the literal keeps the assertion severe rather than loosening it to a substring: it is what caught this change. Correct two stale counts in the header comment. The patch backfills integrity for 10 shrinkwrap entries, not 9, and they are not all atomic-natives* - @bastani/pi-ai is among them, and already was at 0.9.15, so "the 9 @bastani/atomic-natives* entries" was wrong before this bump. The removed devDependencies were 12 at 0.9.15 and are 10 at 0.9.16 (upstream dropped @types/diff and @types/ms). Both counts are now stated as mechanism rather than as numbers, since update.sh selects entries by the absence of `integrity` rather than by name and any fixed count goes stale at the next bump. The "lockfileVersion 3, 359 packages" claim was re-checked against the 0.9.16 tarball and still holds. Verification: `nix build -L --no-link .#atomic .#atomic.tests.help` passes, with versionCheckHook reporting 0.9.16 from the built binary. Checks run: package-atomic, package-atomic-test-help, treefmt (a .nix and a .sh file changed), and atomic-agent-environment-structural as the only other atomic-named check. The full check set is deliberately not run: this change touches one package directory and no shared infrastructure, so the remaining checks could not fail on account of it.
|
Tick the box to add this pull request to the merge queue (same as
|
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.
What
atomic0.9.15 -> 0.9.16 vianix run .#update-atomic, plus a stale-test fix and two stale comment counts the update falsified.The script resolved npm's
latestdist-tag to exactly 0.9.16, as required.nextis0.9.17-alpha.1and stays out of scope: the script reads the stable tag by construction and accepts no version argument.The four derived artifacts moved coherently
manifest.json0.9.15->0.9.16srchashsha256-IUhR/RS0...->sha256-eAgebHtz...npmDepsHashsha256-EHtSTNyz...->sha256-1UIAt5YD...npm-dist-repairs.patch0.9.16, zero0.9.15remnantsThe patch's shape was audited rather than assumed: 10 shrinkwrap hunks each backfilling one
integrityline, and onepackage.jsonhunk removingdevDependencies. Re-derived independently from the 0.9.16 tarball:lockfileVersion 3, 359 packages (the header comment's claim still holds), 10 entries missingintegrity, 10devDependencies.Two defects fixed alongside the bump
A stale test assertion, falsified by upstream.
atomic.tests.helpasserts three literals from--help. atomic 0.9.16 documents a--end-of-options separator, so the usage line atpackages/coding-agent/src/cli/args.ts:262changed:.#atomicitself built green —versionCheckHookandpostInstallCheckboth pass — so this failed only in the passthru test. Worth noting how it surfaced: the first verification run was piped totee, which reported the pipeline's exit status and showed success. The failure was visible only on a direct, unpipednix build. The assertion is updated to the new literal rather than loosened to a substring, since its exactness is what caught the change.Two stale counts in the
package.nixheader. The patch backfills integrity for 10 entries, not 9, and they are not allatomic-natives*—@bastani/pi-aiis among them, and already was at 0.9.15, so "the 9@bastani/atomic-natives*entries" was wrong before this bump. The removeddevDependencieswere 12 at 0.9.15 and are 10 at 0.9.16 (upstream dropped@types/diffand@types/ms). Both are now stated as mechanism rather than as numbers, becauseupdate.shselects entries by the absence ofintegrityrather than by name, so any fixed count goes stale at the next bump. The same stale parenthetical inupdate.sh:52is corrected.Verification
nix build -L --no-link .#atomic .#atomic.tests.helppasses, withversionCheckHookreporting0.9.16from the built binary.Checks run, all green:
package-atomic,package-atomic-test-help— the package and its passthru testtreefmt— a.nixand a.shfile changed (438 files processed, 0 changed)atomic-agent-environment-structural— the only other atomic-named checkDeliberately not run: the remaining ~60 checks in
.#checks.aarch64-darwin. This change touches one package directory and no shared infrastructure, so none of them could fail on account of it.just check-fastbelongs to pre-merge validation, not to a single-package bump.Release review against the firstmate adapter contract
firstmate runs atomic as a worker runtime. Per-surface verdicts follow, each read against tag
0.9.16in the local checkout at/Users/crs58/ghq/github.com/bastani-inc/atomic.Two framing corrections first, because they change what the surfaces mean.
The PRs measured 0.9.13, not 0.9.15. firstmate PRs 26-29 name atomic 0.9.13 throughout, measured 2026-08-19/20; no PR in that repo re-verifies on 0.9.15. Reviewing only
0.9.15..0.9.16would therefore have produced a true-but-useless "nothing invalidated" against a baseline no evidence was ever recorded on. The0.9.13..0.9.15window was audited as well: 1519 files, +140849/-13115, dated 2026-08-13 to 2026-08-21.Two surfaces as briefed do not exist. atomic has no
--effortflag at any of the three tags (git grep effortin the CLI layer: zero hits); firstmate maps its effort levels onto--thinking. And--model provider/iddoes not pin a provider — the measured 0.9.13 fact is the opposite of the brief's premise, which is why firstmate passes two flags,--provider <p> --model <id>.-naextension isolation--model/--provideracceptance--thinking(not--effort)registerTool/defineTool1, 3 — classification and turn-end/stop. atomic exposes no agent-kind registry that firstmate consumes; the
--kindlist is herdr's own and has no atomic entry, which is why firstmate carries a fallback classifier. What it actually consumes is three events and one rendered string, all confirmed present and live at 0.9.16:agent_start,agent_end,agent_settledatcore/extensions/agent-events.ts:51-64; theon()overloads andExtensionHandler = (event, ctx) => ...atcore/extensions/api-types.ts:80,114-118;isIdle(): booleanatcore/extensions/context-types.ts:182, implementedisIdle: () => !this.isStreamingatcore/agent-session-extension-bindings.ts:228. The ordering invariant firstmate depends on —agent_settledemitted last, from afinallyblock after retries, compaction, and queued continuations — holds structurally atcore/agent-session-prompt.ts:246-261, andcore/agent-session-summary.ts:48-53still documents whyagent_endalone is unsafe. The rendered busy token is byte-identical:core/interactive/components/footer.ts:251,this.session.isStreaming ? this.renderStyle.muted("esc to interrupt"). The 12-linefooter.tsdiff touches only compaction usage lines and a Copilot fast-mode parameter.2 —
-na.args.ts:216-219setsprojectTrustOverride = false, byte-identical to 0.9.15. The whole causal chain from that flag to "host repo extensions are not scanned" is byte-identical:package-manager-auto-resources.ts:118-147(the only place a project root'sextensions/is scanned, gated onisProjectTrusted()),config.ts:243-246,387-390(CONFIG_DIR_NAMES = [".atomic", ".pi"], both scanned when trusted, neither under-na), andtrust-manager.ts:68-97(the five-option blocking dialog, never rendered becausemain.ts:472-473skips registering the resolver). An explicit outside-project-epath still loads under-na:resource-loader-reload.ts:274-278includescliEnabledExtensionsunconditionally. That combination is the entire isolation mechanism and it survives intact.One adjacent change worth knowing:
-ne/--no-extensionsno longer means "zero extensions" — mandatory bundled Intercom now loads regardless. This does not affect firstmate, which passes-naand explicitly rejected-neas too blunt. It ischanged-compatiblefor-naspecifically becausegetMandatoryBuiltinExtensionPaths()resolves from the atomic install directory, never fromcwd, so it cannot reintroduce host-repository extension loading.4 — session file. Every element confirmed at 0.9.16: root
${HOME}/.atomic/agent/sessionswithATOMIC_CODING_AGENT_DIRoverride (config.ts:241-254,359-364,466); per-cwd directory (core/session-manager-paths.ts:8-15, empty diff); filename<timestamp>_<session-id>.jsonl(core/session-manager-entries.ts:62-65);--session-idpinning it (args.ts:136-137->main-session.ts:233->core/session-manager-core.ts:127-151); one compact JSON line per entry (core/session-manager-storage.ts:194, no pretty-printing); and the cancellation record withstopReasona field on the assistant message itself (core/agent-session-prompt.ts:319).CURRENT_SESSION_VERSION = 3atcore/session-manager-types.ts:5— checked explicitly at all three tags, never bumped. The one realsession-manager-storage.tschange (commitabb3a308) reorderspersistAppendedEntrybranches, but only along theflush()/workflow-stage path, unreachable from the plain interactive launch firstmate performs.5 — model flags.
--providerstill pins (core/model-resolver-cli.ts:116-123, byte-identical file),--modelstill accepts a bare id viaresolveRawExactModel(:15-56), and--list-modelsstill printsprovider, model, context, max-out, thinking, images(cli/list-models.ts:60-111, byte-identical), restricted to credential-holding providers with no network call (core/model-runtime-snapshot.ts, byte-identical). One benign delta:main.ts:668now emits startup diagnostics before the list-models branch, on stderr only, so the stdout table a preflight parser reads is untouched.6 —
--thinking.VALID_THINKING_LEVELS = ["off", "minimal", "low", "medium", "high", "xhigh", "max"]atcli/args.ts:67, byte-identical text at the same line number in all three tags. Seven levels, none added or removed. An out-of-range value still pushestype: "warning"(args.ts:158-166), andmain.ts:314-320exits only ontype: "error", so a bad level still degrades to the default with exit 0 rather than failing the spawn. Per-model clamping unchanged (core/sdk.ts:213-218).7 — tool registration.
registerToolatcore/extensions/api-types.ts:141-143anddefineToolatcore/extensions/tool-types.ts:120are byte-identical (the latter file has an empty diff); only line numbers shifted, from new event types added earlier in the file. All 22registerTooland 2defineToollocation deltas are line-number churn or internal call-site restructuring within atomic's own bundled packages. The@earendil-works/pi-coding-agentalias still resolves to the same target as@bastani/atomic(core/extensions/loader-virtual-modules.ts:458-460), and the public barrel'screate*export set changed only by addition (the PowerShell family): zero removals, zero renames.createExtensionAPIdid change return shape, but it is exported from nopackage.jsonentry, so no out-of-tree extension touches it.For the record on a pre-existing trap:
createGrepToolDefinitionis defined internally at both tags but was never in the public barrel at either, so the pi-vs-atomic naming divergence PR 26 worked around predates this window and is unaffected by it.8 — intercom always enabled. This is the one genuine behaviour change, and it is breaking as a capability: every opt-out is gone. The
enabledfield, itstruedefault, and its parse branch were deleted frompackages/intercom/config.tsoutright, along with both consumption sites (index-heavy.ts:395,lifecycle.ts:71).packages/intercom/CHANGELOG.md:23states it plainly. Enforcement is layered and deliberate:mandatory: trueon the package (core/builtin-packages.ts:33), a newcore/mandatory-runtime-tools.tswith a WeakSet anti-spoofing guard, anisMandatoryRuntimeToolshort-circuit ahead of allow/denylist checks (core/agent-session-tool-registry.ts:21), re-injection plus a hard throw incore/mandatory-resource-loader.ts:13-32, called unconditionally fromcore/sdk.ts:145, andstageHasIntercomAccess()reduced toreturn true(packages/workflows/src/shared/intercom-group.ts:46). Upstream's own acceptance matrix enumerates every plausible opt-out and confirms each fails, so this is intentional and exhaustively checked, not an oversight.What it does not do: no footer change, no startup dialog, no new approval surface. Intercom's only confirm is gated on
confirmSend(default false) andctx.hasUI, which is false for a headless session, so that branch is structurally unreachable for an unattended worker. Registration alone is inert; the broker stays lazy until a surface fires.Three consequences a maintainer should weigh before deploying, none of which invalidate recorded evidence:
intercom, including theaskaction, which blocks the tool call for up toDEFAULT_REPLY_TIMEOUT_MS = 10 * 60 * 1000(packages/intercom/reply-waiter.ts:27). For a worker with no peer that is a real ten-minute stall per call. It would present as busy, not wedged, so a supervisor watching liveness would not flag it.~/.atomic/agent/intercom/broker.sock, keyed byATOMIC_CODING_AGENT_DIR. The socket scheme predates 0.9.16; what is new is thatenabled: falseno longer avoids it.@bastani/intercomfails to load,mandatory-resource-loader.ts:31now throws and aborts session creation, where at 0.9.15 an optional bundled extension's load failure did not.Evidence invalidated in firstmate PRs 26, 27, 28, 29
None. Empty, and evidenced across the full
0.9.13..0.9.16chain rather than the narrower window the task named.All seven surfaces those PRs rest on are
unchangedin both windows. The0.9.13..0.9.15window is large (+140849 lines) but the size is one structural event:@earendil-works/pi-ai, an external dependency pinned to 0.84.1, was vendored into the monorepo aspackages/aiand every import site mechanically rewritten to@bastani/pi-ai. Nearly every touched file shows only import-line churn.That vendoring created the one case needing cross-repository proof.
clampThinkingLevel, which surface 6 depends on, did not exist in the atomic repo at 0.9.13 — it lived in the external dependency. So "unchanged" could not be established from atomic's history alone. Diffing the vendoredpackages/ai/src/models.tsat atomic 0.9.15 againstv0.84.1of the upstreamearendil-works/picheckout returned empty: a byte-for-byte copy of the exact source 0.9.13 depended on.Surface 8 is the only changed surface, and no recorded evidence rests on it: firstmate contains zero references to intercom in any file — code, config, doc, or test. Its risk is prospective operational exposure, itemised above, not retroactive invalidation.
Not done
No deploy. No
clan machines update, no host state change of any kind. No other package bumped;0.9.17-alpha.1untouched.