Skip to content

Sync phase 2: env hydration, consolidation lifecycle, provider retry, unified data-dir - #6

Closed
ChronodeAi wants to merge 6 commits into
sync/v0.9.29-phase1from
sync/v0.9.29-phase2
Closed

Sync phase 2: env hydration, consolidation lifecycle, provider retry, unified data-dir#6
ChronodeAi wants to merge 6 commits into
sync/v0.9.29-phase1from
sync/v0.9.29-phase2

Conversation

@ChronodeAi

Copy link
Copy Markdown
Owner

Stacks on #5 (base = sync/v0.9.29-phase1).

Ports from upstream v0.9.29 (6cc9b9f subset, d8b5267+e04ba88 core) with fork reconciliation:

  • Env hydration: hydrateProcessEnvFromFile() — fill-missing-only at boot; one precedence chain: real env > ~/.agentmemory/.env > project manifest > defaults; project-config.loadAgentmemoryEnvironment now delegates (dotenv import dropped). Wired after --version/--help early-exits to preserve the fork's documented exit promise.
  • Provider retry: 429/503 honoring Retry-After (seconds or HTTP-date), 3 attempts max, 5s delay cap, 170s total budget below the iii 180s timeout; 9 upstream regression cases adapted.
  • Consolidation on session stop: fires mem::consolidate-pipeline + auto-crystallize inside the existing background-pipeline keyed lock and only after persistPipelineSuccess, debounced by a serialized cooldown marker (AGENTMEMORY_CONSOLIDATION_COOLDOWN_MS, default 5min); stage-resume state never re-runs completed stages; payloads are project-scoped per fork scope policy.
  • Unified data-dir resolver: new src/data-dir.ts — --data-dir flag > AGENTMEMORY_DATA_DIR > ~/.agentmemory default (fork-compat; no platform-dir switch). Upstream's silent cwd ./data adoption is deliberately NOT ported (memory-poisoning vector): warn once and require explicit --data-dir instead.

Build hygiene: hook bundles regenerated; picocolors added to alwaysBundle after the hydration path made config.ts's provider hint reachable from the _auth chunk (isolated-plugin-tree test caught it).

Test plan

  • vitest run: 1834 passed / 1 failed — the same pre-existing cli-connect repair failure present on unmodified main
  • tsc --noEmit: byte-identical to baseline error set
  • R13 preflight passes with credentials configured
  • evidence:interfaces:test passes

Port the 6cc9b9f env-hydration subset. hydrateProcessEnvFromFile()
copies ~/.agentmemory/.env into process.env fill-missing-only, so a
real environment value always wins, and is wired before the first
config read in both entries (src/cli.ts after the --version/--help
exits, src/index.ts at the top of main()). loadEnvFile() is memoized
for the process lifetime with a __resetEnvFileCache() test hook.

loadAgentmemoryEnvironment() now delegates hydration to that single
implementation instead of re-parsing the file with dotenv, giving one
precedence story everywhere: real environment > ~/.agentmemory/.env >
project manifest overrides > defaults.
…psed budget

Port the 6cc9b9f _fetch.ts subset. fetchWithTimeout now retries
429/503 responses (max 3 total attempts) with the Retry-After delay —
integer-seconds or HTTP-date form, clamped to a 5s per-delay cap and
falling back to exponential backoff when absent. Retries are bounded by
the caller's TOTAL timeout budget, hard-capped at 170s so attempts +
sleeps can never approach the iii 180s invocation timeout; the first
attempt honors the capped budget too, and each late attempt gets only
the remaining time. Discarded response bodies are cancelled before
retrying so connections return to the pool.

Brings the bounded-retry regression cases from upstream's
test/fetch-timeout.test.ts: first-attempt cap, single retry, hostile /
oversized / HTTP-date Retry-After, small-budget bail-outs, and the
persistent-503 attempt cap.
…h a cooldown

Port the 6cc9b9f consolidation-lifecycle subset, reconciled with the
fork's persistent background-pipeline state. After the stop pipeline
reaches a successful terminal state — inside the existing
withKeyedLock('background-pipeline:'+sessionId) — the handler fires
mem::consolidate-pipeline {tier:'all',force:true} and
mem::auto-crystallize {olderThanDays:0}, both scoped to the session's
project (fork project-scope rules), gated on isConsolidationEnabled()
so keyless installs never fire no-op LLM work.

Debounce: a consolidation:lastRun marker in KV.config bounds corpus
consolidation to once per AGENTMEMORY_CONSOLIDATION_COOLDOWN_MS
(default 5 min, 0 disables). The read-check-write is serialized through
an in-process chain so concurrent stops cannot both pass. The gate sits
after every resume/supersede/terminal early-return, so retried runs
consume the cooldown only when they actually complete, stages the
resume machinery marks complete are never re-run, and failed pipelines
leave the marker untouched.

getConsolidationCooldownMs() added to config. New
test/consolidation-lifecycle.test.ts covers fire-once payloads, cooldown
suppression and expiry, debounce-disabled mode, stage-resume interplay,
failure paths not consuming the window, keyless gating, and concurrent
stop serialization; session-end-triggers-graph pins CONSOLIDATION_
ENABLED=false to keep its exact fan-out assertions hermetic.
…cy ./data warning

Port the d8b5267/e04ba88 core with fork semantics replacing upstream's:
src/data-dir.ts exports resolveDataDir() resolving --data-dir (separated
or = form) > AGENTMEMORY_DATA_DIR > ~/.agentmemory, with ~/ expansion
and cwd-relative resolution. Upstream's platform-default dirs and its
automatic adoption/copying of a legacy cwd ./data store are NOT ported;
instead, when no explicit data dir is configured and a ./data directory
holding an agentmemory store marker exists in cwd, boot logs a warning
pointing the operator at an explicit --data-dir.

config.ts drops the module-load DATA_DIR constant: the .env path,
loadConfig().dataDir, snapshot dir, and standalone persist path now
resolve lazily through the resolver; migrate.ts validates migration
dbPaths against allowedDirs() from it. cli.ts parses --data-dir before
anything reads the environment (folding the flag over any pre-set
AGENTMEMORY_DATA_DIR so flag > env holds for spawned processes), emits
the legacy-store warning once at boot, and documents the flag in --help.
Shared chunk hashes moved with the hydration/data-dir/retry changes;
CI rebuilds these committed outputs and a stale tree fails the R13
dirty-worktree check.
The hydration wiring made config.ts's provider hint reachable from the
_auth chunk, leaving an external picocolors import in committed bundles
and breaking the isolated-plugin-tree invariant. Bundle it like dotenv
and yaml so hooks stay dependency-free.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant