Skip to content

fix(web): close project actions before editing - #149

Closed
yaacovcorcos wants to merge 2 commits into
mainfrom
fix/project-actions-menu-close-20260728
Closed

fix(web): close project actions before editing#149
yaacovcorcos wants to merge 2 commits into
mainfrom
fix/project-actions-menu-close-20260728

Conversation

@yaacovcorcos

Copy link
Copy Markdown
Contributor

Problem and user outcome

Choosing Edit from a project action's overflow menu could leave the menu logically open behind the edit dialog. Users should get one clean transition: the menu closes, the dialog receives focus, and the project action is not accidentally executed.

This draft makes the project-actions menu controlled and closes it immediately before opening the existing edit dialog. No appearance, layout, copy, motion, or responsive behavior changes.

Scope

  • apps/web/src/components/ProjectScriptsControl.tsx
    • Own the existing menu's open state with one local boolean.
    • Close that menu before selecting the script and opening the existing edit dialog.
    • Preserve the existing pointer/click propagation guards that prevent Edit from running the action.
  • apps/web/src/components/ProjectScriptsControl.browser.tsx
    • Add a hosted browser regression covering real pointer activation, dialog focus, menu removal, non-execution, Escape without menu resurrection, reopening, and subsequent normal action execution.

File impact: 2 files, +50/-2. No persistence, migration, provider, protocol, credentials, packaging, updater, or release changes.

Upstream provenance and disposition

  • Source: pingdotgg/t3code
  • Donor commit: f0121f31d0e7c069f4007480fc13907c28efd4d5
  • Donor license: MIT
  • Disposition: Scient-owned behavioral reimplementation, not a cherry-pick.
  • Intentional divergence: T3 controls two donor-specific menus with an object; Scient has one relevant menu, so one colocated boolean is the narrowest owned seam.

Exact base and head

  • Base: 8f4403d7d0294132775b2f40282eb2b22edeb887
  • Head: f2c7473a964dc72fa004267b7f23ffeac5014e4a
  • Branch: fix/project-actions-menu-close-20260728

Verification

  • bun run scient:upstream-check --intake passed at b1f7e56f1 (identity, format, lint, typecheck, full bun run test, desktop build, and release smoke).
  • After the test-evidence refinement at final head f2c7473a9: targeted format and lint passed; web typecheck passed; bun run --cwd apps/web test -- src/projectScripts.test.ts passed (6/6); git diff --check passed.
  • Final worktree is clean.

Local browser, visual, screenshot, geometry, computer-use, and manual UI checks were deliberately not run. The new .browser.tsx regression is for hosted CI. Repository-required human mouse, keyboard, Escape, and focus acceptance remains pending before this PR can be marked ready or integrated.

Independent read-only reviews

All three reviewers recertified exact final range 8f4403d7..f2c7473a:

  1. Correctness, reliability, lifecycle, performance, regressions: no remaining finding. A P3 test-quality finding was resolved by using userEvent.click and asserting focus on #script-name.
  2. Security, privacy, data loss, migrations, credentials, sessions, permissions, approvals, updater/release safety: no P0-P3 finding.
  3. Architecture, maintainability, reuse, Scient identity, ownership, donor lineage, user behavior, test sufficiency, fast-lane eligibility: no P0-P3 finding.

Risk, limitations, and rollback

Risk is low and isolated to project-action menu/dialog sequencing. The production path has no data or command mutation beyond existing behavior. Hosted browser CI and human interaction acceptance are still required; this draft does not claim visual or interaction certification.

Rollback is a direct revert of commits f2c7473a9 and b1f7e56f1; there is no data migration or persistent state to undo.

Self-review

  • One bounded user behavior
  • Independent of current open PRs; no overlapping files found before publication
  • No unrelated cleanup or dependency additions
  • Exact donor provenance and intentional divergence recorded
  • Focused regression included
  • Three independent reviews complete with no unresolved P0-P2
  • Hosted browser CI complete
  • Required human UI/focus acceptance complete

@yaacovcorcos yaacovcorcos added the upstream-review Official source changes awaiting review label Jul 28, 2026
@github-actions github-actions Bot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:XS labels Jul 28, 2026
yaacovcorcos added a commit that referenced this pull request Jul 28, 2026
Promotes the certified July 28 desktop integration queue. Includes the reviewed work represented by PRs #123, #140, #141, #144, #149, #150, and aligned replacement #151 for #146. Supersedes #68 through the hardened #144 implementation. See PR #154 for exact heads, dispositions, verification, limitations, and rollback evidence.
@yaacovcorcos

Copy link
Copy Markdown
Contributor Author

Integrated through the certified desktop queue and promoted to main by #154. Exact PR head f2c7473 is preserved in the promoted queue history. Closing this source PR as integrated; its branch is preserved.

yaacovcorcos added a commit that referenced this pull request Jul 28, 2026
* Route telemetry through ScientFactory gateway (#43)

* Fix unsigned macOS release signatures (#44)

* Add consent-aware desktop analytics (#47)

* Fix Claude terminal auth and connection recovery (#52)

* fix provider status refresh invariants

* fix Claude auth recovery

* Use direct OAuth for Grok sign-in (#53)

* Use direct OAuth for Grok sign-in

* Expose safe Grok OAuth browser fallback

* Secure Scient state initialization (#48)

* Secure Scient state initialization

* Allow legacy migration state test

* fix(security): harden private state files

* test(security): lock private file boundaries

* fix(security): reject unsafe private file nodes

* Supervise the desktop backend lifecycle (#49)

* Supervise the desktop backend lifecycle

* fix(desktop): preserve backend lifecycle ownership

* fix(desktop): replace semantically unready backends

* fix(desktop): close backend lifecycle races

* Supervise desktop connection recovery (#50)

* Supervise desktop connection recovery

* Isolate provider dialog browser fixtures

* fix(desktop): bind activation readiness generation

* fix(web): enforce single-owner connection recovery

* style(web): format connection recovery

* fix(web): satisfy connection transport types

* fix(web): harden stream and terminal recovery

* fix(web): fail closed on stuck stream cancellation

* fix(web): preserve terminal recovery ordering

* fix(web): clamp reconnect jitter ceilings

* fix(desktop): preserve connection wake after restack

* Define safe RPC recovery policies (#51)

* Define safe RPC recovery policies

* test(web): cover RPC recovery integration

* fix(web): recover after uncertain mutation failures

* test(web): type RPC recovery harness precisely

* fix(web): recover a failed replay generation

* Surface connection recovery diagnostics (#55)

* Surface connection recovery diagnostics

* test(web): cover connection recovery experience

* style(web): format recovery browser coverage

* fix(web): keep recovery diagnostics current

* Recover Codex sessions after authentication loss (#56)

* fix: recover Codex sessions after auth loss

* fix(codex): gate auth recovery by provider mode

* fix: harden Codex authentication recovery

* Support Linux desktop development launch (#57)

* Secure Scient state initialization

* Allow legacy migration state test

* Supervise the desktop backend lifecycle

* Supervise desktop connection recovery

* Define safe RPC recovery policies

* Surface connection recovery diagnostics

* Support Linux desktop development launch

* Isolate provider dialog browser fixtures

* fix(desktop): fail closed on unsafe Linux sandbox

* style(desktop): format Linux launcher hardening

* fix(release): preserve AppImage sandbox

* revert(release): keep AppImage migration out of launcher hardening

* fix(desktop): honor Linux user namespace sandbox

* Fix Antigravity browser authentication (#59)

* Fix Antigravity browser authentication

* Harden Antigravity authentication lifecycle

* Close Antigravity code window deterministically

* Keep Antigravity code submission cancellable

* Scope desktop signing credentials by platform (#60)

* Fix managed Antigravity updates, authentication, and dialog UX (#62)

* Fix trusted Antigravity install and update routing

* Fix Antigravity browser authentication and models

* Refine provider connection dialog actions

* Harden managed provider update recovery

* Stabilize macOS release identity (#63)

* Reduce unintended macOS permission prompts (#64)

* Stabilize macOS release identity

* Reduce unintended macOS permission prompts

* Apply repository formatting

* Control macOS notarization lifecycle (#65)

* Add Evidence to Note as a latent built-in (#70)

* Harden bidirectional chat rendering (#71)

* feat(web): harden bidirectional chat rendering

* fix(web): close bidi review gaps

* Add Medical Exam Study built-in (#72)

* Fix YAML frontmatter in Markdown previews (#69)

* Add T3-inspired project source dialog (#76)

* Add project source dialog

* Harden project source cloning

* Add T3-style right dock surfaces (#77)

* Add T3-style right dock surfaces

* Fix right dock test formatting

* fix: remove AppSnap startup announcement (#80)

* Add artifact preview cards to chat (#81)

* fix: select providers after connection (#82)

* Add message-level conversation forks (#78)

* Add message-level conversation forks

* Stabilize hosted fork browser test

* Close message fork boundary gaps

* Close final fork review gaps

* Resolve final fork recertification blockers

* Avoid replaying completed fork bootstrap

* Harden fork lineage and restart recovery

* Stabilize cold browser geometry startup

* Repair legacy fork title families

* Preserve unrecorded fork rename boundaries

* Clear drifted fork title lineage

* Improve desktop contribution workflow (#75)

* Set default base font to 15px and fix numeric editing (#79)

* Increase default base font size to 15px

* Fix manual font size editing

* Preserve external font setting updates

* Use recommended provider model defaults (#83)

* Use recommended provider model defaults

* Apply repository formatting

* Update browser expectation for Codex default

* Preserve explicit drafts before model discovery

* Respect live provider model availability

* Align desktop approval policy (#85)

* Fix release-candidate regressions (#86)

* Fix release candidate regressions

* Fix long transcript fork validation

* fix(release): preserve Linux sandbox (#87)

* fix(release): preserve Linux sandbox

* test(release): resolve nested builder package

* test(release): follow Bun package symlinks

* fix: preserve whitespace in folder browsing (#90)

* Collapse long assistant artifact shelves (#91)

* Remove project setup confirmation card (#93)

* Build unified notification system (#96)

* Hide provider setup banner on empty chats (#94)

* Hide provider setup banner on empty chats

* Stabilize empty provider banner coverage

* Harden provider banner browser readiness

* Fix Droid model discovery lifecycle (#95)

* Add ChatGPT-first voice transcription with local Whisper fallback (#97)

* feat(voice): define transcription backend contract

* feat(voice): add verified local transcription core

* Fix ChatGPT voice account context

* feat(voice): add ChatGPT-first local Whisper fallback

* Default Git writing to GPT-5.6 Luna (#99)

* Apply updated settings defaults once (#101)

* Apply updated settings defaults once

* Enable Studio in its browser fixture

* Improve voice dictation and active-turn composer controls (#102)

* Improve voice recording controls

* Add live local voice previews

* Keep voice send locked through completion

* Keep active-turn composer actions available

* Pin Whisper runtime source revision

* Fix voice transition regressions

* Fix folder picker navigation and project opening (#98)

* Fix folder picker navigation and project opening

* Tighten project setup choices

* Prevent duplicate folder picker submissions

* Fix Whisper runtime packaging on Windows (#104)

* fix: make Whisper packaging cross-platform safe

* fix: verify signed Windows Whisper runtime

* Secure HTML artifact previews with isolated execution (#100)

* feat: add secure HTML artifact previews

* fix: enforce HTML preview ownership boundaries

* Document cross-platform manual verification

* Use trash icon for voice cancel action (#106)

* Fix browser pane close and runtime recovery (#113)

* Isolate temporary Claude discovery from MCP servers (#116)

* Respect reduced motion in thread spinner (#84)

Adapt the upstream accessibility concept while retaining Scient-owned spinner geometry.

* Harden upstream-derived release tooling (#109)

* Salvage safe PR 61 interaction improvements (#107)

* Salvage safe PR 61 interaction improvements

* Harden terminal selection copy handling

* Adapt Studio Git gating and folder access (#108)

* Adapt Studio folder controls from Synara

* Gate Studio review command on repository detection

* Improve changed-file accessibility and density (#110)

* Add compact previews for bulky changed-file cards (#117)

* Improve changed-file accessibility and density

* Add compact changed-file previews

* Ensure changed-file previews show every file

* feat: add curated in-app release notes (#112)

* feat: add curated release notes workflow

* fix: harden release note experience

* refactor: share release note footer layout

* test: keep release note diagnostics concise

* Reject developer-facing release note copy

* Revert "Reject developer-facing release note copy"

This reverts commit 1006003.

* Harden release note structural validation

* Harden release note asset validation

* Resolve release note certification findings

* Bound release note PNG chunk parsing

* Validate all release note PNG chunk CRCs

* Fix browser multi-tab controls and menu occlusion (#119)

* Fix browser multi-tab controls and menu occlusion

* Keep browser sessions alive under overlays

* Harden browser overlay lifecycle coverage

* Complete browser tab and overlay semantics

* Restore focus after final browser tab closes

* Synchronize split-pane browser focus

* Harden Electron overlay lifecycle runner

* Isolate macOS Electron test bundle state

* Keep Electron lifecycle tests fully hermetic

* Resolve Electron sandbox from workspace package

* Guarantee Electron test harness cleanup

* Register Electron fixture cleanup immediately

* Restore focus after browser close controls

* Complete browser close focus recovery

* Handle early Electron test interruptions

* Cover earliest Electron setup interruption

* Refine branch and automation workflow affordances (#111)

* Refine upstream-derived workflow affordances

* Respect resolved automation triage state

* Fix native branch clipboard acceptance

* Document native workflow UX acceptance

* Add universal local file viewer (#114)

* Add universal local file viewer

* Harden local HTML preview capabilities

* Resolve HTML preview review blockers

* Close final HTML preview review gaps

* Fail closed on truncated active HTML

* Preserve complex HTML preview dependencies

* Fail closed on SVG runtime link mutation

* Block alternate network egress in HTML previews

* Recover HTML preview network setup

* Serialize HTML preview retries

* Occlude native HTML previews under overlays

* Harden provider installation and sign-in (#103)

* Harden provider installation and sign-in

* Fix Windows provider runtime test fixtures

* Make Windows PATH test path-stable

* Close provider onboarding reliability gaps

* Keep post-install sign-in recovery on the correct path

* Canonicalize Windows runtime discovery test paths

* Harden provider device-code recovery

* Harden OpenCode and Kilo turn completion (#120)

* Harden OpenCode and Kilo turn completion

* fix(provider): isolate OpenCode turn completion ownership

* fix(provider): close OpenCode completion review races

* fix(provider): fence OpenCode reply and replay races

* fix(provider): clean interrupted OpenCode replies

* fix(provider): harden OpenCode interaction ownership

* fix(provider): fail closed on ambiguous replies

* Harden OpenCode lifecycle retirement

* Serialize OpenCode session retirement

* Make OpenCode retirement interruption safe

* Finalize confirmed OpenCode process exits

* Add native folder drop to Add Project (#115)

* feat(projects): add native folder drop intake

* fix(projects): harden folder drop feedback

* fix(projects): keep folder errors visible

* fix(projects): preserve compact folder dialog footer

* fix(projects): harden native folder intake

* docs(qa): align folder intake evidence

* fix(projects): scope folder drop to dialog

* test(projects): cover platform folder labels

* docs: correct folder drop verification evidence

* docs: qualify native drag evidence

* docs: refresh folder drop verification evidence

* docs: refresh folder drop certification evidence

* docs: recertify folder drop on latest main

* Neutralize project drops outside dialog

* Update folder drop acceptance evidence

* Make new thread workspace intent explicit (#118)

* fix(web): make new thread workspace intent explicit

* fix(web): serialize distinct new thread intents

* test(web): type exact workspace branch mocks

* fix(web): preserve new thread request ordering

* fix(web): preserve latest new thread intent

* fix(web): coordinate all new thread navigation

* fix(web): preserve latest navigation across preparation

* fix(web): close remaining navigation races

* chore: clean merged sidebar imports

* fix(web): close terminal and route ownership gaps

* fix(web): coordinate every new-thread route intent

* fix(web): enforce route ownership before history commits

* test(web): use typed routes in navigation guard proof

* fix(web): release committed navigation ownership

* Show active file explorer toggle state (#124)

* Prevent background Cursor login browser launches (#125)

* Guard released migration lineage and dependencies (#129)

Adds a fail-closed, read-only release guard for shipped migration history and reviewed runtime dependency resolution.

* build(deps): bump actions/checkout from 7.0.0 to 7.0.1 (#131)

Update every retained workflow use to the verified immutable v7.0.1 commit.

* Bound settled attachment sync generations (#132)

Retire settled generation markers while preserving stale-write suppression and prior pending ownership after synchronous staging failure.

* Use lightweight snapshots for PR polling (#133)

Adapt Synara PR polling on a Scient-owned project-only query seam. Preserve active-project filtering and schema normalization, prove live-layer wiring, and avoid hydrating unrelated thread/session/turn state.

* Advance Synara review checkpoint to July 26 (#134)

* chore(upstream): advance reviewed Synara checkpoint

* chore(upstream): include late lifecycle review

* Prove packaged macOS and Windows startup before release (#121)

* test(release): prove packaged desktop startup

* Close packaged startup proof gaps

* Preserve packaged smoke isolation

* Avoid duplicate Windows tree kills

* Harden packaged smoke process cleanup

* Harden packaged startup proof acceptance

* Close packaged startup certification gaps

* Close exact packaged startup proof gaps

* Bound packaged smoke process cleanup

* Harden packaged startup release proof

* Close packaged startup review findings

* Keep startup proof test lint-clean

* fix(release): close packaged startup proof gaps

* fix(release): harden packaged startup cleanup

* fix(release): authenticate startup ownership records

* fix(release): bind cleanup to process instances

* fix(release): type cleanup authorities explicitly

* fix(release): close final startup proof findings

* fix(release): contain packaged startup by OS identity

* fix(release): fail closed after sentinel loss

* fix(release): close packaged cleanup containment gaps

* fix(release): fail closed on startup cleanup uncertainty

* fix(release): authenticate Windows startup verifier

* ci(release): exercise Windows startup launcher

* fix(release): close packaged startup proof gaps

* fix(release): harden packaged startup certification

* Fix packaged startup reconnect hydration

* fix(release): bind packaged startup containment lifetime

* fix(release): request sentinel cleanup over IPC

* fix(release): bind Windows verifier authority to pipe

* Bound repeated desktop backend crash restarts (#126)

* fix(desktop): bound backend crash restarts

Adapt the bounded supervision lessons from Synara commits 83b685234b2c474ea4d9a6ce593ac730ca95f8f7 and 5495a6e81e4da80e996867a1c487c9546cbd0196 onto Scient's existing generation-safe supervisor. Require post-readiness stability before resetting retry history, pause after repeated failures in a rolling window, and surface local log guidance without importing Synara's database-recovery architecture.

* fix(desktop): make backend crash recovery actionable

* fix(desktop): retain recovery dialog when logs fail

* fix(desktop): preserve crash recovery guarantees

* fix(desktop): suppress crash recovery while quitting

* fix(desktop): harden crash recovery diagnostics

* fix(desktop): preserve backend breaker through updater recovery

* test(desktop): prove native crash-breaker recovery

* fix(desktop): preserve crash-breaker recovery

* fix(desktop): preserve crash history across updater recovery

* test(desktop): prove updater crash recovery wiring

* fix(desktop): preserve shutdown authority during updater failure

* test(desktop): wait for native recovery accessibility

* test(desktop): isolate crash recovery acceptance

* test(desktop): bind recovery fixture process identity

* fix(desktop): retain quit authority during update handoff

* fix(desktop): restart after failed updater stop

* Keep diff mode and Git status refresh responsive (#127)

* fix(web): keep diff and git status refresh responsive

Adapted from Synara 807acfe3c784b41229b81c4b78957681ec8e6cb2.

Remount the third-party diff renderer when its mount-time view mode changes, use the shared menu radio primitive, and prevent branch-discovery races or non-repo workspaces from starting a permanent Git-status invalidation loop. Add focused regression coverage for each boundary.

* fix(web): ignore stale Git status before repository confirmation

* fix(web): require exact branch status for git actions

* fix(git): preserve branch authority across actions

* fix(git): serialize repository mutations

* fix(git): cover repository mutation workflows

* style(server): apply repository formatting

* fix(git): isolate live mutation authority contracts

* fix(git): overlay live mutation RPC authority

* test(web): align stacked action transport contract

* Keep local HTML previews live across source changes (#130)

* fix(desktop): keep local HTML previews live

* fix(desktop): harden live preview refresh

* fix(web): clear stale HTML preview errors

* fix(web): report queued preview refresh failures

* fix(desktop): release retired preview session hooks

* fix(browser): preserve refresh ownership and latest revision

* fix(browser): close live preview certification gaps

* fix(browser): close live preview review findings

* fix(browser): close final live preview review findings

* fix(browser): close exact-head preview review findings

* test(browser): cover preview discovery limits

* fix(browser): preserve optional preview limit metadata

* test(browser): require prepared source authority

* fix(browser): attest local preview capabilities

* fix(html-preview): harden atomic refresh authority

* fix(html-preview): close source watch startup gap

* fix(desktop): close live preview review gaps

* fix(desktop): close preview ownership failure gaps

* fix(html-preview): close remaining security boundaries

* fix(html-preview): pin inspected file versions

* fix(html-preview): serve attested document bytes

* Stop duplicating completed replies in Activity (#135)

* Stop duplicating completed replies in Activity

* Prove Activity completion ownership in Chromium

* Synchronize completion regression assertions

* Show fork provenance in conversation timelines (#136)

* Show fork provenance in transcripts

* Keep unavailable fork provenance truthful

* Require confirmed provider updates (#137)

Gate the Settings > Providers Update action behind a confirmed fresh version check, and harden the confirmed-update boundary so the updater child process only ever spawns against a probed, certified, and re-validated target (closes six concurrency/TOCTOU windows). See PR description for full details.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* Fix oversized transcript–composer gap when a task panel is showing (#138)

* Fix oversized transcript–composer gap when a task panel is showing

The composer is a flex sibling below the transcript, so the stacked composer
chrome (live-changes header, active task list, queued follow-ups) already
reserves its own vertical space through the flex layout. The transcript then
fed that same chrome height into its in-list bottom spacer
(bottomContentInsetPx = composerStackedChromeHeight + 8), reserving the space a
second time. The result was a large, growing gap between the last message and
the composer whenever a task/stacked panel was present, while the no-task case
(spacer at its 64px baseline) already looked correct.

Remove the double reservation: the transcript's bottom spacer is now a fixed
64px in every state, matching the perfect no-task gap. This also retires the
now-vestigial bottomContentInsetPx prop chain (ChatView → ChatTranscriptPane →
MessagesTimeline / AgentActivityDetailView), collapsing both consumers to their
constant baseline and correcting the misleading "composer overlaps / reserves
matching bottom space" comments.

composerStackedChromeHeight is kept for its real remaining job: the
scroll-compensation layout effect that keeps the transcript pinned to its end as
the flex viewport shrinks while the chrome grows.

- Task-present gap now equals the no-task gap (single flex reservation).
- Agent activity detail view uses the same fixed baseline (it was also
  double-counting).
- No behavior change to the no-task case.

Verified: oxfmt, oxlint (0 errors), tsc --noEmit (web), and the affected
component/scroll unit tests (106 passing).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* Add regression coverage for the transcript–composer gap fix

Prove the stacked composer chrome is reserved only once: a
[geometry:linux] browser test mounts ChatView with an active task card
and again once the turn settles (no card), then asserts the gap between
the transcript tail and the composer stack is unchanged. It anchors on
the tail spacer's top (the true end of transcript content, past any
live-turn activity indicator) so a running turn does not confound the
measurement.

Verified the test fails on the pre-fix code — the gap balloons to
~180px when the task card appears — and passes on the fix (~44px in
both states).

Adds two stable test hooks: data-chat-composer-stack on the composer
block wrapper and data-testid="transcript-bottom-spacer" on the list
tail spacer.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>

* Fix file links failing to open across git worktrees (#139)

* fix(server): resolve workspace file links across git worktrees

Bare/partial file references (e.g. a chat link to `kanbanDispatch.ts`)
could fail to open with a misleading "no such file" error even though the
file plainly exists. Two root causes:

1. The filesystem-walk index descended into linked git worktrees, so a
   single logical file was indexed multiple times (the real checkout plus
   each worktree copy). The suffix resolver treats multiple matches as
   ambiguous and gave up, and the read then surfaced the realpath ENOENT
   for the literal (non-existent) path. Indexing the duplicates also
   inflated the index toward its 25k-entry cap, truncating it.

2. On a genuine ambiguity the resolver returned null, which the reader
   reported as ENOENT -- a "file not found" message for a file that exists.

Changes (server-only):
- Prune linked git worktree subtrees from the index walk (a worktree
  records `.git` as a regular file pointer, the reliable discriminator),
  and skip `.git` entries whether file or directory. Extract the shared
  worktree/skip predicates.
- Rework resolveWorkspaceFileBySuffix to return a structured result
  (resolved | ambiguous | unresolved). Resolve only on a single distinct
  match; report the competing paths on a true ambiguity instead of
  guessing between different files.
- When the cached index is truncated (unreliable), re-scan the tree
  directly (bounded) for a trustworthy candidate set.
- Surface an honest, actionable error listing the competing files instead
  of a false ENOENT. Reuses the existing WorkspaceFileSystemError tag, so
  no contract/client change.

Tests: worktree pruning, unique/ambiguous/unresolved resolution, the
worktree-duplicate scenario end-to-end, and the truncated-index disk
re-scan.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(server): don't prune submodules; fail closed on incomplete suffix scan

Follow-up correctness fixes to the worktree-aware file-link resolution.

1. Submodule false-prune. The worktree detector treated *any* directory
   whose `.git` is a regular file as a linked worktree and pruned it. Git
   submodules also store `.git` as a file, so their subtrees were pruned
   too -- silently hiding submodule files from search and link resolution.
   Discriminate by the `gitdir:` pointer target: prune only when it points
   into `.git/worktrees/<name>` (a linked worktree), never when it points
   into `.git/modules/<name>` (a submodule). Reading the pointer fails open
   (do not prune) so an unreadable `.git` can never hide real files.

2. Incomplete-scan false-unique. The bounded disk re-scan (used when the
   index is truncated) returned whatever it had found when it hit the
   scanned-directory cap. A single match found before the cap was then
   reported as a unique "resolved" even though a second match could sit in
   the unscanned remainder -- risking opening the wrong file. The scan now
   reports whether it completed, and classification fails closed to a new
   "indeterminate" outcome when an incomplete scan saw fewer than two
   matches. The reader surfaces an honest "too large to resolve, use a
   fuller path" error instead of guessing or falsely claiming ENOENT.

Tests: submodule files stay resolvable and searchable (not pruned); the
disk scan reports incomplete at its directory cap; classification fails
closed (single match from an incomplete scan -> indeterminate, two
distinct matches -> ambiguous even when incomplete, empty complete scan
-> unresolved). The existing linked-worktree fixtures now use realistic
`.git/worktrees/<name>` pointer contents.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>

* fix(web): guard Enter during IME composition in message composers (#143)

CJK/Japanese/Korean IMEs use Enter to confirm a candidate. An unguarded
Enter-to-send handler treats that confirmation keystroke as "send" and
submits a half-composed message.

Add a shared isImeCompositionKeyEvent() helper (isComposing || keyCode
=== 229) and apply it at the two message-composer key handlers:

- ComposerCommandKeyPlugin, the shared chat + kanban Lexical handler:
  swallow Enter fired mid-composition before it reaches the send/menu
  logic. Lexical already drops keydowns while editor.isComposing() is
  true, but on Safari/WebKit compositionend fires before the confirming
  keydown, so that Enter still dispatches KEY_ENTER_COMMAND; the
  keyCode === 229 branch closes that gap.
- PullRequestCommentComposer, a plain <textarea> with no Lexical gate,
  replacing its isComposing-only check so a keyCode-229 confirm no
  longer submits.

Value: correct multi-language text entry; no accidental send on IME
candidate confirmation.

Out of scope (follow-up): other bare-Enter inputs (project/rename/search
fields) share the hazard and could adopt the same helper.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>

* feat(web): self-host UI fonts, drop Google Fonts CDN (#142)

Remove the runtime Google Fonts <link> from index.html and self-host the
needed families (Geist, Geist Mono, Inter) via @fontsource-variable/*
packages, alongside the JetBrains Mono face already bundled. DM Sans was
listed in the CDN link but has zero references, so it is dropped rather
than self-hosted.

The @fontsource-variable packages register their @font-face under a
"<Family> Variable" name (e.g. "Inter Variable") while themes store the
plain family name, so add expandBundledVariableFontAliases() and apply it
at the theme->CSS-variable emission boundary: the bundled face is matched
and the plain name is kept after it as a fallback.

Value: offline usability, no third-party font beacon on launch, no font
flicker. The default appearance (systemUiFont + JetBrains Mono fallback)
needs no Google fonts, so removing the CDN cannot regress it.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>

* Make new-chat project selection safe across draft and project lifecycles

Integrate the reviewed project-picker interaction and project-lifecycle safety fixes. Complete local certification, three independent final reviews, hosted CI, and manual native visual acceptance passed.

* fix(desktop): preserve Windows Ctrl-minus zoom (#148)

* fix: preserve Windows Ctrl-minus zoom

Adapted from Synara 94b59220e26bc337406110c84220aec76b065490.

* fix: preserve shortcuts help chord compatibility

Keep the Windows physical-minus disambiguation scoped to Windows while retaining the existing Meta-or-Ctrl slash behavior on every platform.

* fix: align Windows minus shortcut routing

* Promote certified desktop integration queue (#154)

Promotes the certified July 28 desktop integration queue. Includes the reviewed work represented by PRs #123, #140, #141, #144, #149, #150, and aligned replacement #151 for #146. Supersedes #68 through the hardened #144 implementation. See PR #154 for exact heads, dispositions, verification, limitations, and rollback evidence.

* Promote certified desktop queue + v0.5.14 release note into main (#155)

* Add Claude Opus 5 capabilities

* Harden Claude capability discovery and Opus gating

* Refresh Claude discovery results

* Fail closed on Claude capability boundaries

* Scope Claude discovery to the exact runtime

* Bind Claude Opus 5 to the exact runtime

* Harden Claude Opus 5 runtime gating

* Keep Claude fresh defaults available

* fix(claude): isolate discovery lifecycle generations

* fix(claude): bind discovery cache generations

* test(web): bind Claude prefetch generation keys

* fix(claude): authorize Opus 5 from exact runtime

* fix(claude): make discovery generations monotonic

* Fix provider runtime extraction and setup progress

* fix(claude): harden discovery lifecycle ownership

* fix(claude): generation-key native slash-command discovery

Native slash-command discovery now participates in the same
renderer-owned discovery-generation scheme already used for model and
agent discovery, so a command catalog fetched under one auth/runtime
generation can never leak into a newer one.

- contracts: add optional discoveryGeneration to ProviderListCommandsInput
- server: fold discoveryGeneration into the listCommands in-flight cache
  key so a later auth generation never joins an older CLI's discovery
- client: bind the commands query to the current generation (query key,
  RPC arg, post-resolve stale discard, fail-fast retry, no stale
  placeholder for claudeAgent) and invalidate commands alongside agents
  on auth-sensitive provider changes
- route the configured Claude binary through every command-discovery
  call site (ChatView, kanban composer, /fast availability check)
- tests: cover generation separation for command discovery on both the
  server adapter and the React Query layer

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* feat(agent-gateway): host-served MCP read/coordination tools (Slice 1)

First slice of the agent gateway: a thread-scoped, host-served MCP
endpoint (`POST /mcp`) that lets an agent in one thread observe and
coordinate sibling top-level threads. Read/coordination only — no
send/interrupt, no create/fork. Behind a feature flag, disabled by
default (`SYNARA_AGENT_GATEWAY_ENABLED` / `--agent-gateway-enabled`).

Lift-and-reconcile of Synara's MIT-licensed agent gateway onto a
Scient-owned authorization + credential spine. `synara_*` names and
`synara/` namespaces kept intentionally (rebrand is a later pass).

New `apps/server/src/agentGateway/` subsystem:
- Transport/ingress auth: per-request bearer verify → thread-existence
  recheck → provider-ownership recheck → central authorization, with no
  cached grant; body cap (1 MiB) + batch cap (50); GET/DELETE mirror the
  disabled-state 404; top-level defect net upholds the never-fails
  contract on handleMcpPost.
- Credential spine: opaque per-thread tokens, in-memory registry (dies
  on restart), least-privilege (`thread:read` only), revoke-on-teardown.
- Central default-deny authorization: capability → project scope →
  thread-type; cross-project reads denied as thread_not_found.
- Read tools: synara_context, list_projects, list_threads, read_thread,
  wait_for_threads, backed by ProjectionSnapshotQuery.
- Claude provider injection via HTTP Authorization header (never the
  process env), flag-gated, revoked on teardown and failed install.

Shared-file injection hand-re-applied at current symbol anchors:
http.ts route registration, config.ts/main.ts flag, effectServer.ts
bound-port publish, ClaudeAdapter.ts/runtimeLayer.ts token lifecycle,
new packages/contracts/src/agentGateway.ts.

typecheck 9/9, full test suite 12/12 (agentGateway 168/12 incl. new
httpRoute.test.ts), lint 0 errors, brand:check green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(agent-gateway): keep contracts barrel frozen + format Slice 1 files

Resolves the two CI failures on this PR:

1. migration:check — Slice 1 added `export * from "./agentGateway"` to
   `packages/contracts/src/index.ts`. That barrel is a released-migration
   dependency (released migrations import `@synara/contracts`, and the
   lineage guard traverses the barrel's re-exports and fingerprints its
   runtime source). Adding the line both *modified* the frozen barrel and
   *pulled* `agentGateway.ts` into the released dependency closure, tripping
   the append-only guard.

   Fix: relocate the gateway contract into the server subsystem as
   `apps/server/src/agentGateway/contract.ts` and drop it from the barrel.
   Every consumer is server-side (no renderer/client consumer exists), so
   the shared package was never required. `index.ts` is restored byte-for-
   byte to the v0.5.13 baseline and `agentGateway.ts` leaves the closure.

2. fmt:check — donor-lifted test files and the ClaudeAdapter edits were not
   run through oxfmt. Applied `oxfmt` (formatting only; no behavior change).

Full gate green: brand, workflow, migration, fmt, lint (0 errors),
typecheck (9/9), test (12/12 packages, 2530 passed).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(agent-gateway): close read_thread disclosure oracle + revoke token on failed spawn

Two pre-merge security fixes on the Slice 1 read foundation, plus a
truthful token-exposure comment.

1. read_thread non-disclosure oracle. An unknown thread failed as a
   plain-text ToolInputError while a cross-project thread failed as a
   JSON GatewayToolError, so a caller could distinguish "no such thread"
   from "exists in another project" by response shape — defeating the
   deliberately byte-identical message. Route read_thread's not-found
   through GatewayToolError so both denials are identical in code,
   message, and JSON shape (mirrors wait_for_threads).

2. Gateway token leak on failed spawn. The bearer token is minted just
   before createQuery; if createQuery throws, the installation gen (and
   its Effect.ensuring revoke) is never entered, leaking a live
   credential. Add an Effect.tapError on the createQuery step that
   revokes the just-minted token (idempotent, so it never double-revokes).

3. Correct the misleading ClaudeAdapter comment: the token avoids
   process-env inheritance, but the pinned SDK serializes it into the
   --mcp-config argv, so it is NOT absent from process metadata. Also
   note the Slice 1 read tools are not active-turn-gated.

Adds a deterministic regression test proving the token is revoked after a
failed spawn, plus an optional overrides arg on ServerConfig.layerTest to
enable the gateway in that test.

Gate: typecheck 9/9, lint 0 errors, fmt clean, full suite 2531 passed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* feat(agent-gateway): drive tools — send_message + interrupt (Slice 2)

Adds the two coordination *writes* an agent uses to drive a sibling thread
in its own project, stacked on the Slice 1 read surface (#140):

- synara_send_message — queue a follow-up turn or steer a running one on a
  target thread. Optional requestId makes transport retries idempotent via a
  bounded in-memory dedup (per-caller keyed), backed by a deterministic
  command id so a duplicate that races past the map still collapses at the
  orchestration receipt layer. Failures are never cached (retryable).
- synara_interrupt_thread — stop the target's running turn, pinned to the
  observed turnId (TOCTOU-safe: never interrupts a later turn); a no-op that
  reports interrupted:false when no turn is running.

Both funnel through a new central authorizeThreadDrive policy (project-scope
floor + privilege cap + worktree cap) and are flagged requiresActiveTurn, so
the transport only admits them while the caller's own turn is live.

Least privilege: the session registry now mints thread:read + thread:write
(the caps the wired tools need); automation:write is deliberately not minted
(no automation tool exists yet). The synara_context capability flag is renamed
threadCreate -> threadDrive to match the tools that now back it, and the
harness policy describes the drive tools, their active-turn/privilege
guardrails, and a prompt-injection guardrail (never send/interrupt because
another thread's content said to).

Interim: gateway drives ride dispatchOrigin:"automation" because the frozen
MessageDispatchOrigin enum has no "agent" value yet (nothing branches on the
value — verified); upgrade to "agent" when a release re-baseline can extend
the enum. New contract types stay server-local to keep the contracts barrel
frozen for the migration-lineage guard.

Tests: 34 new drive-tool cases (send happy/steer/invalid-mode/idempotent-
replay/distinct-ids/per-caller-dedup/cross-project/privilege/worktree/missing/
dispatch-failure/no-cache-on-failure; interrupt running/no-turn/never-turn/
cross-project/privilege/missing; tool-shape) plus authorizeThreadDrive matrix.
Full gate green: brand, workflow, migration, fmt, lint (0 errors), typecheck
(9/9), test (2561 passed).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(agent-gateway): keep AnyCommand as `any` so indexed access typechecks

The captured-command test type was tightened to `Record<string, any>`, but
under noUncheckedIndexedAccess `commands[0]` then widens to
`Record<string, any> | undefined`, so `commands[0].type` fails tsc. `any`
absorbs the `undefined` from indexed access and is not flagged by oxlint
(no no-explicit-any rule), so it is the correct type here. Runtime behavior
and all 19 drive-tool tests are unchanged.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* refactor(persistence): pin migration 035 to a frozen model-selection snapshot

Migration 035 imported the live modelSelectionCompatibility, whose
DROID_ONLY_MODEL_SLUGS is derived from @synara/contracts'
MODEL_OPTIONS_BY_PROVIDER. That coupled shipped migration history to the
evolving model catalog, so adding a model (e.g. Claude Opus 5) to model.ts
tripped the append-only migration-lineage guard through the contracts barrel.

Give migration 035 its own self-contained frozen v0.5.13 snapshot
(migration035FrozenModelSelectionCompatibility) with the DROID_ONLY set
hardcoded as the exact v0.5.13 catalog-derived literal, and repoint the
migration's import to it. All other normalization logic is byte-identical to
the live helper; the live helper stays in place for its runtime consumers.

The snapshot is proven behaviorally identical to the v0.5.13 migration:
- an equivalence test asserts frozen ≡ live across a persisted corpus that
  spans every branch (canonical, provider-less ambiguous slugs incl.
  claude-opus-5, instance-label inference, legacy Gemini, option-row arrays,
  provider-scoped options) and every catalog Droid-only slug, and
- the hardcoded DROID_ONLY literal is an exact match to the droid-only set
  derived from the origin/release/stable (v0.5.13) MODEL_OPTIONS_BY_PROVIDER.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* chore(migration-guard): audited one-time allowance for the 035 decouple

Repointing migration 035 to its frozen snapshot changes the shipped
migration dependency graph: severing the sole import of the live
modelSelectionCompatibility removes the only bridge from migration history
into @synara/contracts, so modelSelectionCompatibility and the entire
contracts barrel legitimately leave the migration dependency closure while
the frozen snapshot enters it. It also changes migration 035's own content
(the import line).

Bless exactly this delta with exact, path-and-blob-pinned, one-time audited
allowances — not a general bypass and without advancing the release baseline
or touching the protected release-tag manifest:
- RELEASED_CONTENT_ALLOWANCES gains the 035 old→new blob pair.
- RELEASED_DEPENDENCY_GRAPH_ALLOWANCES (new) pins 29 removed baseline blobs
  and the 1 added frozen-snapshot blob.

Each allowance pins a Git blob, so the guard fails closed on any other
change: editing the frozen snapshot voids its added-blob allowance, and a
dependency that stays reachable but changes content is never blessed (that
branch remains a hard violation). Violation messages now emit the exact
allowance key so future audited deltas are self-documenting. Guard
self-tests cover both content and removed/added graph suppression.

This precise closure also unfreezes unrelated contract files
(e.g. providerDiscovery.ts) that were only frozen transitively through the
barrel, and lets model.ts add Opus 5 without editing shipped history.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* feat(providers): add safe sign-out controls

* fix(providers): close review gaps

* fix(providers): polish status accessibility

* fix(providers): preserve released contract lineage

* fix(providers): use native sign-out confirmation

* Fix Claude discovery generation isolation

* Fix Claude model discovery without init event

* perf(git): fetch compact diff scope stats

Adapt the server-side working-tree diff statistics lane from Synara b3fc978308b30342694c06f651dc42762fd04552. Preserve selected-scope patch rendering while replacing picker-wide patch transfers and renderer parsing with compact totals.

Donor license: MIT. Scient's existing LICENSE carries the applicable Emanuele Di Pietro copyright and MIT notice.

* fix(diff): keep selected scope count current

* fix(diff): move stats RPC outside released contracts

* fix: enforce provider archive extraction limits

* fix(web): close project actions before editing

* test(web): cover project action focus handoff

* feat(git): discover committed PR templates safely

* fix(server): harden agent gateway session boundaries

* fix(server): close agent gateway review gaps

* fix(server): bind gateway limits to session lifecycle

* fix(agent-gateway): preserve honest message provenance

* fix(orchestration): retain agent dispatch provenance

* fix(git): honor GitHub PR template variants

* fix(git): require canonical PR template names

* fix(git): require dotted template extensions

* Add governed source-control writing (#153)

Integrates the reviewed SCM writing policy into the certified desktop queue. Exact source head 13f933d passed focused and full verification plus three independent final reviews with no remaining P0-P3 findings. See PR #153 for credential, provider-isolation, provenance, rollback, and limitation evidence.

* Add floating browser preview (#152)

Integrate the reviewed floating browser preview into the desktop shadow queue.

Exact candidate c8cb572 was certified against queue base 3f7ef52 with green hosted CI, real Electron acceptance, and three independent final reviews with no unresolved P0-P2 findings.

* docs(release): add Scient v0.5.14 in-app release note

Adds the required Scient-owned v0.5.14 entry to the in-app "What's new"
catalog. Highlights the two new user-facing capabilities in this release
(floating browser preview and source-control writing help) plus the
verified refinements shipped since v0.5.13. Text-only; no artwork added.

Verified locally: release:notes:check 0.5.14, brand:check, fmt:check,
lint (0 errors), whatsNew logic tests (14), verify-release-notes tests
(12), web typecheck.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Scient Release Engineer <yaacov.corcos@datavant.com>

---------

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Scient Release Engineer <yaacov.corcos@datavant.com>
yaacovcorcos added a commit that referenced this pull request Jul 28, 2026
)

* Route telemetry through ScientFactory gateway (#43)

* Fix unsigned macOS release signatures (#44)

* Add consent-aware desktop analytics (#47)

* Fix Claude terminal auth and connection recovery (#52)

* fix provider status refresh invariants

* fix Claude auth recovery

* Use direct OAuth for Grok sign-in (#53)

* Use direct OAuth for Grok sign-in

* Expose safe Grok OAuth browser fallback

* Secure Scient state initialization (#48)

* Secure Scient state initialization

* Allow legacy migration state test

* fix(security): harden private state files

* test(security): lock private file boundaries

* fix(security): reject unsafe private file nodes

* Supervise the desktop backend lifecycle (#49)

* Supervise the desktop backend lifecycle

* fix(desktop): preserve backend lifecycle ownership

* fix(desktop): replace semantically unready backends

* fix(desktop): close backend lifecycle races

* Supervise desktop connection recovery (#50)

* Supervise desktop connection recovery

* Isolate provider dialog browser fixtures

* fix(desktop): bind activation readiness generation

* fix(web): enforce single-owner connection recovery

* style(web): format connection recovery

* fix(web): satisfy connection transport types

* fix(web): harden stream and terminal recovery

* fix(web): fail closed on stuck stream cancellation

* fix(web): preserve terminal recovery ordering

* fix(web): clamp reconnect jitter ceilings

* fix(desktop): preserve connection wake after restack

* Define safe RPC recovery policies (#51)

* Define safe RPC recovery policies

* test(web): cover RPC recovery integration

* fix(web): recover after uncertain mutation failures

* test(web): type RPC recovery harness precisely

* fix(web): recover a failed replay generation

* Surface connection recovery diagnostics (#55)

* Surface connection recovery diagnostics

* test(web): cover connection recovery experience

* style(web): format recovery browser coverage

* fix(web): keep recovery diagnostics current

* Recover Codex sessions after authentication loss (#56)

* fix: recover Codex sessions after auth loss

* fix(codex): gate auth recovery by provider mode

* fix: harden Codex authentication recovery

* Support Linux desktop development launch (#57)

* Secure Scient state initialization

* Allow legacy migration state test

* Supervise the desktop backend lifecycle

* Supervise desktop connection recovery

* Define safe RPC recovery policies

* Surface connection recovery diagnostics

* Support Linux desktop development launch

* Isolate provider dialog browser fixtures

* fix(desktop): fail closed on unsafe Linux sandbox

* style(desktop): format Linux launcher hardening

* fix(release): preserve AppImage sandbox

* revert(release): keep AppImage migration out of launcher hardening

* fix(desktop): honor Linux user namespace sandbox

* Fix Antigravity browser authentication (#59)

* Fix Antigravity browser authentication

* Harden Antigravity authentication lifecycle

* Close Antigravity code window deterministically

* Keep Antigravity code submission cancellable

* Scope desktop signing credentials by platform (#60)

* Fix managed Antigravity updates, authentication, and dialog UX (#62)

* Fix trusted Antigravity install and update routing

* Fix Antigravity browser authentication and models

* Refine provider connection dialog actions

* Harden managed provider update recovery

* Stabilize macOS release identity (#63)

* Reduce unintended macOS permission prompts (#64)

* Stabilize macOS release identity

* Reduce unintended macOS permission prompts

* Apply repository formatting

* Control macOS notarization lifecycle (#65)

* Add Evidence to Note as a latent built-in (#70)

* Harden bidirectional chat rendering (#71)

* feat(web): harden bidirectional chat rendering

* fix(web): close bidi review gaps

* Add Medical Exam Study built-in (#72)

* Fix YAML frontmatter in Markdown previews (#69)

* Add T3-inspired project source dialog (#76)

* Add project source dialog

* Harden project source cloning

* Add T3-style right dock surfaces (#77)

* Add T3-style right dock surfaces

* Fix right dock test formatting

* fix: remove AppSnap startup announcement (#80)

* Add artifact preview cards to chat (#81)

* fix: select providers after connection (#82)

* Add message-level conversation forks (#78)

* Add message-level conversation forks

* Stabilize hosted fork browser test

* Close message fork boundary gaps

* Close final fork review gaps

* Resolve final fork recertification blockers

* Avoid replaying completed fork bootstrap

* Harden fork lineage and restart recovery

* Stabilize cold browser geometry startup

* Repair legacy fork title families

* Preserve unrecorded fork rename boundaries

* Clear drifted fork title lineage

* Improve desktop contribution workflow (#75)

* Set default base font to 15px and fix numeric editing (#79)

* Increase default base font size to 15px

* Fix manual font size editing

* Preserve external font setting updates

* Use recommended provider model defaults (#83)

* Use recommended provider model defaults

* Apply repository formatting

* Update browser expectation for Codex default

* Preserve explicit drafts before model discovery

* Respect live provider model availability

* Align desktop approval policy (#85)

* Fix release-candidate regressions (#86)

* Fix release candidate regressions

* Fix long transcript fork validation

* fix(release): preserve Linux sandbox (#87)

* fix(release): preserve Linux sandbox

* test(release): resolve nested builder package

* test(release): follow Bun package symlinks

* fix: preserve whitespace in folder browsing (#90)

* Collapse long assistant artifact shelves (#91)

* Remove project setup confirmation card (#93)

* Build unified notification system (#96)

* Hide provider setup banner on empty chats (#94)

* Hide provider setup banner on empty chats

* Stabilize empty provider banner coverage

* Harden provider banner browser readiness

* Fix Droid model discovery lifecycle (#95)

* Add ChatGPT-first voice transcription with local Whisper fallback (#97)

* feat(voice): define transcription backend contract

* feat(voice): add verified local transcription core

* Fix ChatGPT voice account context

* feat(voice): add ChatGPT-first local Whisper fallback

* Default Git writing to GPT-5.6 Luna (#99)

* Apply updated settings defaults once (#101)

* Apply updated settings defaults once

* Enable Studio in its browser fixture

* Improve voice dictation and active-turn composer controls (#102)

* Improve voice recording controls

* Add live local voice previews

* Keep voice send locked through completion

* Keep active-turn composer actions available

* Pin Whisper runtime source revision

* Fix voice transition regressions

* Fix folder picker navigation and project opening (#98)

* Fix folder picker navigation and project opening

* Tighten project setup choices

* Prevent duplicate folder picker submissions

* Fix Whisper runtime packaging on Windows (#104)

* fix: make Whisper packaging cross-platform safe

* fix: verify signed Windows Whisper runtime

* Secure HTML artifact previews with isolated execution (#100)

* feat: add secure HTML artifact previews

* fix: enforce HTML preview ownership boundaries

* Document cross-platform manual verification

* Use trash icon for voice cancel action (#106)

* Fix browser pane close and runtime recovery (#113)

* Isolate temporary Claude discovery from MCP servers (#116)

* Respect reduced motion in thread spinner (#84)

Adapt the upstream accessibility concept while retaining Scient-owned spinner geometry.

* Harden upstream-derived release tooling (#109)

* Salvage safe PR 61 interaction improvements (#107)

* Salvage safe PR 61 interaction improvements

* Harden terminal selection copy handling

* Adapt Studio Git gating and folder access (#108)

* Adapt Studio folder controls from Synara

* Gate Studio review command on repository detection

* Improve changed-file accessibility and density (#110)

* Add compact previews for bulky changed-file cards (#117)

* Improve changed-file accessibility and density

* Add compact changed-file previews

* Ensure changed-file previews show every file

* feat: add curated in-app release notes (#112)

* feat: add curated release notes workflow

* fix: harden release note experience

* refactor: share release note footer layout

* test: keep release note diagnostics concise

* Reject developer-facing release note copy

* Revert "Reject developer-facing release note copy"

This reverts commit 1006003.

* Harden release note structural validation

* Harden release note asset validation

* Resolve release note certification findings

* Bound release note PNG chunk parsing

* Validate all release note PNG chunk CRCs

* Fix browser multi-tab controls and menu occlusion (#119)

* Fix browser multi-tab controls and menu occlusion

* Keep browser sessions alive under overlays

* Harden browser overlay lifecycle coverage

* Complete browser tab and overlay semantics

* Restore focus after final browser tab closes

* Synchronize split-pane browser focus

* Harden Electron overlay lifecycle runner

* Isolate macOS Electron test bundle state

* Keep Electron lifecycle tests fully hermetic

* Resolve Electron sandbox from workspace package

* Guarantee Electron test harness cleanup

* Register Electron fixture cleanup immediately

* Restore focus after browser close controls

* Complete browser close focus recovery

* Handle early Electron test interruptions

* Cover earliest Electron setup interruption

* Refine branch and automation workflow affordances (#111)

* Refine upstream-derived workflow affordances

* Respect resolved automation triage state

* Fix native branch clipboard acceptance

* Document native workflow UX acceptance

* Add universal local file viewer (#114)

* Add universal local file viewer

* Harden local HTML preview capabilities

* Resolve HTML preview review blockers

* Close final HTML preview review gaps

* Fail closed on truncated active HTML

* Preserve complex HTML preview dependencies

* Fail closed on SVG runtime link mutation

* Block alternate network egress in HTML previews

* Recover HTML preview network setup

* Serialize HTML preview retries

* Occlude native HTML previews under overlays

* Harden provider installation and sign-in (#103)

* Harden provider installation and sign-in

* Fix Windows provider runtime test fixtures

* Make Windows PATH test path-stable

* Close provider onboarding reliability gaps

* Keep post-install sign-in recovery on the correct path

* Canonicalize Windows runtime discovery test paths

* Harden provider device-code recovery

* Harden OpenCode and Kilo turn completion (#120)

* Harden OpenCode and Kilo turn completion

* fix(provider): isolate OpenCode turn completion ownership

* fix(provider): close OpenCode completion review races

* fix(provider): fence OpenCode reply and replay races

* fix(provider): clean interrupted OpenCode replies

* fix(provider): harden OpenCode interaction ownership

* fix(provider): fail closed on ambiguous replies

* Harden OpenCode lifecycle retirement

* Serialize OpenCode session retirement

* Make OpenCode retirement interruption safe

* Finalize confirmed OpenCode process exits

* Add native folder drop to Add Project (#115)

* feat(projects): add native folder drop intake

* fix(projects): harden folder drop feedback

* fix(projects): keep folder errors visible

* fix(projects): preserve compact folder dialog footer

* fix(projects): harden native folder intake

* docs(qa): align folder intake evidence

* fix(projects): scope folder drop to dialog

* test(projects): cover platform folder labels

* docs: correct folder drop verification evidence

* docs: qualify native drag evidence

* docs: refresh folder drop verification evidence

* docs: refresh folder drop certification evidence

* docs: recertify folder drop on latest main

* Neutralize project drops outside dialog

* Update folder drop acceptance evidence

* Make new thread workspace intent explicit (#118)

* fix(web): make new thread workspace intent explicit

* fix(web): serialize distinct new thread intents

* test(web): type exact workspace branch mocks

* fix(web): preserve new thread request ordering

* fix(web): preserve latest new thread intent

* fix(web): coordinate all new thread navigation

* fix(web): preserve latest navigation across preparation

* fix(web): close remaining navigation races

* chore: clean merged sidebar imports

* fix(web): close terminal and route ownership gaps

* fix(web): coordinate every new-thread route intent

* fix(web): enforce route ownership before history commits

* test(web): use typed routes in navigation guard proof

* fix(web): release committed navigation ownership

* Show active file explorer toggle state (#124)

* Prevent background Cursor login browser launches (#125)

* Guard released migration lineage and dependencies (#129)

Adds a fail-closed, read-only release guard for shipped migration history and reviewed runtime dependency resolution.

* build(deps): bump actions/checkout from 7.0.0 to 7.0.1 (#131)

Update every retained workflow use to the verified immutable v7.0.1 commit.

* Bound settled attachment sync generations (#132)

Retire settled generation markers while preserving stale-write suppression and prior pending ownership after synchronous staging failure.

* Use lightweight snapshots for PR polling (#133)

Adapt Synara PR polling on a Scient-owned project-only query seam. Preserve active-project filtering and schema normalization, prove live-layer wiring, and avoid hydrating unrelated thread/session/turn state.

* Advance Synara review checkpoint to July 26 (#134)

* chore(upstream): advance reviewed Synara checkpoint

* chore(upstream): include late lifecycle review

* Prove packaged macOS and Windows startup before release (#121)

* test(release): prove packaged desktop startup

* Close packaged startup proof gaps

* Preserve packaged smoke isolation

* Avoid duplicate Windows tree kills

* Harden packaged smoke process cleanup

* Harden packaged startup proof acceptance

* Close packaged startup certification gaps

* Close exact packaged startup proof gaps

* Bound packaged smoke process cleanup

* Harden packaged startup release proof

* Close packaged startup review findings

* Keep startup proof test lint-clean

* fix(release): close packaged startup proof gaps

* fix(release): harden packaged startup cleanup

* fix(release): authenticate startup ownership records

* fix(release): bind cleanup to process instances

* fix(release): type cleanup authorities explicitly

* fix(release): close final startup proof findings

* fix(release): contain packaged startup by OS identity

* fix(release): fail closed after sentinel loss

* fix(release): close packaged cleanup containment gaps

* fix(release): fail closed on startup cleanup uncertainty

* fix(release): authenticate Windows startup verifier

* ci(release): exercise Windows startup launcher

* fix(release): close packaged startup proof gaps

* fix(release): harden packaged startup certification

* Fix packaged startup reconnect hydration

* fix(release): bind packaged startup containment lifetime

* fix(release): request sentinel cleanup over IPC

* fix(release): bind Windows verifier authority to pipe

* Bound repeated desktop backend crash restarts (#126)

* fix(desktop): bound backend crash restarts

Adapt the bounded supervision lessons from Synara commits 83b685234b2c474ea4d9a6ce593ac730ca95f8f7 and 5495a6e81e4da80e996867a1c487c9546cbd0196 onto Scient's existing generation-safe supervisor. Require post-readiness stability before resetting retry history, pause after repeated failures in a rolling window, and surface local log guidance without importing Synara's database-recovery architecture.

* fix(desktop): make backend crash recovery actionable

* fix(desktop): retain recovery dialog when logs fail

* fix(desktop): preserve crash recovery guarantees

* fix(desktop): suppress crash recovery while quitting

* fix(desktop): harden crash recovery diagnostics

* fix(desktop): preserve backend breaker through updater recovery

* test(desktop): prove native crash-breaker recovery

* fix(desktop): preserve crash-breaker recovery

* fix(desktop): preserve crash history across updater recovery

* test(desktop): prove updater crash recovery wiring

* fix(desktop): preserve shutdown authority during updater failure

* test(desktop): wait for native recovery accessibility

* test(desktop): isolate crash recovery acceptance

* test(desktop): bind recovery fixture process identity

* fix(desktop): retain quit authority during update handoff

* fix(desktop): restart after failed updater stop

* Keep diff mode and Git status refresh responsive (#127)

* fix(web): keep diff and git status refresh responsive

Adapted from Synara 807acfe3c784b41229b81c4b78957681ec8e6cb2.

Remount the third-party diff renderer when its mount-time view mode changes, use the shared menu radio primitive, and prevent branch-discovery races or non-repo workspaces from starting a permanent Git-status invalidation loop. Add focused regression coverage for each boundary.

* fix(web): ignore stale Git status before repository confirmation

* fix(web): require exact branch status for git actions

* fix(git): preserve branch authority across actions

* fix(git): serialize repository mutations

* fix(git): cover repository mutation workflows

* style(server): apply repository formatting

* fix(git): isolate live mutation authority contracts

* fix(git): overlay live mutation RPC authority

* test(web): align stacked action transport contract

* Keep local HTML previews live across source changes (#130)

* fix(desktop): keep local HTML previews live

* fix(desktop): harden live preview refresh

* fix(web): clear stale HTML preview errors

* fix(web): report queued preview refresh failures

* fix(desktop): release retired preview session hooks

* fix(browser): preserve refresh ownership and latest revision

* fix(browser): close live preview certification gaps

* fix(browser): close live preview review findings

* fix(browser): close final live preview review findings

* fix(browser): close exact-head preview review findings

* test(browser): cover preview discovery limits

* fix(browser): preserve optional preview limit metadata

* test(browser): require prepared source authority

* fix(browser): attest local preview capabilities

* fix(html-preview): harden atomic refresh authority

* fix(html-preview): close source watch startup gap

* fix(desktop): close live preview review gaps

* fix(desktop): close preview ownership failure gaps

* fix(html-preview): close remaining security boundaries

* fix(html-preview): pin inspected file versions

* fix(html-preview): serve attested document bytes

* Stop duplicating completed replies in Activity (#135)

* Stop duplicating completed replies in Activity

* Prove Activity completion ownership in Chromium

* Synchronize completion regression assertions

* Show fork provenance in conversation timelines (#136)

* Show fork provenance in transcripts

* Keep unavailable fork provenance truthful

* Require confirmed provider updates (#137)

Gate the Settings > Providers Update action behind a confirmed fresh version check, and harden the confirmed-update boundary so the updater child process only ever spawns against a probed, certified, and re-validated target (closes six concurrency/TOCTOU windows). See PR description for full details.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* Fix oversized transcript–composer gap when a task panel is showing (#138)

* Fix oversized transcript–composer gap when a task panel is showing

The composer is a flex sibling below the transcript, so the stacked composer
chrome (live-changes header, active task list, queued follow-ups) already
reserves its own vertical space through the flex layout. The transcript then
fed that same chrome height into its in-list bottom spacer
(bottomContentInsetPx = composerStackedChromeHeight + 8), reserving the space a
second time. The result was a large, growing gap between the last message and
the composer whenever a task/stacked panel was present, while the no-task case
(spacer at its 64px baseline) already looked correct.

Remove the double reservation: the transcript's bottom spacer is now a fixed
64px in every state, matching the perfect no-task gap. This also retires the
now-vestigial bottomContentInsetPx prop chain (ChatView → ChatTranscriptPane →
MessagesTimeline / AgentActivityDetailView), collapsing both consumers to their
constant baseline and correcting the misleading "composer overlaps / reserves
matching bottom space" comments.

composerStackedChromeHeight is kept for its real remaining job: the
scroll-compensation layout effect that keeps the transcript pinned to its end as
the flex viewport shrinks while the chrome grows.

- Task-present gap now equals the no-task gap (single flex reservation).
- Agent activity detail view uses the same fixed baseline (it was also
  double-counting).
- No behavior change to the no-task case.

Verified: oxfmt, oxlint (0 errors), tsc --noEmit (web), and the affected
component/scroll unit tests (106 passing).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* Add regression coverage for the transcript–composer gap fix

Prove the stacked composer chrome is reserved only once: a
[geometry:linux] browser test mounts ChatView with an active task card
and again once the turn settles (no card), then asserts the gap between
the transcript tail and the composer stack is unchanged. It anchors on
the tail spacer's top (the true end of transcript content, past any
live-turn activity indicator) so a running turn does not confound the
measurement.

Verified the test fails on the pre-fix code — the gap balloons to
~180px when the task card appears — and passes on the fix (~44px in
both states).

Adds two stable test hooks: data-chat-composer-stack on the composer
block wrapper and data-testid="transcript-bottom-spacer" on the list
tail spacer.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>

* Fix file links failing to open across git worktrees (#139)

* fix(server): resolve workspace file links across git worktrees

Bare/partial file references (e.g. a chat link to `kanbanDispatch.ts`)
could fail to open with a misleading "no such file" error even though the
file plainly exists. Two root causes:

1. The filesystem-walk index descended into linked git worktrees, so a
   single logical file was indexed multiple times (the real checkout plus
   each worktree copy). The suffix resolver treats multiple matches as
   ambiguous and gave up, and the read then surfaced the realpath ENOENT
   for the literal (non-existent) path. Indexing the duplicates also
   inflated the index toward its 25k-entry cap, truncating it.

2. On a genuine ambiguity the resolver returned null, which the reader
   reported as ENOENT -- a "file not found" message for a file that exists.

Changes (server-only):
- Prune linked git worktree subtrees from the index walk (a worktree
  records `.git` as a regular file pointer, the reliable discriminator),
  and skip `.git` entries whether file or directory. Extract the shared
  worktree/skip predicates.
- Rework resolveWorkspaceFileBySuffix to return a structured result
  (resolved | ambiguous | unresolved). Resolve only on a single distinct
  match; report the competing paths on a true ambiguity instead of
  guessing between different files.
- When the cached index is truncated (unreliable), re-scan the tree
  directly (bounded) for a trustworthy candidate set.
- Surface an honest, actionable error listing the competing files instead
  of a false ENOENT. Reuses the existing WorkspaceFileSystemError tag, so
  no contract/client change.

Tests: worktree pruning, unique/ambiguous/unresolved resolution, the
worktree-duplicate scenario end-to-end, and the truncated-index disk
re-scan.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(server): don't prune submodules; fail closed on incomplete suffix scan

Follow-up correctness fixes to the worktree-aware file-link resolution.

1. Submodule false-prune. The worktree detector treated *any* directory
   whose `.git` is a regular file as a linked worktree and pruned it. Git
   submodules also store `.git` as a file, so their subtrees were pruned
   too -- silently hiding submodule files from search and link resolution.
   Discriminate by the `gitdir:` pointer target: prune only when it points
   into `.git/worktrees/<name>` (a linked worktree), never when it points
   into `.git/modules/<name>` (a submodule). Reading the pointer fails open
   (do not prune) so an unreadable `.git` can never hide real files.

2. Incomplete-scan false-unique. The bounded disk re-scan (used when the
   index is truncated) returned whatever it had found when it hit the
   scanned-directory cap. A single match found before the cap was then
   reported as a unique "resolved" even though a second match could sit in
   the unscanned remainder -- risking opening the wrong file. The scan now
   reports whether it completed, and classification fails closed to a new
   "indeterminate" outcome when an incomplete scan saw fewer than two
   matches. The reader surfaces an honest "too large to resolve, use a
   fuller path" error instead of guessing or falsely claiming ENOENT.

Tests: submodule files stay resolvable and searchable (not pruned); the
disk scan reports incomplete at its directory cap; classification fails
closed (single match from an incomplete scan -> indeterminate, two
distinct matches -> ambiguous even when incomplete, empty complete scan
-> unresolved). The existing linked-worktree fixtures now use realistic
`.git/worktrees/<name>` pointer contents.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>

* fix(web): guard Enter during IME composition in message composers (#143)

CJK/Japanese/Korean IMEs use Enter to confirm a candidate. An unguarded
Enter-to-send handler treats that confirmation keystroke as "send" and
submits a half-composed message.

Add a shared isImeCompositionKeyEvent() helper (isComposing || keyCode
=== 229) and apply it at the two message-composer key handlers:

- ComposerCommandKeyPlugin, the shared chat + kanban Lexical handler:
  swallow Enter fired mid-composition before it reaches the send/menu
  logic. Lexical already drops keydowns while editor.isComposing() is
  true, but on Safari/WebKit compositionend fires before the confirming
  keydown, so that Enter still dispatches KEY_ENTER_COMMAND; the
  keyCode === 229 branch closes that gap.
- PullRequestCommentComposer, a plain <textarea> with no Lexical gate,
  replacing its isComposing-only check so a keyCode-229 confirm no
  longer submits.

Value: correct multi-language text entry; no accidental send on IME
candidate confirmation.

Out of scope (follow-up): other bare-Enter inputs (project/rename/search
fields) share the hazard and could adopt the same helper.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>

* feat(web): self-host UI fonts, drop Google Fonts CDN (#142)

Remove the runtime Google Fonts <link> from index.html and self-host the
needed families (Geist, Geist Mono, Inter) via @fontsource-variable/*
packages, alongside the JetBrains Mono face already bundled. DM Sans was
listed in the CDN link but has zero references, so it is dropped rather
than self-hosted.

The @fontsource-variable packages register their @font-face under a
"<Family> Variable" name (e.g. "Inter Variable") while themes store the
plain family name, so add expandBundledVariableFontAliases() and apply it
at the theme->CSS-variable emission boundary: the bundled face is matched
and the plain name is kept after it as a fallback.

Value: offline usability, no third-party font beacon on launch, no font
flicker. The default appearance (systemUiFont + JetBrains Mono fallback)
needs no Google fonts, so removing the CDN cannot regress it.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>

* Make new-chat project selection safe across draft and project lifecycles

Integrate the reviewed project-picker interaction and project-lifecycle safety fixes. Complete local certification, three independent final reviews, hosted CI, and manual native visual acceptance passed.

* fix(desktop): preserve Windows Ctrl-minus zoom (#148)

* fix: preserve Windows Ctrl-minus zoom

Adapted from Synara 94b59220e26bc337406110c84220aec76b065490.

* fix: preserve shortcuts help chord compatibility

Keep the Windows physical-minus disambiguation scoped to Windows while retaining the existing Meta-or-Ctrl slash behavior on every platform.

* fix: align Windows minus shortcut routing

* Promote certified desktop integration queue (#154)

Promotes the certified July 28 desktop integration queue. Includes the reviewed work represented by PRs #123, #140, #141, #144, #149, #150, and aligned replacement #151 for #146. Supersedes #68 through the hardened #144 implementation. See PR #154 for exact heads, dispositions, verification, limitations, and rollback evidence.

* Promote certified desktop queue + v0.5.14 release note into main (#155)

* Add Claude Opus 5 capabilities

* Harden Claude capability discovery and Opus gating

* Refresh Claude discovery results

* Fail closed on Claude capability boundaries

* Scope Claude discovery to the exact runtime

* Bind Claude Opus 5 to the exact runtime

* Harden Claude Opus 5 runtime gating

* Keep Claude fresh defaults available

* fix(claude): isolate discovery lifecycle generations

* fix(claude): bind discovery cache generations

* test(web): bind Claude prefetch generation keys

* fix(claude): authorize Opus 5 from exact runtime

* fix(claude): make discovery generations monotonic

* Fix provider runtime extraction and setup progress

* fix(claude): harden discovery lifecycle ownership

* fix(claude): generation-key native slash-command discovery

Native slash-command discovery now participates in the same
renderer-owned discovery-generation scheme already used for model and
agent discovery, so a command catalog fetched under one auth/runtime
generation can never leak into a newer one.

- contracts: add optional discoveryGeneration to ProviderListCommandsInput
- server: fold discoveryGeneration into the listCommands in-flight cache
  key so a later auth generation never joins an older CLI's discovery
- client: bind the commands query to the current generation (query key,
  RPC arg, post-resolve stale discard, fail-fast retry, no stale
  placeholder for claudeAgent) and invalidate commands alongside agents
  on auth-sensitive provider changes
- route the configured Claude binary through every command-discovery
  call site (ChatView, kanban composer, /fast availability check)
- tests: cover generation separation for command discovery on both the
  server adapter and the React Query layer

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* feat(agent-gateway): host-served MCP read/coordination tools (Slice 1)

First slice of the agent gateway: a thread-scoped, host-served MCP
endpoint (`POST /mcp`) that lets an agent in one thread observe and
coordinate sibling top-level threads. Read/coordination only — no
send/interrupt, no create/fork. Behind a feature flag, disabled by
default (`SYNARA_AGENT_GATEWAY_ENABLED` / `--agent-gateway-enabled`).

Lift-and-reconcile of Synara's MIT-licensed agent gateway onto a
Scient-owned authorization + credential spine. `synara_*` names and
`synara/` namespaces kept intentionally (rebrand is a later pass).

New `apps/server/src/agentGateway/` subsystem:
- Transport/ingress auth: per-request bearer verify → thread-existence
  recheck → provider-ownership recheck → central authorization, with no
  cached grant; body cap (1 MiB) + batch cap (50); GET/DELETE mirror the
  disabled-state 404; top-level defect net upholds the never-fails
  contract on handleMcpPost.
- Credential spine: opaque per-thread tokens, in-memory registry (dies
  on restart), least-privilege (`thread:read` only), revoke-on-teardown.
- Central default-deny authorization: capability → project scope →
  thread-type; cross-project reads denied as thread_not_found.
- Read tools: synara_context, list_projects, list_threads, read_thread,
  wait_for_threads, backed by ProjectionSnapshotQuery.
- Claude provider injection via HTTP Authorization header (never the
  process env), flag-gated, revoked on teardown and failed install.

Shared-file injection hand-re-applied at current symbol anchors:
http.ts route registration, config.ts/main.ts flag, effectServer.ts
bound-port publish, ClaudeAdapter.ts/runtimeLayer.ts token lifecycle,
new packages/contracts/src/agentGateway.ts.

typecheck 9/9, full test suite 12/12 (agentGateway 168/12 incl. new
httpRoute.test.ts), lint 0 errors, brand:check green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(agent-gateway): keep contracts barrel frozen + format Slice 1 files

Resolves the two CI failures on this PR:

1. migration:check — Slice 1 added `export * from "./agentGateway"` to
   `packages/contracts/src/index.ts`. That barrel is a released-migration
   dependency (released migrations import `@synara/contracts`, and the
   lineage guard traverses the barrel's re-exports and fingerprints its
   runtime source). Adding the line both *modified* the frozen barrel and
   *pulled* `agentGateway.ts` into the released dependency closure, tripping
   the append-only guard.

   Fix: relocate the gateway contract into the server subsystem as
   `apps/server/src/agentGateway/contract.ts` and drop it from the barrel.
   Every consumer is server-side (no renderer/client consumer exists), so
   the shared package was never required. `index.ts` is restored byte-for-
   byte to the v0.5.13 baseline and `agentGateway.ts` leaves the closure.

2. fmt:check — donor-lifted test files and the ClaudeAdapter edits were not
   run through oxfmt. Applied `oxfmt` (formatting only; no behavior change).

Full gate green: brand, workflow, migration, fmt, lint (0 errors),
typecheck (9/9), test (12/12 packages, 2530 passed).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(agent-gateway): close read_thread disclosure oracle + revoke token on failed spawn

Two pre-merge security fixes on the Slice 1 read foundation, plus a
truthful token-exposure comment.

1. read_thread non-disclosure oracle. An unknown thread failed as a
   plain-text ToolInputError while a cross-project thread failed as a
   JSON GatewayToolError, so a caller could distinguish "no such thread"
   from "exists in another project" by response shape — defeating the
   deliberately byte-identical message. Route read_thread's not-found
   through GatewayToolError so both denials are identical in code,
   message, and JSON shape (mirrors wait_for_threads).

2. Gateway token leak on failed spawn. The bearer token is minted just
   before createQuery; if createQuery throws, the installation gen (and
   its Effect.ensuring revoke) is never entered, leaking a live
   credential. Add an Effect.tapError on the createQuery step that
   revokes the just-minted token (idempotent, so it never double-revokes).

3. Correct the misleading ClaudeAdapter comment: the token avoids
   process-env inheritance, but the pinned SDK serializes it into the
   --mcp-config argv, so it is NOT absent from process metadata. Also
   note the Slice 1 read tools are not active-turn-gated.

Adds a deterministic regression test proving the token is revoked after a
failed spawn, plus an optional overrides arg on ServerConfig.layerTest to
enable the gateway in that test.

Gate: typecheck 9/9, lint 0 errors, fmt clean, full suite 2531 passed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* feat(agent-gateway): drive tools — send_message + interrupt (Slice 2)

Adds the two coordination *writes* an agent uses to drive a sibling thread
in its own project, stacked on the Slice 1 read surface (#140):

- synara_send_message — queue a follow-up turn or steer a running one on a
  target thread. Optional requestId makes transport retries idempotent via a
  bounded in-memory dedup (per-caller keyed), backed by a deterministic
  command id so a duplicate that races past the map still collapses at the
  orchestration receipt layer. Failures are never cached (retryable).
- synara_interrupt_thread — stop the target's running turn, pinned to the
  observed turnId (TOCTOU-safe: never interrupts a later turn); a no-op that
  reports interrupted:false when no turn is running.

Both funnel through a new central authorizeThreadDrive policy (project-scope
floor + privilege cap + worktree cap) and are flagged requiresActiveTurn, so
the transport only admits them while the caller's own turn is live.

Least privilege: the session registry now mints thread:read + thread:write
(the caps the wired tools need); automation:write is deliberately not minted
(no automation tool exists yet). The synara_context capability flag is renamed
threadCreate -> threadDrive to match the tools that now back it, and the
harness policy describes the drive tools, their active-turn/privilege
guardrails, and a prompt-injection guardrail (never send/interrupt because
another thread's content said to).

Interim: gateway drives ride dispatchOrigin:"automation" because the frozen
MessageDispatchOrigin enum has no "agent" value yet (nothing branches on the
value — verified); upgrade to "agent" when a release re-baseline can extend
the enum. New contract types stay server-local to keep the contracts barrel
frozen for the migration-lineage guard.

Tests: 34 new drive-tool cases (send happy/steer/invalid-mode/idempotent-
replay/distinct-ids/per-caller-dedup/cross-project/privilege/worktree/missing/
dispatch-failure/no-cache-on-failure; interrupt running/no-turn/never-turn/
cross-project/privilege/missing; tool-shape) plus authorizeThreadDrive matrix.
Full gate green: brand, workflow, migration, fmt, lint (0 errors), typecheck
(9/9), test (2561 passed).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(agent-gateway): keep AnyCommand as `any` so indexed access typechecks

The captured-command test type was tightened to `Record<string, any>`, but
under noUncheckedIndexedAccess `commands[0]` then widens to
`Record<string, any> | undefined`, so `commands[0].type` fails tsc. `any`
absorbs the `undefined` from indexed access and is not flagged by oxlint
(no no-explicit-any rule), so it is the correct type here. Runtime behavior
and all 19 drive-tool tests are unchanged.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* refactor(persistence): pin migration 035 to a frozen model-selection snapshot

Migration 035 imported the live modelSelectionCompatibility, whose
DROID_ONLY_MODEL_SLUGS is derived from @synara/contracts'
MODEL_OPTIONS_BY_PROVIDER. That coupled shipped migration history to the
evolving model catalog, so adding a model (e.g. Claude Opus 5) to model.ts
tripped the append-only migration-lineage guard through the contracts barrel.

Give migration 035 its own self-contained frozen v0.5.13 snapshot
(migration035FrozenModelSelectionCompatibility) with the DROID_ONLY set
hardcoded as the exact v0.5.13 catalog-derived literal, and repoint the
migration's import to it. All other normalization logic is byte-identical to
the live helper; the live helper stays in place for its runtime consumers.

The snapshot is proven behaviorally identical to the v0.5.13 migration:
- an equivalence test asserts frozen ≡ live across a persisted corpus that
  spans every branch (canonical, provider-less ambiguous slugs incl.
  claude-opus-5, instance-label inference, legacy Gemini, option-row arrays,
  provider-scoped options) and every catalog Droid-only slug, and
- the hardcoded DROID_ONLY literal is an exact match to the droid-only set
  derived from the origin/release/stable (v0.5.13) MODEL_OPTIONS_BY_PROVIDER.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* chore(migration-guard): audited one-time allowance for the 035 decouple

Repointing migration 035 to its frozen snapshot changes the shipped
migration dependency graph: severing the sole import of the live
modelSelectionCompatibility removes the only bridge from migration history
into @synara/contracts, so modelSelectionCompatibility and the entire
contracts barrel legitimately leave the migration dependency closure while
the frozen snapshot enters it. It also changes migration 035's own content
(the import line).

Bless exactly this delta with exact, path-and-blob-pinned, one-time audited
allowances — not a general bypass and without advancing the release baseline
or touching the protected release-tag manifest:
- RELEASED_CONTENT_ALLOWANCES gains the 035 old→new blob pair.
- RELEASED_DEPENDENCY_GRAPH_ALLOWANCES (new) pins 29 removed baseline blobs
  and the 1 added frozen-snapshot blob.

Each allowance pins a Git blob, so the guard fails closed on any other
change: editing the frozen snapshot voids its added-blob allowance, and a
dependency that stays reachable but changes content is never blessed (that
branch remains a hard violation). Violation messages now emit the exact
allowance key so future audited deltas are self-documenting. Guard
self-tests cover both content and removed/added graph suppression.

This precise closure also unfreezes unrelated contract files
(e.g. providerDiscovery.ts) that were only frozen transitively through the
barrel, and lets model.ts add Opus 5 without editing shipped history.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* feat(providers): add safe sign-out controls

* fix(providers): close review gaps

* fix(providers): polish status accessibility

* fix(providers): preserve released contract lineage

* fix(providers): use native sign-out confirmation

* Fix Claude discovery generation isolation

* Fix Claude model discovery without init event

* perf(git): fetch compact diff scope stats

Adapt the server-side working-tree diff statistics lane from Synara b3fc978308b30342694c06f651dc42762fd04552. Preserve selected-scope patch rendering while replacing picker-wide patch transfers and renderer parsing with compact totals.

Donor license: MIT. Scient's existing LICENSE carries the applicable Emanuele Di Pietro copyright and MIT notice.

* fix(diff): keep selected scope count current

* fix(diff): move stats RPC outside released contracts

* fix: enforce provider archive extraction limits

* fix(web): close project actions before editing

* test(web): cover project action focus handoff

* feat(git): discover committed PR templates safely

* fix(server): harden agent gateway session boundaries

* fix(server): close agent gateway review gaps

* fix(server): bind gateway limits to session lifecycle

* fix(agent-gateway): preserve honest message provenance

* fix(orchestration): retain agent dispatch provenance

* fix(git): honor GitHub PR template variants

* fix(git): require canonical PR template names

* fix(git): require dotted template extensions

* Add governed source-control writing (#153)

Integrates the reviewed SCM writing policy into the certified desktop queue. Exact source head 13f933d passed focused and full verification plus three independent final reviews with no remaining P0-P3 findings. See PR #153 for credential, provider-isolation, provenance, rollback, and limitation evidence.

* Add floating browser preview (#152)

Integrate the reviewed floating browser preview into the desktop shadow queue.

Exact candidate c8cb572 was certified against queue base 3f7ef52 with green hosted CI, real Electron acceptance, and three independent final reviews with no unresolved P0-P2 findings.

* docs(release): add Scient v0.5.14 in-app release note

Adds the required Scient-owned v0.5.14 entry to the in-app "What's new"
catalog. Highlights the two new user-facing capabilities in this release
(floating browser preview and source-control writing help) plus the
verified refinements shipped since v0.5.13. Text-only; no artwork added.

Verified locally: release:notes:check 0.5.14, brand:check, fmt:check,
lint (0 errors), whatsNew logic tests (14), verify-release-notes tests
(12), web typecheck.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Scient Release Engineer <yaacov.corcos@datavant.com>

* Fix release preflight tag visibility (#157)

Fetch the official Synara tag set through a push-disabled remote before migration-lineage validation in Release Preflight. Preserve the reviewed 79-tag manifest and enforce the fetch commands and ordering through release smoke coverage.

---------

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Scient Release Engineer <yaacov.corcos@datavant.com>
yaacovcorcos added a commit that referenced this pull request Jul 29, 2026
#161)

* Route telemetry through ScientFactory gateway (#43)

* Fix unsigned macOS release signatures (#44)

* Add consent-aware desktop analytics (#47)

* Fix Claude terminal auth and connection recovery (#52)

* fix provider status refresh invariants

* fix Claude auth recovery

* Use direct OAuth for Grok sign-in (#53)

* Use direct OAuth for Grok sign-in

* Expose safe Grok OAuth browser fallback

* Secure Scient state initialization (#48)

* Secure Scient state initialization

* Allow legacy migration state test

* fix(security): harden private state files

* test(security): lock private file boundaries

* fix(security): reject unsafe private file nodes

* Supervise the desktop backend lifecycle (#49)

* Supervise the desktop backend lifecycle

* fix(desktop): preserve backend lifecycle ownership

* fix(desktop): replace semantically unready backends

* fix(desktop): close backend lifecycle races

* Supervise desktop connection recovery (#50)

* Supervise desktop connection recovery

* Isolate provider dialog browser fixtures

* fix(desktop): bind activation readiness generation

* fix(web): enforce single-owner connection recovery

* style(web): format connection recovery

* fix(web): satisfy connection transport types

* fix(web): harden stream and terminal recovery

* fix(web): fail closed on stuck stream cancellation

* fix(web): preserve terminal recovery ordering

* fix(web): clamp reconnect jitter ceilings

* fix(desktop): preserve connection wake after restack

* Define safe RPC recovery policies (#51)

* Define safe RPC recovery policies

* test(web): cover RPC recovery integration

* fix(web): recover after uncertain mutation failures

* test(web): type RPC recovery harness precisely

* fix(web): recover a failed replay generation

* Surface connection recovery diagnostics (#55)

* Surface connection recovery diagnostics

* test(web): cover connection recovery experience

* style(web): format recovery browser coverage

* fix(web): keep recovery diagnostics current

* Recover Codex sessions after authentication loss (#56)

* fix: recover Codex sessions after auth loss

* fix(codex): gate auth recovery by provider mode

* fix: harden Codex authentication recovery

* Support Linux desktop development launch (#57)

* Secure Scient state initialization

* Allow legacy migration state test

* Supervise the desktop backend lifecycle

* Supervise desktop connection recovery

* Define safe RPC recovery policies

* Surface connection recovery diagnostics

* Support Linux desktop development launch

* Isolate provider dialog browser fixtures

* fix(desktop): fail closed on unsafe Linux sandbox

* style(desktop): format Linux launcher hardening

* fix(release): preserve AppImage sandbox

* revert(release): keep AppImage migration out of launcher hardening

* fix(desktop): honor Linux user namespace sandbox

* Fix Antigravity browser authentication (#59)

* Fix Antigravity browser authentication

* Harden Antigravity authentication lifecycle

* Close Antigravity code window deterministically

* Keep Antigravity code submission cancellable

* Scope desktop signing credentials by platform (#60)

* Fix managed Antigravity updates, authentication, and dialog UX (#62)

* Fix trusted Antigravity install and update routing

* Fix Antigravity browser authentication and models

* Refine provider connection dialog actions

* Harden managed provider update recovery

* Stabilize macOS release identity (#63)

* Reduce unintended macOS permission prompts (#64)

* Stabilize macOS release identity

* Reduce unintended macOS permission prompts

* Apply repository formatting

* Control macOS notarization lifecycle (#65)

* Add Evidence to Note as a latent built-in (#70)

* Harden bidirectional chat rendering (#71)

* feat(web): harden bidirectional chat rendering

* fix(web): close bidi review gaps

* Add Medical Exam Study built-in (#72)

* Fix YAML frontmatter in Markdown previews (#69)

* Add T3-inspired project source dialog (#76)

* Add project source dialog

* Harden project source cloning

* Add T3-style right dock surfaces (#77)

* Add T3-style right dock surfaces

* Fix right dock test formatting

* fix: remove AppSnap startup announcement (#80)

* Add artifact preview cards to chat (#81)

* fix: select providers after connection (#82)

* Add message-level conversation forks (#78)

* Add message-level conversation forks

* Stabilize hosted fork browser test

* Close message fork boundary gaps

* Close final fork review gaps

* Resolve final fork recertification blockers

* Avoid replaying completed fork bootstrap

* Harden fork lineage and restart recovery

* Stabilize cold browser geometry startup

* Repair legacy fork title families

* Preserve unrecorded fork rename boundaries

* Clear drifted fork title lineage

* Improve desktop contribution workflow (#75)

* Set default base font to 15px and fix numeric editing (#79)

* Increase default base font size to 15px

* Fix manual font size editing

* Preserve external font setting updates

* Use recommended provider model defaults (#83)

* Use recommended provider model defaults

* Apply repository formatting

* Update browser expectation for Codex default

* Preserve explicit drafts before model discovery

* Respect live provider model availability

* Align desktop approval policy (#85)

* Fix release-candidate regressions (#86)

* Fix release candidate regressions

* Fix long transcript fork validation

* fix(release): preserve Linux sandbox (#87)

* fix(release): preserve Linux sandbox

* test(release): resolve nested builder package

* test(release): follow Bun package symlinks

* fix: preserve whitespace in folder browsing (#90)

* Collapse long assistant artifact shelves (#91)

* Remove project setup confirmation card (#93)

* Build unified notification system (#96)

* Hide provider setup banner on empty chats (#94)

* Hide provider setup banner on empty chats

* Stabilize empty provider banner coverage

* Harden provider banner browser readiness

* Fix Droid model discovery lifecycle (#95)

* Add ChatGPT-first voice transcription with local Whisper fallback (#97)

* feat(voice): define transcription backend contract

* feat(voice): add verified local transcription core

* Fix ChatGPT voice account context

* feat(voice): add ChatGPT-first local Whisper fallback

* Default Git writing to GPT-5.6 Luna (#99)

* Apply updated settings defaults once (#101)

* Apply updated settings defaults once

* Enable Studio in its browser fixture

* Improve voice dictation and active-turn composer controls (#102)

* Improve voice recording controls

* Add live local voice previews

* Keep voice send locked through completion

* Keep active-turn composer actions available

* Pin Whisper runtime source revision

* Fix voice transition regressions

* Fix folder picker navigation and project opening (#98)

* Fix folder picker navigation and project opening

* Tighten project setup choices

* Prevent duplicate folder picker submissions

* Fix Whisper runtime packaging on Windows (#104)

* fix: make Whisper packaging cross-platform safe

* fix: verify signed Windows Whisper runtime

* Secure HTML artifact previews with isolated execution (#100)

* feat: add secure HTML artifact previews

* fix: enforce HTML preview ownership boundaries

* Document cross-platform manual verification

* Use trash icon for voice cancel action (#106)

* Fix browser pane close and runtime recovery (#113)

* Isolate temporary Claude discovery from MCP servers (#116)

* Respect reduced motion in thread spinner (#84)

Adapt the upstream accessibility concept while retaining Scient-owned spinner geometry.

* Harden upstream-derived release tooling (#109)

* Salvage safe PR 61 interaction improvements (#107)

* Salvage safe PR 61 interaction improvements

* Harden terminal selection copy handling

* Adapt Studio Git gating and folder access (#108)

* Adapt Studio folder controls from Synara

* Gate Studio review command on repository detection

* Improve changed-file accessibility and density (#110)

* Add compact previews for bulky changed-file cards (#117)

* Improve changed-file accessibility and density

* Add compact changed-file previews

* Ensure changed-file previews show every file

* feat: add curated in-app release notes (#112)

* feat: add curated release notes workflow

* fix: harden release note experience

* refactor: share release note footer layout

* test: keep release note diagnostics concise

* Reject developer-facing release note copy

* Revert "Reject developer-facing release note copy"

This reverts commit 1006003.

* Harden release note structural validation

* Harden release note asset validation

* Resolve release note certification findings

* Bound release note PNG chunk parsing

* Validate all release note PNG chunk CRCs

* Fix browser multi-tab controls and menu occlusion (#119)

* Fix browser multi-tab controls and menu occlusion

* Keep browser sessions alive under overlays

* Harden browser overlay lifecycle coverage

* Complete browser tab and overlay semantics

* Restore focus after final browser tab closes

* Synchronize split-pane browser focus

* Harden Electron overlay lifecycle runner

* Isolate macOS Electron test bundle state

* Keep Electron lifecycle tests fully hermetic

* Resolve Electron sandbox from workspace package

* Guarantee Electron test harness cleanup

* Register Electron fixture cleanup immediately

* Restore focus after browser close controls

* Complete browser close focus recovery

* Handle early Electron test interruptions

* Cover earliest Electron setup interruption

* Refine branch and automation workflow affordances (#111)

* Refine upstream-derived workflow affordances

* Respect resolved automation triage state

* Fix native branch clipboard acceptance

* Document native workflow UX acceptance

* Add universal local file viewer (#114)

* Add universal local file viewer

* Harden local HTML preview capabilities

* Resolve HTML preview review blockers

* Close final HTML preview review gaps

* Fail closed on truncated active HTML

* Preserve complex HTML preview dependencies

* Fail closed on SVG runtime link mutation

* Block alternate network egress in HTML previews

* Recover HTML preview network setup

* Serialize HTML preview retries

* Occlude native HTML previews under overlays

* Harden provider installation and sign-in (#103)

* Harden provider installation and sign-in

* Fix Windows provider runtime test fixtures

* Make Windows PATH test path-stable

* Close provider onboarding reliability gaps

* Keep post-install sign-in recovery on the correct path

* Canonicalize Windows runtime discovery test paths

* Harden provider device-code recovery

* Harden OpenCode and Kilo turn completion (#120)

* Harden OpenCode and Kilo turn completion

* fix(provider): isolate OpenCode turn completion ownership

* fix(provider): close OpenCode completion review races

* fix(provider): fence OpenCode reply and replay races

* fix(provider): clean interrupted OpenCode replies

* fix(provider): harden OpenCode interaction ownership

* fix(provider): fail closed on ambiguous replies

* Harden OpenCode lifecycle retirement

* Serialize OpenCode session retirement

* Make OpenCode retirement interruption safe

* Finalize confirmed OpenCode process exits

* Add native folder drop to Add Project (#115)

* feat(projects): add native folder drop intake

* fix(projects): harden folder drop feedback

* fix(projects): keep folder errors visible

* fix(projects): preserve compact folder dialog footer

* fix(projects): harden native folder intake

* docs(qa): align folder intake evidence

* fix(projects): scope folder drop to dialog

* test(projects): cover platform folder labels

* docs: correct folder drop verification evidence

* docs: qualify native drag evidence

* docs: refresh folder drop verification evidence

* docs: refresh folder drop certification evidence

* docs: recertify folder drop on latest main

* Neutralize project drops outside dialog

* Update folder drop acceptance evidence

* Make new thread workspace intent explicit (#118)

* fix(web): make new thread workspace intent explicit

* fix(web): serialize distinct new thread intents

* test(web): type exact workspace branch mocks

* fix(web): preserve new thread request ordering

* fix(web): preserve latest new thread intent

* fix(web): coordinate all new thread navigation

* fix(web): preserve latest navigation across preparation

* fix(web): close remaining navigation races

* chore: clean merged sidebar imports

* fix(web): close terminal and route ownership gaps

* fix(web): coordinate every new-thread route intent

* fix(web): enforce route ownership before history commits

* test(web): use typed routes in navigation guard proof

* fix(web): release committed navigation ownership

* Show active file explorer toggle state (#124)

* Prevent background Cursor login browser launches (#125)

* Guard released migration lineage and dependencies (#129)

Adds a fail-closed, read-only release guard for shipped migration history and reviewed runtime dependency resolution.

* build(deps): bump actions/checkout from 7.0.0 to 7.0.1 (#131)

Update every retained workflow use to the verified immutable v7.0.1 commit.

* Bound settled attachment sync generations (#132)

Retire settled generation markers while preserving stale-write suppression and prior pending ownership after synchronous staging failure.

* Use lightweight snapshots for PR polling (#133)

Adapt Synara PR polling on a Scient-owned project-only query seam. Preserve active-project filtering and schema normalization, prove live-layer wiring, and avoid hydrating unrelated thread/session/turn state.

* Advance Synara review checkpoint to July 26 (#134)

* chore(upstream): advance reviewed Synara checkpoint

* chore(upstream): include late lifecycle review

* Prove packaged macOS and Windows startup before release (#121)

* test(release): prove packaged desktop startup

* Close packaged startup proof gaps

* Preserve packaged smoke isolation

* Avoid duplicate Windows tree kills

* Harden packaged smoke process cleanup

* Harden packaged startup proof acceptance

* Close packaged startup certification gaps

* Close exact packaged startup proof gaps

* Bound packaged smoke process cleanup

* Harden packaged startup release proof

* Close packaged startup review findings

* Keep startup proof test lint-clean

* fix(release): close packaged startup proof gaps

* fix(release): harden packaged startup cleanup

* fix(release): authenticate startup ownership records

* fix(release): bind cleanup to process instances

* fix(release): type cleanup authorities explicitly

* fix(release): close final startup proof findings

* fix(release): contain packaged startup by OS identity

* fix(release): fail closed after sentinel loss

* fix(release): close packaged cleanup containment gaps

* fix(release): fail closed on startup cleanup uncertainty

* fix(release): authenticate Windows startup verifier

* ci(release): exercise Windows startup launcher

* fix(release): close packaged startup proof gaps

* fix(release): harden packaged startup certification

* Fix packaged startup reconnect hydration

* fix(release): bind packaged startup containment lifetime

* fix(release): request sentinel cleanup over IPC

* fix(release): bind Windows verifier authority to pipe

* Bound repeated desktop backend crash restarts (#126)

* fix(desktop): bound backend crash restarts

Adapt the bounded supervision lessons from Synara commits 83b685234b2c474ea4d9a6ce593ac730ca95f8f7 and 5495a6e81e4da80e996867a1c487c9546cbd0196 onto Scient's existing generation-safe supervisor. Require post-readiness stability before resetting retry history, pause after repeated failures in a rolling window, and surface local log guidance without importing Synara's database-recovery architecture.

* fix(desktop): make backend crash recovery actionable

* fix(desktop): retain recovery dialog when logs fail

* fix(desktop): preserve crash recovery guarantees

* fix(desktop): suppress crash recovery while quitting

* fix(desktop): harden crash recovery diagnostics

* fix(desktop): preserve backend breaker through updater recovery

* test(desktop): prove native crash-breaker recovery

* fix(desktop): preserve crash-breaker recovery

* fix(desktop): preserve crash history across updater recovery

* test(desktop): prove updater crash recovery wiring

* fix(desktop): preserve shutdown authority during updater failure

* test(desktop): wait for native recovery accessibility

* test(desktop): isolate crash recovery acceptance

* test(desktop): bind recovery fixture process identity

* fix(desktop): retain quit authority during update handoff

* fix(desktop): restart after failed updater stop

* Keep diff mode and Git status refresh responsive (#127)

* fix(web): keep diff and git status refresh responsive

Adapted from Synara 807acfe3c784b41229b81c4b78957681ec8e6cb2.

Remount the third-party diff renderer when its mount-time view mode changes, use the shared menu radio primitive, and prevent branch-discovery races or non-repo workspaces from starting a permanent Git-status invalidation loop. Add focused regression coverage for each boundary.

* fix(web): ignore stale Git status before repository confirmation

* fix(web): require exact branch status for git actions

* fix(git): preserve branch authority across actions

* fix(git): serialize repository mutations

* fix(git): cover repository mutation workflows

* style(server): apply repository formatting

* fix(git): isolate live mutation authority contracts

* fix(git): overlay live mutation RPC authority

* test(web): align stacked action transport contract

* Keep local HTML previews live across source changes (#130)

* fix(desktop): keep local HTML previews live

* fix(desktop): harden live preview refresh

* fix(web): clear stale HTML preview errors

* fix(web): report queued preview refresh failures

* fix(desktop): release retired preview session hooks

* fix(browser): preserve refresh ownership and latest revision

* fix(browser): close live preview certification gaps

* fix(browser): close live preview review findings

* fix(browser): close final live preview review findings

* fix(browser): close exact-head preview review findings

* test(browser): cover preview discovery limits

* fix(browser): preserve optional preview limit metadata

* test(browser): require prepared source authority

* fix(browser): attest local preview capabilities

* fix(html-preview): harden atomic refresh authority

* fix(html-preview): close source watch startup gap

* fix(desktop): close live preview review gaps

* fix(desktop): close preview ownership failure gaps

* fix(html-preview): close remaining security boundaries

* fix(html-preview): pin inspected file versions

* fix(html-preview): serve attested document bytes

* Stop duplicating completed replies in Activity (#135)

* Stop duplicating completed replies in Activity

* Prove Activity completion ownership in Chromium

* Synchronize completion regression assertions

* Show fork provenance in conversation timelines (#136)

* Show fork provenance in transcripts

* Keep unavailable fork provenance truthful

* Require confirmed provider updates (#137)

Gate the Settings > Providers Update action behind a confirmed fresh version check, and harden the confirmed-update boundary so the updater child process only ever spawns against a probed, certified, and re-validated target (closes six concurrency/TOCTOU windows). See PR description for full details.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* Fix oversized transcript–composer gap when a task panel is showing (#138)

* Fix oversized transcript–composer gap when a task panel is showing

The composer is a flex sibling below the transcript, so the stacked composer
chrome (live-changes header, active task list, queued follow-ups) already
reserves its own vertical space through the flex layout. The transcript then
fed that same chrome height into its in-list bottom spacer
(bottomContentInsetPx = composerStackedChromeHeight + 8), reserving the space a
second time. The result was a large, growing gap between the last message and
the composer whenever a task/stacked panel was present, while the no-task case
(spacer at its 64px baseline) already looked correct.

Remove the double reservation: the transcript's bottom spacer is now a fixed
64px in every state, matching the perfect no-task gap. This also retires the
now-vestigial bottomContentInsetPx prop chain (ChatView → ChatTranscriptPane →
MessagesTimeline / AgentActivityDetailView), collapsing both consumers to their
constant baseline and correcting the misleading "composer overlaps / reserves
matching bottom space" comments.

composerStackedChromeHeight is kept for its real remaining job: the
scroll-compensation layout effect that keeps the transcript pinned to its end as
the flex viewport shrinks while the chrome grows.

- Task-present gap now equals the no-task gap (single flex reservation).
- Agent activity detail view uses the same fixed baseline (it was also
  double-counting).
- No behavior change to the no-task case.

Verified: oxfmt, oxlint (0 errors), tsc --noEmit (web), and the affected
component/scroll unit tests (106 passing).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* Add regression coverage for the transcript–composer gap fix

Prove the stacked composer chrome is reserved only once: a
[geometry:linux] browser test mounts ChatView with an active task card
and again once the turn settles (no card), then asserts the gap between
the transcript tail and the composer stack is unchanged. It anchors on
the tail spacer's top (the true end of transcript content, past any
live-turn activity indicator) so a running turn does not confound the
measurement.

Verified the test fails on the pre-fix code — the gap balloons to
~180px when the task card appears — and passes on the fix (~44px in
both states).

Adds two stable test hooks: data-chat-composer-stack on the composer
block wrapper and data-testid="transcript-bottom-spacer" on the list
tail spacer.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>

* Fix file links failing to open across git worktrees (#139)

* fix(server): resolve workspace file links across git worktrees

Bare/partial file references (e.g. a chat link to `kanbanDispatch.ts`)
could fail to open with a misleading "no such file" error even though the
file plainly exists. Two root causes:

1. The filesystem-walk index descended into linked git worktrees, so a
   single logical file was indexed multiple times (the real checkout plus
   each worktree copy). The suffix resolver treats multiple matches as
   ambiguous and gave up, and the read then surfaced the realpath ENOENT
   for the literal (non-existent) path. Indexing the duplicates also
   inflated the index toward its 25k-entry cap, truncating it.

2. On a genuine ambiguity the resolver returned null, which the reader
   reported as ENOENT -- a "file not found" message for a file that exists.

Changes (server-only):
- Prune linked git worktree subtrees from the index walk (a worktree
  records `.git` as a regular file pointer, the reliable discriminator),
  and skip `.git` entries whether file or directory. Extract the shared
  worktree/skip predicates.
- Rework resolveWorkspaceFileBySuffix to return a structured result
  (resolved | ambiguous | unresolved). Resolve only on a single distinct
  match; report the competing paths on a true ambiguity instead of
  guessing between different files.
- When the cached index is truncated (unreliable), re-scan the tree
  directly (bounded) for a trustworthy candidate set.
- Surface an honest, actionable error listing the competing files instead
  of a false ENOENT. Reuses the existing WorkspaceFileSystemError tag, so
  no contract/client change.

Tests: worktree pruning, unique/ambiguous/unresolved resolution, the
worktree-duplicate scenario end-to-end, and the truncated-index disk
re-scan.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(server): don't prune submodules; fail closed on incomplete suffix scan

Follow-up correctness fixes to the worktree-aware file-link resolution.

1. Submodule false-prune. The worktree detector treated *any* directory
   whose `.git` is a regular file as a linked worktree and pruned it. Git
   submodules also store `.git` as a file, so their subtrees were pruned
   too -- silently hiding submodule files from search and link resolution.
   Discriminate by the `gitdir:` pointer target: prune only when it points
   into `.git/worktrees/<name>` (a linked worktree), never when it points
   into `.git/modules/<name>` (a submodule). Reading the pointer fails open
   (do not prune) so an unreadable `.git` can never hide real files.

2. Incomplete-scan false-unique. The bounded disk re-scan (used when the
   index is truncated) returned whatever it had found when it hit the
   scanned-directory cap. A single match found before the cap was then
   reported as a unique "resolved" even though a second match could sit in
   the unscanned remainder -- risking opening the wrong file. The scan now
   reports whether it completed, and classification fails closed to a new
   "indeterminate" outcome when an incomplete scan saw fewer than two
   matches. The reader surfaces an honest "too large to resolve, use a
   fuller path" error instead of guessing or falsely claiming ENOENT.

Tests: submodule files stay resolvable and searchable (not pruned); the
disk scan reports incomplete at its directory cap; classification fails
closed (single match from an incomplete scan -> indeterminate, two
distinct matches -> ambiguous even when incomplete, empty complete scan
-> unresolved). The existing linked-worktree fixtures now use realistic
`.git/worktrees/<name>` pointer contents.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>

* fix(web): guard Enter during IME composition in message composers (#143)

CJK/Japanese/Korean IMEs use Enter to confirm a candidate. An unguarded
Enter-to-send handler treats that confirmation keystroke as "send" and
submits a half-composed message.

Add a shared isImeCompositionKeyEvent() helper (isComposing || keyCode
=== 229) and apply it at the two message-composer key handlers:

- ComposerCommandKeyPlugin, the shared chat + kanban Lexical handler:
  swallow Enter fired mid-composition before it reaches the send/menu
  logic. Lexical already drops keydowns while editor.isComposing() is
  true, but on Safari/WebKit compositionend fires before the confirming
  keydown, so that Enter still dispatches KEY_ENTER_COMMAND; the
  keyCode === 229 branch closes that gap.
- PullRequestCommentComposer, a plain <textarea> with no Lexical gate,
  replacing its isComposing-only check so a keyCode-229 confirm no
  longer submits.

Value: correct multi-language text entry; no accidental send on IME
candidate confirmation.

Out of scope (follow-up): other bare-Enter inputs (project/rename/search
fields) share the hazard and could adopt the same helper.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>

* feat(web): self-host UI fonts, drop Google Fonts CDN (#142)

Remove the runtime Google Fonts <link> from index.html and self-host the
needed families (Geist, Geist Mono, Inter) via @fontsource-variable/*
packages, alongside the JetBrains Mono face already bundled. DM Sans was
listed in the CDN link but has zero references, so it is dropped rather
than self-hosted.

The @fontsource-variable packages register their @font-face under a
"<Family> Variable" name (e.g. "Inter Variable") while themes store the
plain family name, so add expandBundledVariableFontAliases() and apply it
at the theme->CSS-variable emission boundary: the bundled face is matched
and the plain name is kept after it as a fallback.

Value: offline usability, no third-party font beacon on launch, no font
flicker. The default appearance (systemUiFont + JetBrains Mono fallback)
needs no Google fonts, so removing the CDN cannot regress it.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>

* Make new-chat project selection safe across draft and project lifecycles

Integrate the reviewed project-picker interaction and project-lifecycle safety fixes. Complete local certification, three independent final reviews, hosted CI, and manual native visual acceptance passed.

* fix(desktop): preserve Windows Ctrl-minus zoom (#148)

* fix: preserve Windows Ctrl-minus zoom

Adapted from Synara 94b59220e26bc337406110c84220aec76b065490.

* fix: preserve shortcuts help chord compatibility

Keep the Windows physical-minus disambiguation scoped to Windows while retaining the existing Meta-or-Ctrl slash behavior on every platform.

* fix: align Windows minus shortcut routing

* Promote certified desktop integration queue (#154)

Promotes the certified July 28 desktop integration queue. Includes the reviewed work represented by PRs #123, #140, #141, #144, #149, #150, and aligned replacement #151 for #146. Supersedes #68 through the hardened #144 implementation. See PR #154 for exact heads, dispositions, verification, limitations, and rollback evidence.

* Promote certified desktop queue + v0.5.14 release note into main (#155)

* Add Claude Opus 5 capabilities

* Harden Claude capability discovery and Opus gating

* Refresh Claude discovery results

* Fail closed on Claude capability boundaries

* Scope Claude discovery to the exact runtime

* Bind Claude Opus 5 to the exact runtime

* Harden Claude Opus 5 runtime gating

* Keep Claude fresh defaults available

* fix(claude): isolate discovery lifecycle generations

* fix(claude): bind discovery cache generations

* test(web): bind Claude prefetch generation keys

* fix(claude): authorize Opus 5 from exact runtime

* fix(claude): make discovery generations monotonic

* Fix provider runtime extraction and setup progress

* fix(claude): harden discovery lifecycle ownership

* fix(claude): generation-key native slash-command discovery

Native slash-command discovery now participates in the same
renderer-owned discovery-generation scheme already used for model and
agent discovery, so a command catalog fetched under one auth/runtime
generation can never leak into a newer one.

- contracts: add optional discoveryGeneration to ProviderListCommandsInput
- server: fold discoveryGeneration into the listCommands in-flight cache
  key so a later auth generation never joins an older CLI's discovery
- client: bind the commands query to the current generation (query key,
  RPC arg, post-resolve stale discard, fail-fast retry, no stale
  placeholder for claudeAgent) and invalidate commands alongside agents
  on auth-sensitive provider changes
- route the configured Claude binary through every command-discovery
  call site (ChatView, kanban composer, /fast availability check)
- tests: cover generation separation for command discovery on both the
  server adapter and the React Query layer

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* feat(agent-gateway): host-served MCP read/coordination tools (Slice 1)

First slice of the agent gateway: a thread-scoped, host-served MCP
endpoint (`POST /mcp`) that lets an agent in one thread observe and
coordinate sibling top-level threads. Read/coordination only — no
send/interrupt, no create/fork. Behind a feature flag, disabled by
default (`SYNARA_AGENT_GATEWAY_ENABLED` / `--agent-gateway-enabled`).

Lift-and-reconcile of Synara's MIT-licensed agent gateway onto a
Scient-owned authorization + credential spine. `synara_*` names and
`synara/` namespaces kept intentionally (rebrand is a later pass).

New `apps/server/src/agentGateway/` subsystem:
- Transport/ingress auth: per-request bearer verify → thread-existence
  recheck → provider-ownership recheck → central authorization, with no
  cached grant; body cap (1 MiB) + batch cap (50); GET/DELETE mirror the
  disabled-state 404; top-level defect net upholds the never-fails
  contract on handleMcpPost.
- Credential spine: opaque per-thread tokens, in-memory registry (dies
  on restart), least-privilege (`thread:read` only), revoke-on-teardown.
- Central default-deny authorization: capability → project scope →
  thread-type; cross-project reads denied as thread_not_found.
- Read tools: synara_context, list_projects, list_threads, read_thread,
  wait_for_threads, backed by ProjectionSnapshotQuery.
- Claude provider injection via HTTP Authorization header (never the
  process env), flag-gated, revoked on teardown and failed install.

Shared-file injection hand-re-applied at current symbol anchors:
http.ts route registration, config.ts/main.ts flag, effectServer.ts
bound-port publish, ClaudeAdapter.ts/runtimeLayer.ts token lifecycle,
new packages/contracts/src/agentGateway.ts.

typecheck 9/9, full test suite 12/12 (agentGateway 168/12 incl. new
httpRoute.test.ts), lint 0 errors, brand:check green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(agent-gateway): keep contracts barrel frozen + format Slice 1 files

Resolves the two CI failures on this PR:

1. migration:check — Slice 1 added `export * from "./agentGateway"` to
   `packages/contracts/src/index.ts`. That barrel is a released-migration
   dependency (released migrations import `@synara/contracts`, and the
   lineage guard traverses the barrel's re-exports and fingerprints its
   runtime source). Adding the line both *modified* the frozen barrel and
   *pulled* `agentGateway.ts` into the released dependency closure, tripping
   the append-only guard.

   Fix: relocate the gateway contract into the server subsystem as
   `apps/server/src/agentGateway/contract.ts` and drop it from the barrel.
   Every consumer is server-side (no renderer/client consumer exists), so
   the shared package was never required. `index.ts` is restored byte-for-
   byte to the v0.5.13 baseline and `agentGateway.ts` leaves the closure.

2. fmt:check — donor-lifted test files and the ClaudeAdapter edits were not
   run through oxfmt. Applied `oxfmt` (formatting only; no behavior change).

Full gate green: brand, workflow, migration, fmt, lint (0 errors),
typecheck (9/9), test (12/12 packages, 2530 passed).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(agent-gateway): close read_thread disclosure oracle + revoke token on failed spawn

Two pre-merge security fixes on the Slice 1 read foundation, plus a
truthful token-exposure comment.

1. read_thread non-disclosure oracle. An unknown thread failed as a
   plain-text ToolInputError while a cross-project thread failed as a
   JSON GatewayToolError, so a caller could distinguish "no such thread"
   from "exists in another project" by response shape — defeating the
   deliberately byte-identical message. Route read_thread's not-found
   through GatewayToolError so both denials are identical in code,
   message, and JSON shape (mirrors wait_for_threads).

2. Gateway token leak on failed spawn. The bearer token is minted just
   before createQuery; if createQuery throws, the installation gen (and
   its Effect.ensuring revoke) is never entered, leaking a live
   credential. Add an Effect.tapError on the createQuery step that
   revokes the just-minted token (idempotent, so it never double-revokes).

3. Correct the misleading ClaudeAdapter comment: the token avoids
   process-env inheritance, but the pinned SDK serializes it into the
   --mcp-config argv, so it is NOT absent from process metadata. Also
   note the Slice 1 read tools are not active-turn-gated.

Adds a deterministic regression test proving the token is revoked after a
failed spawn, plus an optional overrides arg on ServerConfig.layerTest to
enable the gateway in that test.

Gate: typecheck 9/9, lint 0 errors, fmt clean, full suite 2531 passed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* feat(agent-gateway): drive tools — send_message + interrupt (Slice 2)

Adds the two coordination *writes* an agent uses to drive a sibling thread
in its own project, stacked on the Slice 1 read surface (#140):

- synara_send_message — queue a follow-up turn or steer a running one on a
  target thread. Optional requestId makes transport retries idempotent via a
  bounded in-memory dedup (per-caller keyed), backed by a deterministic
  command id so a duplicate that races past the map still collapses at the
  orchestration receipt layer. Failures are never cached (retryable).
- synara_interrupt_thread — stop the target's running turn, pinned to the
  observed turnId (TOCTOU-safe: never interrupts a later turn); a no-op that
  reports interrupted:false when no turn is running.

Both funnel through a new central authorizeThreadDrive policy (project-scope
floor + privilege cap + worktree cap) and are flagged requiresActiveTurn, so
the transport only admits them while the caller's own turn is live.

Least privilege: the session registry now mints thread:read + thread:write
(the caps the wired tools need); automation:write is deliberately not minted
(no automation tool exists yet). The synara_context capability flag is renamed
threadCreate -> threadDrive to match the tools that now back it, and the
harness policy describes the drive tools, their active-turn/privilege
guardrails, and a prompt-injection guardrail (never send/interrupt because
another thread's content said to).

Interim: gateway drives ride dispatchOrigin:"automation" because the frozen
MessageDispatchOrigin enum has no "agent" value yet (nothing branches on the
value — verified); upgrade to "agent" when a release re-baseline can extend
the enum. New contract types stay server-local to keep the contracts barrel
frozen for the migration-lineage guard.

Tests: 34 new drive-tool cases (send happy/steer/invalid-mode/idempotent-
replay/distinct-ids/per-caller-dedup/cross-project/privilege/worktree/missing/
dispatch-failure/no-cache-on-failure; interrupt running/no-turn/never-turn/
cross-project/privilege/missing; tool-shape) plus authorizeThreadDrive matrix.
Full gate green: brand, workflow, migration, fmt, lint (0 errors), typecheck
(9/9), test (2561 passed).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(agent-gateway): keep AnyCommand as `any` so indexed access typechecks

The captured-command test type was tightened to `Record<string, any>`, but
under noUncheckedIndexedAccess `commands[0]` then widens to
`Record<string, any> | undefined`, so `commands[0].type` fails tsc. `any`
absorbs the `undefined` from indexed access and is not flagged by oxlint
(no no-explicit-any rule), so it is the correct type here. Runtime behavior
and all 19 drive-tool tests are unchanged.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* refactor(persistence): pin migration 035 to a frozen model-selection snapshot

Migration 035 imported the live modelSelectionCompatibility, whose
DROID_ONLY_MODEL_SLUGS is derived from @synara/contracts'
MODEL_OPTIONS_BY_PROVIDER. That coupled shipped migration history to the
evolving model catalog, so adding a model (e.g. Claude Opus 5) to model.ts
tripped the append-only migration-lineage guard through the contracts barrel.

Give migration 035 its own self-contained frozen v0.5.13 snapshot
(migration035FrozenModelSelectionCompatibility) with the DROID_ONLY set
hardcoded as the exact v0.5.13 catalog-derived literal, and repoint the
migration's import to it. All other normalization logic is byte-identical to
the live helper; the live helper stays in place for its runtime consumers.

The snapshot is proven behaviorally identical to the v0.5.13 migration:
- an equivalence test asserts frozen ≡ live across a persisted corpus that
  spans every branch (canonical, provider-less ambiguous slugs incl.
  claude-opus-5, instance-label inference, legacy Gemini, option-row arrays,
  provider-scoped options) and every catalog Droid-only slug, and
- the hardcoded DROID_ONLY literal is an exact match to the droid-only set
  derived from the origin/release/stable (v0.5.13) MODEL_OPTIONS_BY_PROVIDER.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* chore(migration-guard): audited one-time allowance for the 035 decouple

Repointing migration 035 to its frozen snapshot changes the shipped
migration dependency graph: severing the sole import of the live
modelSelectionCompatibility removes the only bridge from migration history
into @synara/contracts, so modelSelectionCompatibility and the entire
contracts barrel legitimately leave the migration dependency closure while
the frozen snapshot enters it. It also changes migration 035's own content
(the import line).

Bless exactly this delta with exact, path-and-blob-pinned, one-time audited
allowances — not a general bypass and without advancing the release baseline
or touching the protected release-tag manifest:
- RELEASED_CONTENT_ALLOWANCES gains the 035 old→new blob pair.
- RELEASED_DEPENDENCY_GRAPH_ALLOWANCES (new) pins 29 removed baseline blobs
  and the 1 added frozen-snapshot blob.

Each allowance pins a Git blob, so the guard fails closed on any other
change: editing the frozen snapshot voids its added-blob allowance, and a
dependency that stays reachable but changes content is never blessed (that
branch remains a hard violation). Violation messages now emit the exact
allowance key so future audited deltas are self-documenting. Guard
self-tests cover both content and removed/added graph suppression.

This precise closure also unfreezes unrelated contract files
(e.g. providerDiscovery.ts) that were only frozen transitively through the
barrel, and lets model.ts add Opus 5 without editing shipped history.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* feat(providers): add safe sign-out controls

* fix(providers): close review gaps

* fix(providers): polish status accessibility

* fix(providers): preserve released contract lineage

* fix(providers): use native sign-out confirmation

* Fix Claude discovery generation isolation

* Fix Claude model discovery without init event

* perf(git): fetch compact diff scope stats

Adapt the server-side working-tree diff statistics lane from Synara b3fc978308b30342694c06f651dc42762fd04552. Preserve selected-scope patch rendering while replacing picker-wide patch transfers and renderer parsing with compact totals.

Donor license: MIT. Scient's existing LICENSE carries the applicable Emanuele Di Pietro copyright and MIT notice.

* fix(diff): keep selected scope count current

* fix(diff): move stats RPC outside released contracts

* fix: enforce provider archive extraction limits

* fix(web): close project actions before editing

* test(web): cover project action focus handoff

* feat(git): discover committed PR templates safely

* fix(server): harden agent gateway session boundaries

* fix(server): close agent gateway review gaps

* fix(server): bind gateway limits to session lifecycle

* fix(agent-gateway): preserve honest message provenance

* fix(orchestration): retain agent dispatch provenance

* fix(git): honor GitHub PR template variants

* fix(git): require canonical PR template names

* fix(git): require dotted template extensions

* Add governed source-control writing (#153)

Integrates the reviewed SCM writing policy into the certified desktop queue. Exact source head 13f933d passed focused and full verification plus three independent final reviews with no remaining P0-P3 findings. See PR #153 for credential, provider-isolation, provenance, rollback, and limitation evidence.

* Add floating browser preview (#152)

Integrate the reviewed floating browser preview into the desktop shadow queue.

Exact candidate c8cb572 was certified against queue base 3f7ef52 with green hosted CI, real Electron acceptance, and three independent final reviews with no unresolved P0-P2 findings.

* docs(release): add Scient v0.5.14 in-app release note

Adds the required Scient-owned v0.5.14 entry to the in-app "What's new"
catalog. Highlights the two new user-facing capabilities in this release
(floating browser preview and source-control writing help) plus the
verified refinements shipped since v0.5.13. Text-only; no artwork added.

Verified locally: release:notes:check 0.5.14, brand:check, fmt:check,
lint (0 errors), whatsNew logic tests (14), verify-release-notes tests
(12), web typecheck.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Scient Release Engineer <yaacov.corcos@datavant.com>

* Fix release preflight tag visibility (#157)

Fetch the official Synara tag set through a push-disabled remote before migration-lineage validation in Release Preflight. Preserve the reviewed 79-tag manifest and enforce the fetch commands and ordering through release smoke coverage.

* fix(release): add .ts extension to windows-authenticode import in whisper staging (#160)

Node 24 (pinned "node": "^24.13.1") runs scripts/build-desktop-artifact.ts via
native TS/ESM, which requires explicit extensions on relative imports. The new
scripts/lib/windows-authenticode.ts module (added in the 0.5.14 candidate) was
imported extensionless from scripts/stage-whisper-runtime.ts, breaking
`dist:desktop:artifact` on macOS/Linux/Windows with ERR_MODULE_NOT_FOUND.

dist:desktop:artifact only runs in release.yml (never in ci.yml), so this was
never exercised until the v0.5.14 build-only run. Every other script in scripts/
imports ./lib/*.ts with the extension (scripts/tsconfig.json sets
allowImportingTsExtensions); this brings stage-whisper-runtime.ts in line.

Co-authored-by: Scient Release Bot <yaacov.corcos@datavant.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Scient Release Engineer <yaacov.corcos@datavant.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XS upstream-review Official source changes awaiting review vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant