Skip to content

V3.8.2 fixbug#34

Merged
deepagent-ai merged 4 commits into
mainfrom
dev
Jul 9, 2026
Merged

V3.8.2 fixbug#34
deepagent-ai merged 4 commits into
mainfrom
dev

Conversation

@deepagent-ai

Copy link
Copy Markdown
Contributor

Issue for this PR

Closes #

Type of change

  • Bug fix
  • New feature
  • Refactor / code improvement
  • Documentation

What does this PR do?

Please provide a description of the issue, the changes you made to fix it, and why they work. It is expected that you understand why your changes work and if you do not understand why at least say as much so a maintainer knows how much to value the PR.

If you paste a large clearly AI generated description here your PR may be IGNORED or CLOSED!

How did you verify your code works?

Screenshots / recordings

If this is a UI change, please include a screenshot or recording.

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

If you do not follow this template your PR will be automatically rejected.

deepagent-ai and others added 4 commits July 9, 2026 09:25
A legacy session persisted with directory "/" made the app unusable after
upgrading: the V3.8 instance-boot guard (assertSafeInstanceRoot) rejects a
"/"-rooted directory — correct, since it would make the file-tool permission
boundary the whole disk — but the client kept re-requesting that boot, so it
surfaced as an endless retry storm reported only as "unexpected server error"
when loading conversations. Root cause was pre-existing dirty data, not this
release; the guard simply started refusing it.

Two fail-closed guards so no user hits this again:

- server-sync (client): bootstrapInstance now refuses a filesystem-root
  directory up front and shows a clear toast, instead of firing the doomed
  server boot and storming on retry. Adds a dependency-free isFilesystemRootDir
  (posix "/" and Windows drive/UNC roots) + toast.project.rootRefused strings.
- import writer: refuses to import a source session whose OWN cwd is a
  filesystem root — such a session could never be opened later. Checks the
  source cwd, NOT the resolved project dir, so a non-git session that
  legitimately maps to the `global` project (worktree sentinel "/") still
  imports. Per-session import is isolated, so it skips just that one. Adds a
  regression test.

The user's live dirty row (one session at "/") was cleaned separately from the
DB; these guards prevent recurrence.

Verified: typecheck 2/2; import + question + task + structured-output 63/63;
i18n parity green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ing, sidebar rename

Reply timeline:
- Move elapsed time + token count to a live top-left per-turn badge (ticks
  from thinking-start until completion), change the reply footer from elapsed
  duration to the reply's date+time.
- Roll subagent (child-session) token usage into the parent turn total,
  deduped by child sessionId; show each subagent's usage on the task box.

Context accounting:
- Top-right gauge now reports REAL retained context (input+cache.read+
  cache.write), excluding generated output/reasoning tokens.
- Add a cumulative conversation-token total (all turns + descendant subagent
  sessions) to the usage tooltip and context tab; hide the unaligned cost.

Sidebar:
- Double-click a session row to rename in place (optimistic update + rollback).
- Right-click context menu (Rename/Archive/Delete) aligned with Codex's thread
  actions; Delete shows a confirm dialog, Archive runs directly.

i18n: add duration.hoursMinutes, tool.agent.tokens, conversation-token keys
across all locales.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…3.8.1 §G)

Learned facts default to project scope and global promotion needs manual
review, so cross-project operational facts (test servers, containers,
endpoints) never surface in a new project. This adds a governed fast path
for verifiable, non-directive, desensitized environment facts: they
auto-admit to a user-global `provisional` status without gate-7 review,
and each project decides at first use whether to adopt them.

Core:
- document-store: new `environment_fact` DocType + `provisional` DocStatus
  (non-knowledge; excluded from retrieve() so it is never silently injected)
- environment-fact: pure desensitize (fail-closed on residual secrets),
  fast-path routing, per-(project×fact) adoption decision, and a
  connection-failure -> stale matcher (§G.6)
- environment-fact-adoption: per-project use-gate service (adopt / reject /
  modify with global-correction vs project-override), file-backed sidecar
- durable-knowledge-store: provisional write + env-fact list/stale helpers
- agent-gateway: connection-failure hook degrades adopted facts on a
  connect error observed during a run

Server: HTTP endpoints GET /deepagent/env-facts, POST /env-facts/{decide,modify}

App: use-gate section in the review dialog — adopt/reject cards plus an
inline edit form (host/port/container/purpose/notes; global vs project
scope). Credentials are never editable or displayed (secret_ref pointers
only). Pure client API split into dialog-review.api.ts so the route
contract test loads server-side.

Boundaries held: credentials never enter memory (desensitize fail-closed),
strategy/methodology still go through human review, cross-org never projects.

Tests: 24 core (desensitize/routing/adoption/staleness) + 8 app route
contract. Full deepagent suite 477/477, all packages typecheck clean.

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

Clicking a code-review/researcher subagent conversation in the sidebar
crashed the renderer and reloaded the desktop app. Root cause: subagent
messages persisted before d6c325e stored `info.format` as a plain object.
OutputFormatText/OutputFormatJsonSchema are Schema.Class with
instanceof-gated encoders, so serializing such a stored message on the
messages read path threw "Expected OutputFormatJsonSchema, got {...}" at
["info"]["format"], rejecting fetchMessages and killing the renderer.
d6c325e fixed the write path but not already-persisted rows.

- message-v2: normalizeFormat() coerces a stored plain-object format to an
  instance via the same decodeUnknownExit(Format) path the write side uses
  (idempotent, fills retryCount default, both variants). Applied in info(row)
  — the single choke point every stored message flows through on read.

Also, per request, agent-spawned subagent conversations no longer appear in
the sidebar; only human-initiated forks nest under their origin.

- helpers: new forkParentID() (forkedFrom only, ignores parentID) drives
  directChildSessions. roots() still excludes subagents via sessionOriginID,
  so a hidden subagent neither nests nor leaks in as a top-level row.
  Subagents remain reachable via the subagent panel.

Tests: structured-output 30/30 (4 new normalizeFormat regressions),
message-v2 36/36, app layout helpers 29/29 (subagent-exclusion + roots
no-leak). deepagent-code + app typecheck clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@deepagent-ai
deepagent-ai merged commit 7aaf064 into main Jul 9, 2026
5 of 17 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant