Alexander Russell
0d6fec59d4
fix(secret_scope): memoise the shared .env tokenizer once per file change
...
load_env_file() is now the canonical .env tokenizer after c849bc383a collapsed
six hand parsers onto it. Profile scopes, dashboard boundary discovery, skill
secret capture, managed .env and setup readers share the same decoding and
parsing rules, but direct calls still re-read and re-parse the whole file.
build_profile_secret_scope() puts that work on the gateway's hottest paths:
every turn, every cron job, MCP and browser lifecycle adoption, the TUI prompt
turn, and the 60s housekeeping drain of the durable cron delivery queue.
Memoising the shared tokenizer now removes redundant work for the consolidated
readers as well as the motivating profile-scope path.
config.load_env() keeps its existing outer memo over a call that is now itself
memoised; this leaves its menu-render shortcut intact without redesigning it.
Freshness is the hard part, because a stale credential map is a far worse
failure than a slow one. Every load_env_file() call still OPENS the file and
keys on os.fstat() of that descriptor rather than os.stat() of the path:
* the open preserves close-to-open revalidation on NFS;
* an open or read failure returns {} without caching it, and drops any warm
entry so a transient EACCES cannot become a persistent empty profile;
* the descriptor pins one inode, so a symlink repointed mid-read cannot file
one file's contents under another file's identity.
The key is (mtime_ns, size, inode, device), re-checked on the same descriptor
after reading. A rewrite through that inode is not stored under the pre-read
fingerprint. Unavailable metadata means "do not cache", never "cannot read".
A generation counter checked under the lock prevents a slow reader from
repopulating an entry that a writer invalidated while the read was in flight.
Read bytes from the open descriptor and preserve upstream's decoding exactly:
strip a UTF-8 BOM before trying UTF-8, then fall back to latin-1 for invalid
UTF-8. Both the cached reader and the uncached reference use that decoder and
the shared text parser. Invalid UTF-8 is a cacheable result, not a read error.
The value and inline-comment helpers remain local to secret_scope.
invalidate_env_cache() clears this memo too, so save_env_value,
remove_env_value and sanitize_env_file invalidate both layers. The per-path
LRU holds at most 64 entries and every caller gets its own dict.
Accepted limitation: a write keeping length, inode and nanosecond mtime all
identical is not detected without explicit invalidation. This is a new
limitation for previously uncached readers. Parsed secrets also remain
reachable in memory between use and eviction for up to 64 paths, where the
outer config memo holds one.
The pre-rebase measurement on a 508-line, 25432-byte .env was 0.868 ms ->
0.011 ms per call. That measurement predates the shared binary decoder.
Add decode/cache invariants for BOM and plain files, latin-1 fallback,
same-size writes switching UTF-8 -> latin-1 -> UTF-8, and agreement with the
uncached reference. All eight decoding, cache and freshness mutations fail
the new tests, and all 40 cache tests pass after restoration.
The requested agent, CLI, cron and gateway suites report 30,168 passed,
479 failed and 303 skipped in the restricted local environment. All 140
failing files were checked against upstream/main at 5eb99eb284 : all 479
failed-test IDs and 210 collection/setup/teardown error IDs match exactly.
2026-09-17 20:56:27 +05:30
..
2026-09-16 16:50:07 -07:00
2026-09-16 16:53:20 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-15 05:19:57 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-15 04:53:38 -07:00
2026-09-10 15:13:02 -04:00
2026-09-13 09:18:02 -07:00
2026-09-11 13:06:16 +05:30
2026-09-11 13:06:16 +05:30
2026-09-13 09:18:02 -07:00
2026-09-16 17:16:06 -07:00
2026-09-16 14:34:59 -07:00
2026-09-07 08:07:26 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-07 08:07:26 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-09 10:32:01 +05:30
2026-09-14 20:35:28 +05:30
2026-09-13 09:18:02 -07:00
2026-09-07 21:43:54 +05:30
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-07 00:41:09 +05:30
2026-09-09 16:21:36 -07:00
2026-09-09 16:21:36 -07:00
2026-09-15 04:49:01 -07:00
2026-09-10 09:11:00 -07:00
2026-09-11 13:06:16 +05:30
2026-09-13 09:18:02 -07:00
2026-09-16 16:51:06 -07:00
2026-09-16 16:51:06 -07:00
2026-09-09 14:06:12 -07:00
2026-09-15 18:23:55 -07:00
2026-09-16 11:57:56 +05:30
2026-09-16 17:01:52 -07:00
2026-09-10 18:11:25 -07:00
2026-09-13 09:18:02 -07:00
2026-09-07 06:02:22 -07:00
2026-09-07 07:06:58 -07:00
2026-09-14 06:55:54 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-09 12:19:13 +05:30
2026-09-14 05:25:01 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-15 04:45:33 -07:00
2026-09-11 01:37:22 -07:00
2026-09-11 03:45:33 +05:30
2026-09-13 09:18:02 -07:00
2026-09-06 13:21:17 -07:00
2026-09-13 09:18:02 -07:00
2026-09-07 08:08:04 -07:00
2026-09-13 09:18:02 -07:00
2026-09-15 19:23:53 -07:00
2026-09-13 09:18:02 -07:00
2026-09-15 22:30:11 -07:00
2026-09-13 09:18:02 -07:00
2026-09-15 18:48:35 -07:00
2026-09-07 08:09:57 -07:00
2026-09-16 14:23:55 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-15 04:49:47 -07:00
2026-09-15 19:23:53 -07:00
2026-09-13 09:18:02 -07:00
2026-09-07 05:24:15 -07:00
2026-09-16 17:45:01 -07:00
2026-09-16 17:16:06 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-16 17:12:33 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-15 04:12:13 -07:00
2026-09-09 09:21:39 -07:00
2026-09-13 09:18:02 -07:00
2026-09-16 17:22:17 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-16 17:12:33 -07:00
2026-09-13 09:18:02 -07:00
2026-09-16 16:54:37 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-06 14:19:42 -07:00
2026-09-13 09:18:02 -07:00
2026-09-15 18:40:03 -07:00
2026-09-13 09:18:02 -07:00
2026-09-06 13:21:17 -07:00
2026-09-08 02:27:01 +05:30
2026-09-06 13:21:17 -07:00
2026-09-07 05:59:08 -07:00
2026-09-16 16:59:43 -07:00
2026-09-07 08:13:01 -07:00
2026-09-07 00:49:51 -07:00
2026-09-16 17:17:47 -07:00
2026-09-13 09:18:02 -07:00
2026-09-16 16:59:03 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 05:20:26 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 19:17:06 +05:30
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-07 22:47:33 +05:30
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-16 14:34:59 -07:00
2026-09-07 08:06:48 -07:00
2026-09-16 14:34:59 -07:00
2026-09-16 17:16:06 -07:00
2026-09-15 18:39:31 -07:00
2026-09-16 17:24:07 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-11 03:45:33 +05:30
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-16 17:48:17 -07:00
2026-09-13 09:18:02 -07:00
2026-09-16 16:58:22 -07:00
2026-09-07 22:47:33 +05:30
2026-09-09 21:16:48 +05:30
2026-09-13 09:18:02 -07:00
2026-09-07 08:19:32 -07:00
2026-09-06 05:37:03 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-10 13:23:00 +02:00
2026-09-13 09:18:02 -07:00
2026-09-16 17:08:02 -07:00
2026-09-15 18:42:10 -07:00
2026-09-12 08:23:42 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-16 17:21:57 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-15 11:03:39 +05:30
2026-09-17 12:28:25 +05:30
2026-09-15 20:44:42 +05:30
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-15 04:12:13 -07:00
2026-09-15 04:12:13 -07:00
2026-09-16 17:18:10 -07:00
2026-09-13 09:18:02 -07:00
2026-09-16 14:24:30 -07:00
2026-09-13 09:18:02 -07:00
2026-09-07 06:07:16 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-07 06:15:43 -07:00
2026-09-13 05:09:06 -07:00
2026-09-15 18:22:12 -07:00
2026-09-07 00:20:11 +05:30
2026-09-15 06:20:15 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-07 08:10:36 -07:00
2026-09-15 03:54:01 -07:00
2026-09-13 09:18:02 -07:00
2026-09-14 06:44:54 -07:00
2026-09-12 21:10:02 -07:00
2026-09-07 21:10:50 -07:00
2026-09-10 01:08:18 -07:00
2026-09-13 09:18:02 -07:00
2026-09-11 15:26:46 -07:00
2026-09-13 09:18:02 -07:00
2026-09-06 09:09:00 -07:00
2026-09-13 09:18:02 -07:00
2026-09-17 13:52:36 +05:30
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-16 17:09:50 -07:00
2026-09-16 17:09:30 -07:00
2026-09-06 14:19:42 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 21:13:23 -07:00
2026-09-11 15:26:46 -07:00
2026-09-07 06:05:13 -07:00
2026-09-12 08:23:13 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-16 17:48:17 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-07 08:28:43 -07:00
2026-09-13 09:18:02 -07:00
2026-09-07 08:28:43 -07:00
2026-09-15 18:41:19 -07:00
2026-09-13 09:18:02 -07:00
2026-09-11 11:54:49 -07:00
2026-09-15 05:38:31 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-12 08:27:11 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-12 08:22:57 -07:00
2026-09-06 13:25:48 -07:00
2026-09-06 13:25:48 -07:00
2026-09-13 09:18:02 -07:00
2026-09-15 22:30:11 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-16 17:18:10 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-07 06:15:43 -07:00
2026-09-13 09:18:02 -07:00
2026-09-17 17:10:58 +05:30
2026-09-13 09:18:02 -07:00
2026-09-16 17:09:50 -07:00
2026-09-13 09:18:02 -07:00
2026-09-15 06:18:31 -07:00
2026-09-11 15:26:46 -07:00
2026-09-12 01:35:05 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-09 16:30:24 -07:00
2026-09-07 05:24:15 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-16 17:16:06 -07:00
2026-09-17 12:28:25 +05:30
2026-09-16 11:06:06 -07:00
2026-09-15 20:44:42 +05:30
2026-09-06 09:11:04 -07:00
2026-09-15 04:17:31 -07:00
2026-09-13 09:18:02 -07:00
2026-09-15 19:10:00 -07:00
2026-09-13 09:18:02 -07:00
2026-09-15 04:51:15 -07:00
2026-09-16 17:22:17 -07:00
2026-09-17 13:52:36 +05:30
2026-09-11 15:26:46 -07:00
2026-09-13 09:18:02 -07:00
2026-09-15 03:54:58 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-07 04:38:59 -07:00
2026-09-13 14:46:42 -07:00
2026-09-13 09:18:02 -07:00
2026-09-06 02:18:14 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-16 11:06:06 -07:00
2026-09-09 12:42:02 +05:30
2026-09-15 04:13:13 -07:00
2026-09-16 21:39:13 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-09 09:59:13 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-16 17:16:06 -07:00
2026-09-13 09:18:02 -07:00
2026-09-16 17:23:44 -07:00
2026-09-16 17:17:47 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-16 17:07:21 -07:00
2026-09-12 13:44:52 -07:00
2026-09-15 05:42:35 -07:00
2026-09-13 05:09:43 -07:00
2026-09-13 09:18:02 -07:00
2026-09-12 08:06:48 -07:00
2026-09-16 17:21:57 -07:00
2026-09-07 08:24:54 -07:00
2026-09-10 02:44:26 -07:00
2026-09-15 18:59:55 -07:00
2026-09-13 09:18:02 -07:00
2026-09-09 12:19:13 +05:30
2026-09-10 13:23:24 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-06 14:04:05 -07:00
2026-09-13 19:23:09 +05:30
2026-09-16 17:08:02 -07:00
2026-09-16 17:16:06 -07:00
2026-09-16 14:23:20 -07:00
2026-09-13 05:09:43 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-08 04:38:47 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-15 03:39:07 -07:00
2026-09-13 09:18:02 -07:00
2026-09-15 18:18:08 -07:00
2026-09-09 17:04:30 +05:30
2026-09-13 09:18:02 -07:00
2026-09-17 20:56:27 +05:30
2026-09-13 05:32:38 -07:00
2026-09-15 04:12:13 -07:00
2026-09-15 04:12:13 -07:00
2026-09-13 09:18:02 -07:00
2026-09-15 00:41:14 +05:30
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-06 05:35:12 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-07 08:08:41 -07:00
2026-09-16 17:50:21 -07:00
2026-09-13 09:18:02 -07:00
2026-09-12 07:54:57 -07:00
2026-09-13 05:07:11 -07:00
2026-09-13 09:18:02 -07:00
2026-09-12 08:25:36 -07:00
2026-09-12 08:25:59 -07:00
2026-09-15 03:34:20 -07:00
2026-09-16 21:15:30 +05:30
2026-09-13 09:18:02 -07:00
2026-09-06 13:08:31 -07:00
2026-09-13 09:18:02 -07:00
2026-09-12 21:07:46 -07:00
2026-09-15 18:42:10 -07:00
2026-09-16 17:10:13 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-15 18:21:17 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-15 12:46:27 +05:30
2026-09-07 05:24:15 -07:00
2026-09-13 21:27:35 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-16 17:08:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-15 04:46:36 -07:00
2026-09-15 18:19:26 -07:00
2026-09-13 09:18:02 -07:00
2026-09-14 20:35:28 +05:30
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-09 10:31:26 +05:30
2026-09-16 17:48:48 -07:00
2026-09-16 06:27:23 -05:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 14:46:42 -07:00
2026-09-13 09:18:02 -07:00
2026-09-16 10:43:48 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 05:09:43 -07:00
2026-09-15 18:23:07 -07:00
2026-09-13 09:18:02 -07:00
2026-09-16 17:08:25 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-12 08:25:14 -07:00
2026-09-13 21:13:23 -07:00
2026-09-16 17:10:13 -07:00
2026-09-10 10:27:07 -07:00
2026-09-06 13:21:17 -07:00
2026-09-16 21:15:30 +05:30
2026-09-13 09:18:02 -07:00
2026-09-15 04:18:34 -07:00
2026-09-15 04:12:13 -07:00
2026-09-10 13:23:00 +02:00
2026-09-15 04:12:13 -07:00
2026-09-15 18:21:44 -07:00
2026-09-16 10:43:48 -07:00
2026-09-16 17:48:17 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 09:18:02 -07:00
2026-09-15 20:44:42 +05:30
2026-09-06 13:52:15 -07:00
2026-09-13 09:18:02 -07:00
2026-09-15 04:45:33 -07:00
2026-09-06 13:21:17 -07:00
2026-09-10 02:44:26 -07:00
2026-09-15 19:10:00 -07:00
2026-09-13 09:18:02 -07:00
2026-09-09 02:35:41 -07:00
2026-09-09 02:35:41 -07:00
2026-09-09 02:35:41 -07:00
2026-09-07 08:08:41 -07:00
2026-09-09 02:35:41 -07:00
2026-09-13 09:18:02 -07:00
2026-09-13 14:46:38 -07:00
2026-09-15 04:48:20 -07:00
2026-09-13 09:18:02 -07:00
2026-09-17 12:28:25 +05:30
2026-09-17 12:39:05 +05:30