Commit Graph
5086 Commits
Author SHA1 Message Date
Rod Boev e88e4ecefc fix(#4694): treat fetch timeout diagnostics as network failures 2026-06-24 19:29:06 +00:00
Rod Boev a3eac6a538 fix(#4694): surface non-network git fetch failures in updates 2026-06-24 19:29:06 +00:00
nesquena-hermes 25dc1dcd2a Release WJ (v0.51.629): macOS workspace drag-drop now lands (#4845, closes #4757)
Release WJ (v0.51.629): macOS workspace drag-drop now lands (#4845, closes #4757)
2026-06-24 12:27:36 -07:00
nesquena-hermes d313a899fc Release WJ (v0.51.629): macOS workspace drag-drop now lands (#4845, closes #4757) 2026-06-24 19:23:32 +00:00
nesquena-hermesandRod Boev c21d30e02b fix(#4757): defer window-drop cleanup a tick so target ondrop runs first (gate finding)
Codex re-gate: the capture-phase window 'drop' listener fired BEFORE the target
el.ondrop, clearing _wsActiveDragPath before _isWorkspaceTreeMoveDrag/_wsDragSrcPath
ran — re-breaking the macOS stripped-MIME move it set out to fix. setTimeout(_clearWsDragData,0)
lets the real drop handler complete, then clears the lingering flag.

Co-authored-by: Rod Boev <rod.boev@gmail.com>
2026-06-24 19:13:59 +00:00
nesquena-hermesandRod Boev 63e3f91654 harden(#4757): gate stripped-MIME drop on text/plain===tracked path + robust drag-flag cleanup (gate finding)
Codex gate found a SILENT hazard: if a workspace drag is abandoned without
ondragend firing (cancel/drop-outside/blur), _wsActiveDragPath lingered and a
later FOREIGN text/plain drag could be misread as a workspace move. Hardening:
- _wsDragSrcPath now only trusts the active flag when the drop's own text/plain
  EQUALS _wsActiveDragPath (a foreign/empty text drag resolves to '' -> no move).
- Shared _clearWsDragData() called from ondragend, a drop finally, and
  window-level dragend/drop/pagehide/blur fallbacks (lost-dragend cleanup).
- 2 regression tests (stale-flag foreign-text -> empty; _clearWsDragData resets),
  proven non-vacuous.

Co-authored-by: Rod Boev <rod.boev@gmail.com>
2026-06-24 19:06:30 +00:00
Rod Boev 30c9f5e52a fix(test): use regex for let-declaration extraction resilience (#4757) 2026-06-24 18:58:33 +00:00
Rod Boev 2ef8a5f827 fix: add node portability guard to drag-drop test 2026-06-24 18:58:33 +00:00
Rod Boev 36fee0c6a4 fix(#4757): add active-drag flags so macOS workspace drag-drop lands 2026-06-24 18:58:33 +00:00
nesquena-hermes f61de2a178 Release WI (v0.51.628): no ghost messages after edit/retry/undo (#4772, closes #4767)
Release WI (v0.51.628): no ghost messages after edit/retry/undo (#4772, closes #4767)
2026-06-24 11:53:00 -07:00
nesquena-hermes 4816f0a38e Release WI (v0.51.628): no ghost messages after edit/retry/undo (#4772, closes #4767) 2026-06-24 18:48:39 +00:00
nesquena-hermesandAlexeyDsov 6a7fe93e10 fix(#4767): gate boundary-advanced bypass on checkpoint consumption (no stale-suffix resurrection)
Codex final-gate found the boundary<watermark advanced signal made
sidecar_advanced_past_watermark globally true, so a stale ts>watermark suffix
row appearing in state.db BEFORE the edited checkpoint bypassed the skip and
resurrected. Gate the bypass on state_replay_idx >= len(sidecar_visible_sequence)
(checkpoint consumed); apply the same gate to the same-second CORE-B exception.
Regression test added + proven non-vacuous. All legit cases (state-only reply
after checkpoint, CORE-B same-second) still pass.

Co-authored-by: AlexeyDsov <alexeydsov@gmail.com>
2026-06-24 18:39:02 +00:00
nesquena-hermesandAlexeyDsov 695d9ab814 fix(#4767): keep state-only post-edit reply when sidecar tail equals advanced watermark (Codex final gate)
Final-gate Codex repro found a non-empty-sidecar drop: when the post-edit USER
turn is checkpointed into the sidecar (ts == advanced watermark) but its
ASSISTANT reply exists only in state.db (ts > watermark), the
sidecar_advanced_past_watermark guard was False (max_sidecar_timestamp ==
watermark, not >), so the 'timestamp > watermark' skip dropped the legitimate
reply. GET /api/session returned ['first','first reply','edited prompt'] and
omitted the assistant.

Fix: treat truncation_boundary < watermark (genuinely advanced) as advanced too,
so post-watermark state-only rows merge through even when the sidecar tail only
EQUALS the watermark. Conservative skip preserved for boundary None / == watermark.
Hoisted the loop-invariant boundary check out of the per-message loop. Regression
test added + proven non-vacuous.

Co-authored-by: AlexeyDsov <alexeydsov@gmail.com>
2026-06-24 18:21:34 +00:00
nesquena-hermesandAlexeyDsov 7317e29d82 fix(#4767): guard empty-sidecar reconstruction against not-advanced watermark (Opus gate)
Opus deep-gate found a latent data-loss the Codex harnesses missed: the
empty-sidecar branch kept at_or_after (ts>=watermark) UNCONDITIONALLY, which is
only valid once the watermark was ADVANCED strictly past the original cutoff
(a new turn committed -> boundary < watermark). In the not-advanced states the
content above the watermark is the deleted suffix, so it got resurrected — the
same data-loss class this fix exists to kill. Reachable via crash/cold-load
metadata-vs-sidecar divergence.

- Keep at_or_after ONLY when boundary < watermark (genuinely advanced).
- boundary == watermark (just truncated) OR boundary is None (legacy: a positive
  watermark always meant 'frozen at cutoff' pre-#4767) -> conservative ts<=watermark
  filter; never resurrects.
- Replaced the backward-scan heuristic with the provable boundary guard.
- Removed the now-dead 'or (not sidecar_messages and watermark>0)' clause in the
  non-empty-sidecar path (unreachable; empty sidecar returns earlier).
- Added 2 regression tests (boundary==watermark, legacy None-boundary), both proven
  non-vacuous; updated 2 contributor tests that assumed advanced-watermark-without-boundary
  (an unreachable state) to pass the boundary the real persistence path always writes.

Co-authored-by: AlexeyDsov <alexeydsov@gmail.com>
2026-06-24 18:08:50 +00:00
nesquena-hermesandAlexeyDsov 6ce9533d53 test(#4767): route-level CORE-A regression — /api/session full reload honors truncation_boundary
Co-authored-by: AlexeyDsov <alexeydsov@gmail.com>
2026-06-24 18:08:50 +00:00
nesquena-hermesandAlexeyDsov aac220b625 fix(#4767): thread truncation_boundary through remaining full-load merge call sites (CORE-A)
The contributor's empty-sidecar recovery uses the persisted truncation_boundary
to distinguish a legitimate prefix from a deleted suffix, but two production
call sites still passed only truncation_watermark — the default /api/session
full reload (routes.py ~9504) and _merged_session_messages_for_display
(routes.py ~6098) — so a normal full reload fell back to the old 'drop one
turn pair' heuristic and resurrected deleted suffix turns when an OLDER message
was edited leaving >=2 later turns. Thread truncation_boundary through both.

Co-authored-by: AlexeyDsov <alexeydsov@gmail.com>
2026-06-24 18:08:50 +00:00
AlexeyDsov 037253e4fc fix(#4767): review fixes - more edge cases 2026-06-24 18:08:50 +00:00
AlexeyDsov 195d53ea90 fix(#4767): review fixes - edge cases 2026-06-24 18:08:50 +00:00
AlexeyDsov 0a1c94e5c8 fix(#4767): review fixes 2026-06-24 18:08:50 +00:00
Alexey Denisovandgreptile-apps[bot] d76abfb734 Update api/streaming.py
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
2026-06-24 18:08:50 +00:00
AlexeyDsov e1bbf3e807 fix(#4767): advance truncation_watermark instead of clearing to None after edit/retry/undo (#2914, #3831) 2026-06-24 18:08:50 +00:00
nesquena-hermes 3917400c80 Release WH (v0.51.627): cron Task APIs survive a shadowing top-level cron package (#4855)
Release WH (v0.51.627): cron Task APIs survive a shadowing top-level cron package (#4855)
2026-06-24 10:56:25 -07:00
nesquena-hermes 36c92d8bd2 Release WH (v0.51.627): cron Task APIs survive a shadowing top-level cron package (#4855) 2026-06-24 17:53:14 +00:00
Ruyan a7788792fb fix: prefer agent cron package for task APIs 2026-06-24 17:52:57 +00:00
nesquena-hermes f22affb638 Release WG (v0.51.626): restore mobile streaming scroll-jank guard (#4857)
Release WG (v0.51.626): restore mobile streaming scroll-jank guard (#4857)
2026-06-24 10:48:15 -07:00
nesquena-hermes caf36d11dd Release WG (v0.51.626): restore mobile streaming scroll-jank guard (#4857) 2026-06-24 17:40:30 +00:00
Brett Yelverton 2a40ca4240 fix(streaming): restore mobile scroll-jank guard during live renders
A later streaming parse-cache change dropped the #MOBILESCROLL guard from
the live-stream render tick while leaving the helper and CSS in place.
On iOS PWA, Safari can paint a transient scrollTop=0 frame during streamed
DOM rebuilds, forcing the reader to the first/oldest message.

Re-add _fixMobileScrollJank() before streaming DOM work begins and pin it
with a regression test so the third layer of the mobile scroll fix cannot
be silently dropped again.
2026-06-24 17:20:40 +00:00
nesquena-hermes c70105cf35 Merge pull request #4840 from nesquena/stage/4813-cron-prefix
Release v0.51.625 — cron job model override no longer keeps the @provider: display prefix (#4813)
2026-06-24 04:13:39 -07:00
nesquena-hermes f84db40a23 test(#4813): resolve node via shutil.which + skip if absent (CI portability)
The hardcoded /home/hermes/.local/bin/node doesn't exist in CI runners. Use
shutil.which('node') with a module-level skipif, matching the repo's other
node-driven tests.
2026-06-24 11:07:54 +00:00
nesquena-hermes eb331b5163 release: stamp v0.51.625 (#4813 cron model @provider prefix strip) 2026-06-24 11:02:44 +00:00
nesquena-hermes 984fd9557c Merge remote-tracking branch 'origin/master' into gate/4813-cron-prefix 2026-06-24 11:01:50 +00:00
nesquena-hermes adacf2fb17 Merge pull request #4839 from nesquena/stage/4832-kanban-height
Release v0.51.624 — bound the Kanban column card-list height (#4832)
2026-06-24 03:54:37 -07:00
nesquena-hermes d755ed1c06 test(#4813): cover _cronModelBareName provider-prefix strip matrix
The contributor PR had no test for the new helper. Adds Node-driven coverage:
matching-provider prefix stripped, unprefixed untouched, no/mismatched provider
untouched, empty/null passthrough. Co-authored-by: luandnh
2026-06-24 10:51:24 +00:00
nesquena-hermes 9493f1640f Merge branch 'peek-4813' into gate/4813-cron-prefix 2026-06-24 10:49:48 +00:00
nesquena-hermes b9e4e24cbc release: stamp v0.51.624 (#4832 bound kanban column card-list height) 2026-06-24 10:49:28 +00:00
nesquena-hermes 631f1a35da Merge branch 'peek-4832' into gate/4832-kanban-height 2026-06-24 10:38:49 +00:00
nesquena-hermes a287980799 Merge pull request #4838 from nesquena/fix/4702-portrait-scroll-bottom
Release v0.51.623 — iOS portrait: opening a conversation lands at the bottom (#4702)
2026-06-24 03:28:54 -07:00
nesquena-hermes 718cefc264 release: stamp v0.51.623 (#4702 iOS portrait open-scroll-to-bottom) 2026-06-24 10:25:20 +00:00
nesquena-hermes 7fe6861a54 test(#4702): thread _lastMessageClientHeight through the scroll-pin-reentry JS harness
The #4295 harness runs the extracted scroll-handler body in a Node new Function();
the body now references _lastMessageClientHeight, so it must be a param + threaded
through state (seeded null, samples keep clientHeight stable so grew stays false and
the pin-reentry assertions are unchanged).
2026-06-24 10:15:04 +00:00
Hoang Luan 78cd8798ec Merge branch 'master' into fix/cron-model-provider-prefix 2026-06-24 17:05:29 +07:00
nesquena-hermes 671f4504ae fix(#4702): co-seed _lastMessageClientHeight with every programmatic _lastScrollTop write (Codex gate)
Codex found the guard had a first-event gap: programmatic seeds of _lastScrollTop
(_setMessageScrollToBottom, scrollToBottom, snapshot restore paths) didn't seed
_lastMessageClientHeight, so the FIRST native toolbar-collapse scroll saw a null
prior height -> grew=false -> the false-unpin still fired. Now every programmatic
_lastScrollTop=el.scrollTop is paired with _lastMessageClientHeight=el.clientHeight.
2026-06-24 10:02:52 +00:00
nesquena-hermes fe40912eb9 fix(#4702): don't false-unpin a freshly-opened session on iOS portrait toolbar settle
iOS Safari portrait resolves its dynamic toolbar height after first paint; when the
toolbar collapses the #messages scroller grows (clientHeight up), firing a scroll
event with decreased scrollTop that was misread as an upward user scroll -> falsely
set _messageUserUnpinned, and the ResizeObserver settle then self-cancelled, leaving
the reader stranded at the TOP of a freshly-opened conversation (landscape unaffected
since it doesn't resize late). Sibling of #4701.

Fix (touch-safe, no-op on desktop/landscape where clientHeight is stable):
- Track _lastMessageClientHeight; gate movedUp on !grew so a container-height
  INCREASE can't be read as an upward scroll. Reset on session switch.
- For explicit (open) settles, also observe the scroller itself so a late portrait
  toolbar collapse re-anchors the bottom.

Independent of #4818 (overflow-anchor paint-gap) — different mechanism, coexists.
Diagnosis credit: investigation. Co-authored-by: reinocheong <reporter>
2026-06-24 09:56:06 +00:00
nesquena-hermes dabbf06575 Merge pull request #4837 from nesquena/fix/4768-cron-graceful-degrade
Release v0.51.622 — Tasks tab no longer 500s when the cron package is absent (#4768)
2026-06-24 02:41:04 -07:00
nesquena-hermes 77b59f7c85 test(#4768): drop unused 're' import (ruff F401) 2026-06-24 09:29:15 +00:00
nesquena-hermes 054e39151b release: stamp v0.51.622 (#4768 cron-absent Tasks tab graceful degrade) 2026-06-24 09:24:54 +00:00
nesquena-hermes f4e150e105 Merge remote-tracking branch 'origin/master' into fix/4768-cron-graceful-degrade 2026-06-24 09:23:37 +00:00
nesquena-hermes 853c367241 Merge pull request #4835 from nesquena/stage/4241-vietnamese
Release v0.51.621 — Vietnamese UI language (#4241)
2026-06-24 02:15:14 -07:00
nesquena-hermes 1e3132376b fix(#4768): only treat absent cron package as unavailable, re-raise real import bugs (Codex gate)
ModuleNotFoundError fires both when cron.jobs is absent AND when an existing
cron/jobs.py fails to import its own dependency. Catch as exc and only return the
graceful {jobs:[],cron_unavailable:true} when exc.name is 'cron'/'cron.jobs';
re-raise otherwise so a real cron bug isn't silently swallowed.
2026-06-24 09:12:46 +00:00
nesquena-hermes 61f3c766df release: stamp v0.51.621 (#4241 Vietnamese UI language) 2026-06-24 09:11:06 +00:00
jkobject 93afd60425 fix(kanban): bound column card list height 2026-06-24 10:57:03 +02:00