Skip to content

Preserve the published FStack runtime baseline alongside inherited PATH policies - #187

Closed
CoreyShupe wants to merge 28 commits into
mainfrom
feat/environment-cpu-ram-configuration
Closed

CoreyShupe wants to merge 28 commits into
mainfrom
feat/environment-cpu-ram-configuration

Conversation

@CoreyShupe

Copy link
Copy Markdown
Collaborator

Purpose

Follow-up to #186: FStack previously shipped runtime 582643c98ef0f85ead9996c70dd22cea31badcf4, which contains existing provider/coordination APIs absent from main. Pinning main's #186 release fails FStack native checking with missing external-child-report, owner-Chat follow-up and turn-completion APIs.

This standalone PR incorporates only that exact previously published baseline, preserving its behavior plus #186's inherited read-only PATH policy. It does not modify any other PR or branch or incorporate newer draft-branch work. Owner explicitly requested our own PR rather than changing other PRs.

Compared with the previously shipped revision, the combined tree differs only in the three reviewed #186 files and rustfmt of one existing assertion in src/state.rs.

Validation

  • Full workspace rustfmt check passes with official Rust 1.97 formatter.
  • Local cargo test --offline --all-targets --all-features refuses missing cached clipboard-rs; no local test pass claimed.
  • Local Clippy component is unavailable. Required hosted lint/tests/headless gates must pass before merge.
  • No machine updates, restarts, deployment dispatch, environment lifecycle changes or canary.

After this PR's exact merged SHA is published as runtime-<SHA>, FStack will pin and validate it. The older #186 release alone is not API-compatible with FStack's existing runtime baseline.

QuillDev and others added 28 commits September 23, 2026 15:19
A broker that serves many machines from one sign-in, such as the FStack
dashboard, can now supply Claude and ChatGPT access tokens through
SetProviderAccountCredential with kind oauth_brokered. Providers rotate
refresh tokens, so the broker must be the only refresher: a brokered
credential carries no refresh token, Nakode never refreshes it, and once it
expires commands fail with a message beginning credential_refresh_required.

Each adapter validates its own brokered shape. Replacement credentials now
reach running Claude sessions in place through UpdateCredential, as they
already did for ChatGPT, so a periodic token replacement never interrupts
work.

cargo fmt and clippy (pedantic, -D warnings) are clean. The all-target suite
passes except tools::tests::bash_skips_unchanged_successful_validation_until_
reason_or_state_change, which fails identically on origin/main.
With several eligible accounts and none in automatic routing, session
creation refused outright even though one account was the owner's default.
A machine holding its own sign-in beside a brokered account could not start
a Claude session at all. The eligible default is now the choice; without one
the owner must still pick.
A session no longer belongs to a provider account. Where a turn begins the
runtime keeps the session's last or requested account while it is eligible
and otherwise routes to any eligible one; commands inside a running turn stay
on the account running it. Codex, Claude, Kimi and GLM take the new account's
credential into the live handle, and a start or resume loads into a fresh
handle on it. sessions.account_id records where a session last ran and is no
longer enforced: the affinity conflicts, the historical-session refusal and
the in-use account refusal are gone, and removing an account frees its
sessions. Codex reasoning is tagged with the ChatGPT account that produced it
and replayed only to that account, since its encrypted content opens for no
other.
Every backend event of an ordinary session logged "durable inbound replay
deferred" because the missing bridge record surfaced as an error.
The Claude SDK owns Claude history, so after a restart a read of a session
that is not loaded had nothing to project and failed until the session was
reopened. The bridge now leaves its history after every turn and resume,
and the retained read projects it.
Account variables such as GH_TOKEN and the GitHub credential helper reached
only Nakode's own shell tools; Claude's Bash ran with the bridge's
environment, so gh and git push could not authenticate.
One short-lived bridge reads each snapshot-less Claude session's transcript
without resuming it, so sessions from before snapshots existed read back
too. An unreadable transcript keeps no snapshot rather than an empty one.
Every mutation, including each streamed chunk, cleared the prefix proofs,
and the next page read serialized and hashed every entry again. Entry
digests are now kept beside the exact entry they came from and reused while
it is unchanged; each proof chains the previous one with the next entry's
digest. A rebuilt unloaded session reuses its last digests. Proof values
change once (v2 tag); clients only compare them.
History rebuilt from the Claude SDK kept a call's input and output only in
its body, so resumed and unloaded transcripts showed raw JSON instead of the
command, edit and search rows live calls get.
History rebuilt from the Claude SDK had no provider, so restored thinking
fell back to a generic notice instead of the thinking trace a live turn
shows. Owner messages stay unattributed.
Where the machine gives agents a desktop (DISPLAY, xdotool, ffmpeg), three
tools appear: desktop_screenshot, desktop_action (click, drag, scroll,
type, keys) and screen_record. Recordings drop repeated frames, hold the
last one, and compress to H.264 within 8 MiB into the stack Gallery with a
poster frame. Claude sees each screenshot, including one after every
action; native tools save it for the vision tool.
The bridge always launched `claude` from PATH, so a machine without Claude
Code installed, such as an environment VM, listed no Claude models and
could not start a turn. It now uses a configured or installed Claude Code
and otherwise the platform build the Agent SDK installed.
…r-credentials

# Conflicts:
#	docs/coordination-messages.md
Claude Code offers one model twice, with its standard and its 1M-token context window (opus and
opus[1m]); names leave the window out, so both read "Opus 5.5". Where names would repeat, the row
whose identifier asks for a window now says so: "Opus 5.5 (1M context)".
A Chat on a machine and the agent it started inside a stack VM run in two
runtimes, so no session_child_links row joins them and the child's final
report never reaches the parent. AdmitExternalChildReport lets the
authenticated integration that recorded the relationship relay the report:
it enters the parent's durable inbox exactly as a linked child's report
does (durable_child_evidence, inert, never owner instruction), deduplicated
by message identity, and the idle parent is activated to process it. The
runtime advertises ExternalChildReports.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A parent in another runtime needs the same report a linked parent receives.
The runtime already captures each terminal turn's bounded completion and
persists it with the session; keep it on LastTurn and project it as
last_turn.completion through the protocol view and gRPC.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@CoreyShupe CoreyShupe closed this Oct 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants