workspace: a memory block whose mirror fails is never retried — local and workspace memory diverge silently

Open
#1,161 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
4/5
Estimated time
3-5 days
Newbie friendliness
42/100
Issue type
Bug
Clarity
Needs clarification
Activity status
Active
Tech stack
typescript
Domain
api, backend, cli

Research direction

Start by tracing the workspace bind flow around mirrorBlock, backfillOnBind, and hydrate, then inspect the altimate-code link entry point and the local block indexing state described in the issue. Compare the local block ids or hashes with the workspace record set and decide which recovery direction is appropriate; done means failed mirrors are retried or surfaced instead of remaining local-only.

Written by the indexing model from the issue text.

Description

Found while running the workspace bind + memory mirror flow end to end against a live tenant.

What happens

When mirrorBlock can't confirm the workspace's memory setting — e.g. the /datamates/ lookup times out — it logs a warning and returns without mirroring:

[WARN] service=altimate-workspace-memory-sync could not confirm workspace memory setting
       err=WorkspaceApiError: Request to <api>/datamates/ timed out after 15s

The block is written locally, nothing is lost, and the block is deliberately left unindexed so that — per the code's own comment — "a later save retries it".

The gap is that nothing constitutes "a later save" for a block the user doesn't touch again. There is no sweep, no reconciliation on session start, and no retry queue. An untouched block that missed its mirror stays local indefinitely, while the workspace silently lacks it.

Why re-linking doesn't rescue it

The obvious recovery — re-run altimate-code link — doesn't help, for a non-obvious reason. backfillOnBind is gated on alreadySeeded, and re-selecting the workspace a directory is already linked to isn't a re-bind, so the bind path never fires and no sweep runs.

Switching to a different workspace does re-seed (sameBinding compares datamateId, so the marker stops matching) — but that's not a recovery path anyone would think to use, and it changes the binding.

Observed

During a period of degraded network, 3 of 5 memory writes failed this way. All 5 blocks existed locally; only 2 reached the workspace. Re-linking to the same workspace changed nothing. Editing one of the missed blocks caused it to mirror immediately, confirming that a re-save is the only recovery. The other two remained local-only indefinitely.

Why it matters

The failure is silent from the user's point of view — the memory tool reports success, because the local write did succeed. Local and workspace memory then diverge permanently, and nothing surfaces the divergence: the SaaS shows fewer records than the user has, and another project bound to the same workspace never sees the missing facts.

On a flaky connection this accumulates.

Possible directions

  • Session-start reconciliation — compare local block ids/hashes against the workspace's record set and push what's missing. Cheapest in the sense that hydrate already fetches that record set every session, so the comparison is nearly free.
  • Un-gate the bind sweep on an explicit re-link — makes re-running link the intuitive recovery it currently isn't.
  • Retry queue — most thorough, most machinery.
  • At minimum, surface it — the tool result currently says "Created" with no indication the mirror didn't happen.

Environment

Reproduced against a live workspace with ALTIMATE_WORKSPACE=1. Not GA-affecting while the pilot flag stays off by default.

Dominant language
TypeScript
Stars
813
Forks
134
Avg merge
2d 5h
Merged PRs (30d)
62

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from AltimateAI/altimate-code

All issues in AltimateAI/altimate-code

Similar issues

More TypeScript issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.