The #6717 burst-reset call grows the renderMessages() preamble, pushing the
render-window reset past the probe's 1400-char slice. Widen it to 2400; the
guard-before-reset ordering assertion is unchanged and still passes on master.
_scheduleMessageVirtualizedRender now takes (force, request), so the two
structural probes in test_issue4346_vscroll_footer_jitter.py matched nothing.
renderMessages() calls _resetMessageVirtualMeasurementBurst(), which node
harnesses that extract renderMessages() alone (test_compaction_current_summary_fallback.py)
don't define; guard it with typeof like the file's other optional helpers.
The production guard now ends the burst only on a non-consecutive repeat
(A -> B -> A), so a window needing a second re-measure is not mistaken for
oscillation. Update the structural assertion to that condition.
Layer three additive pieces on top of the #7021 / #6931 continuation
predicate without changing its shape or CONTINUATION_STARTED_AT_TOLERANCE_SECONDS:
- _reset_from is a boundary marker alongside _branched_from/_delegate_from
(Hermes Agent stamps it in gateway/session_recovery.py and filters it in
_NON_CONTINUATION_CHILD_FILTER_SQL). The same predicate drives the sidebar
listing, lineage metadata/report and the transcript stitcher.
- _branch_markers() returns ('none' | 'markers' | 'unknown', markers);
unparsable, non-object, too-deep, or non-string marker payloads are
'unknown' and fail closed as a lineage boundary instead of degrading to
"no markers" (fail open).
- gateway_watcher._snapshot_hash() hashes the complete canonicalized published
payload, and the cheap fingerprint covers model_config, so a projection change
to title/created_at/metadata with fixed (id, updated_at, message_count) emits
sessions_changed.
The row-id fast path for a marked native-image mirror row continued
without advancing state_replay_idx, unlike the ordinary and multimodal-
mirror replay paths. The edited checkpoint then never read as consumed,
so a rerun reply that exists only in state.db was truncated. Master (no
marker branch) keeps that reply.
Advance the replay index when the resolved sidecar row is the next
expected visible row, the same guard the mirror branch uses. Adds a
regression that fails without the fix: sidecar [u1,a1,img#42,a_img,uE],
state [.., marked img#42, a_img, u_old, a_old, uE, aE], watermark 900,
boundary 861 -> aE survives, u_old/a_old stay out.
Found by the release-manager advisor gate on #7754.
mcp 2.x removed mcp.server.fastmcp (the high-level server is now
mcp.server.MCPServer), so the fake stdio server in this test failed to
start on hosts with mcp 2.x installed and four tests failed there. CI pins
mcp<2, so this only affected local runs. Try the 1.x import first and fall
back to the 2.x name.
Apply the existing truncation and checkpoint-order eligibility to marked
state.db image rows before insertion. Keep removed turns out of full,
limited, and model-context reads without changing no-watermark replay.
Preserve conflicting provider payloads for a uniquely proven retained
image row across Undo without restoring distinct removed rows.
Assisted-by: Hermes Agent:gpt-6-sol
Assisted-by: Codex:gpt-6-luna
Review gate on #7720 (two regressions reproduced against master with the
installed Agent):
1. Deleting a profile's last MCP server left ADOPTED tools callable after
/reload-mcp. The scoped teardown only stops connections the profile owns,
and the Agent's discover_mcp_tools() returns before its reconcile step
when the profile's config has no server, so an adopted shared connection
was never judged against the config. /reload-mcp now calls
register_mcp_servers({}) under the profile's scope before rediscovery:
the Agent's overlay heal detaches only this profile's overlay for servers
its config no longer has; the owner's connection keeps running (master's
wildcard shutdown stopped the owner too).
2. Portable plugin MCP servers are merged by the Agent at runtime and never
appear in the profile's raw ``mcp_servers``; the registry fallback
required a config entry and dropped every plugin tool from
/api/mcp/tools and the Notes inventory. The profile's own registry slot
(registry_tool_owned_by_view) is the isolation check; the config is not
an allowlist any more.
Tests (red before, green after): agent-free unit tests for both (the fake
agent now models the overlay heal and discovery's empty-config early
return), and a real-Agent integration test for the adopted-then-deleted
case (owner connection survives, adopter slot emptied, "Removed" reported).
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Review follow-up on #7720 (Greptile P2): the external Notes drawer reads the
same profile-bound MCP inventory as the MCP panel but dropped the
``runtime_scope`` label, so a profile whose runtime scope could not be
confirmed rendered its note sources as inactive/configured with no
explanation. ``/api/notes/sources`` now returns ``runtime_scope`` and the
drawer shows the existing ``mcp_runtime_scope_unavailable`` notice (same key,
no new locale strings) when it is ``unavailable``.
Tests: the skewed-routing unit test now also asserts the notes response
carries ``runtime_scope: "unavailable"`` with its sources inactive.
docs/troubleshooting.md mentions the drawer next to the panel.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Two profiles configuring a same-named MCP server shared one connection and
the MCP settings panel showed another profile's runtime ("Active, N tools"
next to an empty inventory); /reload-mcp stopped every profile's servers and
rediscovered from the process-default config.
- api.profiles._set_hermes_home() is the single writer of the process-profile
home: it records get_process_profile_home() and hands it to Hermes Agent's
hermes_constants.pin_process_hermes_home when available, at startup and on
switch_profile(process_wide=True), so the per-turn HERMES_HOME mirror no
longer makes every turn look like the process profile (bare-name,
cross-profile MCP keys) and the anchor cannot drift from HERMES_HOME.
- Run get_mcp_status/registry reads and /reload-mcp inside
api.mcp_runtime.mcp_runtime_scope(): request profile's Hermes-home override
and secret scope (root included), no os.environ mutation, restored on exit.
- One ledger predicate, ledger_key_serves_view() (owned via
_server_scope_keys/key scope, or adopted via _server_tool_scopes), is shared
by status, inventory and the reload summary. The Agent's launch-profile view
is process-wide and name-indexed, so filter_runtime_status_to_view()
rebuilds connected/tools/status/error from the entries serving the profile:
the root profile never shows a routed profile's connection (nor lets its own
parked failed-spawn task borrow a routed profile's live same-named one).
- Inventory lists only tools in the profile's own registry slot for servers it
configures; responses carry runtime_scope.
- Fail closed when the agent's routing does not match the resolved profile:
hide runtime data (runtime_scope "unavailable", shown as a notice in the MCP
panel, 14 locales) and refuse /reload-mcp.
- /reload-mcp shuts down only the profile's own ledger names (parked
included), drops its own connect cooldown/error entries so a failed spawn is
retried (the wildcard cleared every cooldown; a scoped shutdown only clears
the live keys it tears down), rediscovers under the profile's home and
counts live connections only. The bare wildcard remains for agents without
profile-scoped MCP.
- Signature introspection is centralized (accepts_keywords) and falls back to
the bare call instead of blanking every status; ledger key helpers resolve
to the Agent's tools.mcp_tool_scope when present; tools.mcp_tool is
resolved by full name so stubbed agents still work.
- ARCHITECTURE.md §4.10 and docs/troubleshooting.md document the boundary.
- Tests: agent-free contract (models adoption, parked tasks, cooldowns and the
process-wide root view) and real-Agent integration (fake stdio MCP server,
skips without hermes-agent + mcp SDK).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The sidecar default is now 'no opinion' (None) so the projection can fall
back to state.db's archived flag. Update the #4842 perf test's missing-
sidecar expectation to match.
Co-authored-by: webtecnica <webtecnica@users.noreply.github.com>
A pending approval/clarify prompt re-surfaces on every 1.5s poll tick, and
with permission still 'default' (second browser/device) each tick issued a
non-gesture Notification.requestPermission() and toasted 'notifications
denied'. Auto requests are now made once per page; the explicit Send-test
path still always asks. Release-gate hardening on top of #7493.