* fix(ai-vault): discover and parse Devin sessions on Windows, restore workspace mapping
Devin sessions never appeared in the AI Vault on Windows, and parsed
nearly empty elsewhere:
- The transcripts root hardcoded the XDG layout
(~/.local/share/devin/cli/transcripts), but Devin CLI writes under
%APPDATA%/devin/cli/transcripts on Windows. The root is now
platform-aware (APPDATA on win32, XDG_DATA_HOME elsewhere) for both
local scans and win32 remote hosts, and APPDATA joins the scanner
child's env allowlist so relocated AppData resolves.
- The parser read metadata.is_user_input / created_at / metrics, which
real ATIF-v1.7 transcripts don't carry. It now also accepts the ATIF
step shape (source, timestamp, step-level metrics/model_name,
plain-string message) while keeping the legacy shape.
- ATIF transcripts carry no working_directory, so sessions couldn't
group under a workspace. The sibling sessions.db index is now merged
through the existing sidecar seam: it fills cwd/title/model/
timestamps, honors the db's hidden flag, and re-merges on db-only
changes without re-reading transcripts.
* fix(ai-vault): inline Devin transcripts root, harden parser/db edge cases
- Resolve the platform-aware Devin cli dir in agent-sources instead of
importing the shared devin-cli-data-dir module, which is not part of
this change (broke typecheck).
- Exclude source:'system' steps unconditionally, even when legacy
metadata fields would classify them as user/assistant messages.
- Guard unix-seconds conversion against out-of-range values so a single
bad sessions.db row cannot mark the whole index unreadable.
* fix(ai-vault): watch sessions.db-wal so live Devin metadata cannot go stale
In WAL mode, committed rows sit in sessions.db-wal while sessions.db
keeps its stat until checkpoint, so keying the dependency on the db
alone could serve a stale index. The dependency now observes the wal
when one exists; the reader still opens sessions.db itself.
* fix(ai-vault): probe sessions.db-wal through the WSL-gated stat
existsSync bypasses wslGatedStat and can hang a scan on a stalled 9P
mount; the fs-import guard forbids it in session-scanner modules. The
dependency path resolution is now async and probes through the gate.
* fix(ai-vault): honor zero metrics and array messages in Devin steps
- firstDevinMetricValue skipped explicit numeric zeros, letting a
lower-priority positive metric win and overstating token totals.
- ATIF allows step.message as an array of content parts; route it
through extractContentText so those steps still feed title/preview.
* test(ai-vault): cover array-valued ATIF message extraction
The extractDevinStepText fallback that routes an array-valued
step.message through extractContentText shipped without a fixture that
produces that shape, so a future refactor could silently drop the
branch. Pin that an array of text parts feeds the step's title and
preview.
* fix(ai-vault): invalidate old Devin caches and bound database retries
* Discover current Devin ATIF exports alongside legacy transcripts
* Recognize drawn geometry in the browser markup contract test
* Deduplicate Devin exports across transcript roots
* Account for the workspace sleep-state reader in scan budget
* Align OMP integration tests with recorded-path resume
* fix: update scan benchmarks and await relay environment test
---------
Co-authored-by: Neil <neil@stably.ai>