You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Stop-hook capture overwrites the per-session transcript each turn — only the first turn of every session ever syncs; later turns are silently dropped as "unchanged" #5
Every ZCode session syncs to Nowledge Mem with only its first turn (1 user + 1 assistant message). All subsequent turns in the same session are captured by the Stop hook but never imported. There is no error anywhere; the failure is silent.
Observed across 9 sessions spanning two days: every per-session transcript in plugins/data/nowledge-mem-zcode@nowledge-zcode/transcripts/ contains exactly 2 lines (the latest turn at capture time), and every zcode-sess_* thread in Nowledge Mem contains exactly the first turn.
Root cause
Three parts compound:
The hook overwrites the per-session transcript instead of accumulating.copiedTranscriptPath() in hooks/zcode-mem-hook.mjs does writeFileSync(out, body) on a fixed per-session path. Because completeTranscript() pairs only the uncleared pending prompts (cleared after each successful sync) with the assistant-only Stop transcript, each Stop emits exactly one turn and replaces whatever was there before.
nmem t sync reconciles an existing thread positionally, not by content. Re-syncing a transcript that contains only turn 2 for a thread that already has turn 1 returns:
The 2 new messages are never appended — same count, same positions → "unchanged".
--checkpointed can't cover the gap yet: nmem t sync --from zcode --checkpointed returns "checkpointed automatic capture is not yet available for zcode; use the normal sync path".
Proof the server appends fine when the transcript is cumulative
Controlled experiment with a throwaway session (cleaned up afterwards):
Sync a 2-message transcript → created.
Append 2 more messages to the same transcript file, sync again → "action": "appended", "messages_added": 2, "total_messages": 4. ✅
So the server-side reconciliation appends correctly as long as each sync receives the full conversation so far. The plugin is the side sending only the delta.
Server: enable --checkpointed capture for the zcode source, so per-turn deltas append from a durable checkpoint.
In the meantime, a doctor/status check that compares the transcript's turn count against the thread's message count would surface the silent drop.
Footnote
The 0.2.1 changelog says new sessions "retain ordered user and assistant turns" — with this bug, that only holds for the first turn of each session. The save-handoff skill remains the only reliable path for multi-turn sessions today.
Environment
nowledge-mem-zcode0.2.1 (installed from the GitHub marketplace source; hooks confirmed loaded)Symptom
Every ZCode session syncs to Nowledge Mem with only its first turn (1 user + 1 assistant message). All subsequent turns in the same session are captured by the Stop hook but never imported. There is no error anywhere; the failure is silent.
Observed across 9 sessions spanning two days: every per-session transcript in
plugins/data/nowledge-mem-zcode@nowledge-zcode/transcripts/contains exactly 2 lines (the latest turn at capture time), and everyzcode-sess_*thread in Nowledge Mem contains exactly the first turn.Root cause
Three parts compound:
The hook overwrites the per-session transcript instead of accumulating.
copiedTranscriptPath()inhooks/zcode-mem-hook.mjsdoeswriteFileSync(out, body)on a fixed per-session path. BecausecompleteTranscript()pairs only the uncleared pending prompts (cleared after each successful sync) with the assistant-only Stop transcript, each Stop emits exactly one turn and replaces whatever was there before.nmem t syncreconciles an existing thread positionally, not by content. Re-syncing a transcript that contains only turn 2 for a thread that already has turn 1 returns:{"action": "unchanged", "messages_added": 0, "total_messages": 2}The 2 new messages are never appended — same count, same positions → "unchanged".
--checkpointedcan't cover the gap yet:nmem t sync --from zcode --checkpointedreturns "checkpointed automatic capture is not yet available for zcode; use the normal sync path".Proof the server appends fine when the transcript is cumulative
Controlled experiment with a throwaway session (cleaned up afterwards):
created."action": "appended", "messages_added": 2, "total_messages": 4. ✅So the server-side reconciliation appends correctly as long as each sync receives the full conversation so far. The plugin is the side sending only the delta.
Suggested fixes
Any one of these closes the gap:
copiedTranscriptPath(), append each reconstructed turn to the existing per-session file (or rebuild the full conversation from the sqlite store, as in the workaround described in Hooks silently not loaded from a local directory marketplace; ZCode 0.16.5 Stop transcript is assistant-only so stock sync always fails #2) instead ofwriteFileSync-overwriting it. This matches whatt syncalready expects and makes every sync idempotent.--checkpointedcapture for the zcode source, so per-turn deltas append from a durable checkpoint.Footnote
The 0.2.1 changelog says new sessions "retain ordered user and assistant turns" — with this bug, that only holds for the first turn of each session. The
save-handoffskill remains the only reliable path for multi-turn sessions today.