Skip to content

Releases: rasyidmmz/dsh-ai-memory

v1.3.0 — native DSH capture with safe legacy compatibility

Choose a tag to compare

@rasyidmmz rasyidmmz released this 22 Oct 22:11

Adds native DSH capture identity support for ai-memory 3.2.0 and later. Finalization uses each stored session's actual dsh or claude-code identity, never the server version. Explicit agentKind still wins; unavailable stores fall back to legacy capture. Sweeper excludes unrelated harnesses and preserves row identity. No hook/profile rewrites or database relabeling. Includes migration guidance and 27 passing checks (16 smoke, 11 SQLite regressions). Source contract checked at upstream 3.2.0/3.2.1; not a live 3.2.1 consolidation test. Full changelog: https://github.com/rasyidmmz/dsh-ai-memory/blob/v1.3.0/CHANGELOG.md

v1.2.1 — declare dsh.engines for marketplace compatibility gating

Choose a tag to compare

@rasyidmmz rasyidmmz released this 18 Oct 07:00

Metadata only; behaviour unchanged from 1.2.0.

Added

  • dsh.engines in package.json: dsh: ">=0.1.7-rc.2 <0.3.0" and node: ">=22.5.0". dsh-market reads an own engines.dsh range as the authoritative compatibility declaration, so an incompatible host is refused at install instead of failing at runtime. The DSH floor is where ctx.shell.execute() replaced run(); the ceiling is the 0.2.x line this release was verified on. Node's floor is where node:sqlite (the sweeper's read-only store access) became available.

Changed

  • Repository description now states what the plugin does and that it ships the capture-hook template.

v1.2.0 — startup diagnosis for a marketplace install

Choose a tag to compare

@rasyidmmz rasyidmmz released this 18 Oct 06:16

The plugin can be installed from a marketplace in one row, but it cannot install ai-memory or wire DSH's capture hooks. Until now that looked like 'loaded, idle'. It now says which piece is missing, once, with the next step.

  • Checks the configured ai-memory binary, its data directory (config.toml), and whether the running DSH profile wires @deepseek-ai/dsh-hooks-claude-code.
  • Each miss prints a concrete step: the upstream install link, ai-memory init, or the absolute path to the shipped docs/hooks-dsh.json.
  • 'server did not answer' now says how to start one.
  • npm test = 16 checks, including a clean profile producing no output at all.

No change to the finalize path: same events, same CLI arguments, same sweeper.

v1.1.2 — re-verified on DSH 0.2.1-rc.2 and ai-memory 3.1.1

Choose a tag to compare

@rasyidmmz rasyidmmz released this 18 Oct 06:09

Compatibility re-verification; no behaviour change.

  • DSH 0.2.1-rc.2 (installed app.asar): agent/created, agent/disposed, session/disposed still emitted; ctx.sessions.get().header still carries cwd/origin/delegationDepth; ctx.shell still execute()-only.
  • ai-memory 3.1.1: finalize-session keeps --agent/--workspace/--project/--session-id/--reopen/--json; output lines unchanged (Finalized … / No open … sessions matched …); session ids still uuid5(NAMESPACE_OID, native id).
  • Store upgrade: a 2.6-era store opens under 3.1.1, migrates to schema V83, sweeper query returns the same rows.
  • docs/hooks-dsh.json now matches the running configuration (PreToolUse included with its measured cost, Stop->hook-drain chain explained, insert-form profile row, Windows 0xC0000142 sandbox note).
  • New: test/smoke.mjs — 11 in-process checks via npm test.

v1.1.1

Choose a tag to compare

@rasyidmmz rasyidmmz released this 18 Oct 07:00

Fixed

  • The identity support added in 1.1.0 never ran in the common case. The
    candidate that resolves a marker's identity to the project that owns it was
    placed inside the branch that runs only when the session's folder sits BELOW
    the marker root. But a marker that declares only identity is the root it
    sits in, so the session's own folder is that root — precisely the case the
    branch excludes. On any folder whose name differs from the identity's project,
    the plugin looked the session up under the folder name instead, got
    No open ... sessions matched, and left it to the sweeper.

    Found by running the installed plugin against a real identity with a real
    shell, not by the unit test: that test put the session in a subfolder, so it
    exercised the harder case and walked straight past the common one. There is a
    test for both shapes now, and the old code fails the new one.

    Behaviour for markers without identity is unchanged.

Verified

  • Feature suite 9/9 on the published source, 7/7 on the local variant (two
    assertions skipped there, with the reason printed). Against 1.1.0 the same
    suite scores 8/9 — the new assertion is the one that fails.
  • Behaviour suite 19/19; parity SEPADAN (18 units).

v1.1.0

Choose a tag to compare

@rasyidmmz rasyidmmz released this 18 Oct 07:00

Built against ai-memory 2.5.2. Two changes, both driven by that release.

Added

  • A marker's identity is honoured. ai-memory 2.5.0 gave every project an
    identity that is deliberately not its folder name (#708) and routes captures
    by it; identity in .ai-memory.toml outranks project, and a marker that
    declares only identity is valid.

    The plugin does not try to reproduce the naming rule — which name owns an
    identity is the SERVER's decision on first sighting, and guessing it is what
    caused the 1.0.4 bug. It reads the answer back out of projects.identity
    (migration V70) with one indexed lookup, and falls back to the folder name
    when there is no answer. Read-only; any failure is silent.

  • A session that continued after a finalize can be re-finalized. ai-memory
    2.5.0 added finalize-session --reopen (#836). This matters for one concrete
    failure the plugin could otherwise cause and not repair: the sweeper
    closing a session it wrongly judged abandoned. Its page was then built from
    the first half, and because the session had ended, no later finalize could
    ever update it — everything the agent did afterwards was lost.

    --reopen is now used for exactly that case: once per session, only for a
    session this process already finalized, and only after a plain finalize
    answers No open ... sessions matched. Re-running with nothing new is a
    documented no-op, so the case where another harness ended the session is
    harmless.

Changed

  • "Already finalized" is now a question about time, not a flag. The guard
    that stops two events describing one session end from finalizing twice
    (Bug 1) was a set, which cannot tell "the second event of one end" from "a
    genuinely new end hours later". It is a timestamped map with a 60-second
    window, and only a finalize outside that window is allowed to reopen.

    Stated plainly: a session that ends twice inside those 60 seconds gets only
    the first finalize. The window is far wider than the millisecond race the
    guard exists for, and can be overridden with AI_MEMORY_DEDUP_WINDOW_MS.

Verified

  • New suite uji-fitur-1.1.0.mjs: 6/6 on the published source, 5/5 on
    the local variant (one assertion is skipped there, with the reason printed —
    that variant reads a fixed database path and cannot take an injected one).
    Against 1.0.5 the same suite scores 2/6, which is how the new behaviour is
    shown to be what makes it pass.
  • Existing behaviour suite 19/19; parity between the variants SEPADAN
    (18 compared units).

v1.0.5

Choose a tag to compare

@rasyidmmz rasyidmmz released this 18 Oct 07:00

Fixed

  • The startup log no longer reports a stale version. VERSION was a
    hand-edited constant, and it fell behind package.json twice — first
    active v1.0.0 while package.json said 1.0.2, then active v1.0.3 while
    package.json said 1.0.4. Both times the only visible symptom was a log line
    that lied, which is exactly the question that line exists to answer: which
    build is actually loaded?

    The version is now read from the package.json shipped beside the module, so
    there is no number left that can go stale. If it cannot be read, the log says
    active v? rather than guessing.

    Version 1.0.4 is functionally correct but announces itself as v1.0.3. If
    you are on 1.0.4 and the log bothers you, this is the release that fixes it;
    there is no behavioural difference between the two.

Verified

  • uji-label-versi.mjs — the guard that caught this — now passes for the
    published repo. It imports the plugin, runs apply() against a mock context
    and compares the captured log line with package.json, so a computed version
    is checked for real rather than pattern-matched.
  • Behaviour suite 19/19, parity SEPADAN (17 units).

v1.0.4

Choose a tag to compare

@rasyidmmz rasyidmmz released this 18 Oct 07:00

Fixed

  • A session opened in a subfolder is now finalized into its project's root.
    ai-memory derives a session's project from its working directory, and a
    .ai-memory.toml marker pins the name only for the folder that HOLDS it —
    measured with ai-memory doctor: run from C:\Code\Dsh\arsip-dump it answers
    project arsip-dump, not dsh, while the workspace is still inherited from
    the ancestor marker.

    So a session started in <project>\sub was looked up under a project named
    sub, the CLI answered No open ... sessions matched, and the session was
    left to the sweeper instead of being summarized on the spot. The plugin now
    walks up from the session's directory to the nearest marker and tries that
    project FIRST, so the fast path succeeds the same way it does for a session
    opened at the root.

    The walk stops at a .git boundary, so a nested repository such as
    ai-memory/plugin-publik keeps its own project instead of being folded into
    its parent. A session whose folder is not inside a marker root behaves exactly
    as before — the previous behaviour is still in the candidate chain, so a
    session captured before this change (project = folder basename) finalizes too
    rather than being retried on every sweep.

    Nothing else changed: no new configuration, no new dependency, and the
    resolution is bounded and silent (any failure falls back to the old path).

Verified

  • Behaviour suite 19/19, against the installed copy, the published source and
    the local variant. Three of those assertions are new and cover this case: with
    the previous code they fail (17/19), which is how the fix was confirmed to be
    the thing that makes them pass.
  • Parity between the local and published variants: SEPADAN (17 compared
    units — the two new scope helpers included, so the rule cannot drift between
    them).

v1.0.1

Choose a tag to compare

@rasyidmmz rasyidmmz released this 18 Oct 07:00

Do not use this version on DSH 0.1.7-rc.2. It contains both bug fixes below
but still calls ctx.shell.run(), which no longer exists there. It installed
cleanly and finalized nothing. See 1.0.2.

Fixed

Two real bugs, both found in the field rather than by reading code.

  • A session was finalized twice. agent/disposed carries the id
    session-<uuid>, while session/disposed carries the bare stored UUID. The
    same session therefore entered the queue twice within milliseconds, through two
    different id shapes. Both were checked against finalizedRecently at
    enqueue time — when the first finalize has not finished and the set is still
    empty, so both passed. pump() did not re-check, so the CLI ran twice: ~2.2 s
    and one ai-memory.exe process wasted, the second call answering
    No open claude-code sessions matched.

    Observed in the log before the fix:

    04:41:18.237 finalizing session session-
    04:41:20.482 session -> page created
    04:41:20.482 finalizing session c37c3911   (SAME session, second call)
    04:41:22.665 session c37c3911 -> no open session matched
    

    Fixed by de-duplicating in pump() on the normalised UUID, so a duplicate is
    caught regardless of which event enqueued it.

  • Session labels in logs were the useless constant "session-".
    id.slice(0, 8) applied to a raw session-<uuid> id yields "session-", so
    every session logged identically and the line told you nothing. Labels now come
    from shortLabel(), which strips the prefix first and therefore always shows
    the real UUID's first 8 characters.

Verification

  • A functional test drives the plugin with a stub ctx and sends two events for one
    session. Before the fix it made 3 finalize-session calls; after, 1.
  • Unit tests cover shortLabel for a raw id, a bare UUID, and an empty string
    (4/4).

Note for the record

The first attempt at the duplicate-finalize fix was itself wrong: it guarded on
!hinted, but the fast path records a sweepProjects hint and enqueues, so the
duplicate always arrives as a hinted item and the check caught nothing. The
functional test caught that — not code review.

v1.0.0

Choose a tag to compare

@rasyidmmz rasyidmmz released this 18 Oct 07:00

Added

  • Initial release, published as dsh-ai-memory-bridge and renamed to
    dsh-ai-memory the same evening. Closes ai-memory's consolidation loop for
    DSH: on session end, calls ai-memory finalize-session so captured
    observations become searchable wiki pages.
  • Skips subagents (only main sessions are finalized).
  • Queues concurrent session ends instead of dropping them.
  • Sweeps sessions abandoned by a forced restart.
  • Handles both id shapes: session-<uuid> from agent/disposed and the bare
    stored UUID from session/disposed.
  • docs/ ships in the npm package so the README's hook example link resolves.