Skip to content

Releases: Opita-Code/dark-memory-mcp

v2.7.0-alpha

Choose a tag to compare

@github-actions github-actions released this 29 Jul 00:02

Full Changelog: v2.6.2...v2.7.0-alpha

v2.6.2

Choose a tag to compare

@github-actions github-actions released this 28 Jul 22:37

v2.6.2 — fix npm wrapper optionalDependencies (v2.6.1 patch)

⚠️ Why v2.6.2 exists

v2.6.1's npm wrapper was tagged with a package.json whose
optionalDependencies block still referenced
@opitacode/dark-memory-mcp-{darwin,linux,win32}-{x64,arm64}@2.6.0 (the
previous release). When a user ran
npx -y @opitacode/dark-memory-mcp@2.6.1, npm pulled the v2.6.0
platform packages, so the user effectively got v2.6.0 binaries from
a v2.6.1 install.

Functional impact was limited: the GitHub Release binaries
and MCPB bundles for v2.6.1 were correct (self-bootstrapping,
reproducible builds). Only the npm install path was broken.

v2.6.2 is a patch release that re-bumps the npm wrapper with
correct optionalDependencies for v2.6.2 platform packages.

🎯 For users

Use v2.6.2. The v2.6.1 release notes have been updated with a
warning pointing here.

# upgrade
npm install -g @opitacode/dark-memory-mcp@2.6.2
# or use npx
npx -y @opitacode/dark-memory-mcp@2.6.2

🔧 What's actually new in v2.6.2

  • npm/wrapper/package.json:
    optionalDependencies now references v2.6.2 platform packages
    (matching the wrapper version).
  • All other v2.6.1 → v2.6.2 changes are version bumps only.

🆕 v2.6.1 highlights (carried into v2.6.2)

v2.6.1 was the first follow-up to v2.6.0 (the self-bootstrapping
release) and shipped 3 real changes plus a version-bump. The npm
wrapper bug masked them in v2.6.1; v2.6.2 re-publishes the same
binaries with a correct npm wrapper.

1. migrate.CurrentSchemaVersion() — exported helper

internal/tools/agent_bootstrap.go's
detect_environment tool previously hardcoded SchemaVersion: 20.
Now reads from sqlite.CurrentVersion() which iterates the
compiled-in Migrations slice. Adding a new migration now
automatically updates the tool's reported schema version — no
manual sync needed.

internal/migrate.CurrentSchemaVersion(migs []Migration) int
internal/migrate/sqlite.CurrentVersion() int  # convenience

7 new tests in 2 new test files (5 logic tests + 2 integration
tests).

2. publish-mcp-registry.yml race condition fix

publish-npm.yml and publish-mcp-registry.yml triggered in
parallel on the same tag push. mcp-publisher's publish step
validates against the npm registry, which has a 5-30s CDN
propagation delay. Race window: registry workflow reaches publish
before npm's CDN has indexed the new version, so mcp-publisher
returned a 404. v2.6.0 hit this once (manual recovery).

Fix: wrap ./mcp-publisher publish in a retry loop (up to 3
attempts with 30s sleeps). Common case (npm propagates <30s):
succeeds on first retry. Worst case: ~90s of retries.

MAX_ATTEMPTS=3
RETRY_DELAY=30

Test: tests/distribution/mcpb_v2_6_1_test.go::TestV261_RegistryPublishRetryLoop.

⚠️ Note: v2.6.2's own registry publish ran into a slower npm
CDN propagation than the 90s retry budget. The retry loop
exhausted and required manual workflow_dispatch recovery
(same pattern as v2.6.0). The retry loop is in place for the
common case; for the slow case, manual rerun remains the
fallback. Future enhancement: bump to 5 attempts × 60s.

3. docs/agent-bootstrap.md + README update

New operator-facing doc explains the self-bootstrapping architecture
(5 layers, decision tree, DARK_AGENT_BOOTSTRAP_DIR override).
README updated with the new "🪜 Self-Bootstrapping (AGENT_BOOTSTRAP
— 3 tools, v2.6.0)" section. Tool count: 35 → 38 across 12 namespaces.

📦 Distribution

All channels live for v2.6.2:

  • npm wrapper: 6 platform packages + wrapper (correct
    optionalDependencies this time).
  • Official MCP Registry: published via manual workflow_dispatch
    after retry exhaustion (see note above).
  • GitHub Releases: 9 assets.

🔮 Follow-ups

  • Bump publish-mcp-registry retry budget to 5 × 60s (~5 min
    worst case). Today's 3 × 30s budget (~90s) is sometimes too
    short for slow npm CDN propagation.
  • Move to workflow_run trigger for publish-mcp-registry.yml
    so it waits for publish-npm.yml completion before starting.
    Trade-off: more complex trigger config vs simpler inline retry.
  • Consider --force for npm publish to allow v2.6.1 hotfix
    (today, broken versions can't be re-published — must bump
    to next version, which is what v2.6.2 does).

📝 Commits since v2.6.0

021e04c fix(dist): v2.6.2 - bump wrapper optionalDependencies to 2.6.2
b869923 fix(dist): v2.6.1 - bump wrapper optionalDependencies to 2.6.1
a824984 chore(release): bump versions 2.6.0 -> 2.6.1
d14c16e docs(v2.6.1): agent-bootstrap.md + README Self-Bootstrapping section
49c8126 fix(ci): v2.6.1 publish-mcp-registry npm propagation race (retry loop)
84d92fa feat(migrate): export CurrentSchemaVersion helper
5e410f6 ci: re-trigger CI to verify v2.6.0 drift fix

Full Changelog: v2.6.0...v2.6.2

v2.6.1

Choose a tag to compare

@github-actions github-actions released this 28 Jul 22:34

⚠️ KNOWN ISSUE: v2.6.1 npm wrapper has stale optionalDependencies

The @opitacode/dark-memory-mcp@2.6.1\ wrapper's \optionalDependencies\ block still references @opitacode/dark-memory-mcp-{darwin,linux,win32}-{x64,arm64}@2.6.0\ (the previous version). When a user runs
px -y @opitacode/dark-memory-mcp@2.6.1, npm pulls the v2.6.0 platform packages, so the user effectively gets v2.6.0 binaries from a v2.6.1 install.

Fix: use v2.6.2 instead. Its wrapper correctly references v2.6.2 platform packages.

Functional impact:

  • GitHub Release v2.6.1 binaries: ✅ correct (self-bootstrap content, reproducible builds).
  • MCPB bundle v2.6.1: ✅ correct (manifest references the v2.6.1 binary).
  • npm install path: ❌ pulls v2.6.0 platform packages (uses old binaries).

For v2.6.2+ users: use
px -y @opitacode/dark-memory-mcp@2.6.2.


Full Changelog: v2.6.0...v2.6.1

v2.6.0

Choose a tag to compare

@github-actions github-actions released this 28 Jul 21:52

v2.6.0 — dark-agent self-bootstrapping + reproducible-builds fix

🌟 Headline: dark-agent self-bootstrapping

Any MCP harness (Claude Desktop, Claude Code, opencode, Cline, Cursor, Continue)
can now discover how to operate dark-memory-mcp without external docs.
The server publishes a canonical operating manual + a per-harness
compatibility matrix + 6 install guides + 2 companion docs via MCP resources
(URI scheme dark-memory://docs/*). Three new tools make that content
discoverable programmatically.

5 layers (all non-invasive)

# Layer Path
L1 System-prompt resource dark-memory://docs/system-prompt.md (8.9 KB)
L2 Compatibility matrix dark-memory://docs/compatibility-matrix.md (3.8 KB)
L3 Install URI templates dark-memory://docs/install/{client}.md × 6
L4 instructions field cross-feature hints appended to the initialize response
L5 Companion URI templates dark-memory://docs/companions/{name}.md × 2

3 new self-bootstrap tools (AGENT_BOOTSTRAP namespace)

Tool Purpose
dark_memory_agent_bootstrap Read any resource by surface/target (system_prompt, compatibility_matrix, install_guide, companion, all)
dark_memory_agent_recommend_companions Harness-aware companion advice (dark-research, dark-copilot)
dark_memory_agent_detect_environment Harness runtime introspection (clientInfo + negotiated capabilities)

Dual-spec clientInfo capture

Both legacy 2025-06-18 (initialize.clientInfo) and new 2026-07-28
(_meta.clientInfo per-request) feeds converge into a single
ClientInfoRecord store; the bootstrap tools read from there.

Operator override

DARK_AGENT_BOOTSTRAP_DIR env var points to a custom directory with
the 10 expected files. Validated at load time; invalid → fallback to
embedded + warning.

Why this matters

opencode (issue #32856) discards the instructions field. Claude
Desktop/Code honor it but only for the initial session. Resources
are the canonical cross-harness path
because every spec-compliant
harness MUST support resources/list + resources/read.

Wire contract

100% additive. Schema v20 unchanged. Canonical tool count grows
35 → 38 (AGENT_BOOTSTRAP between RESEARCH and VIBE per RFC D-9).
10 new resources. No existing tool renames, no position shifts.

🔧 Reproducible-builds drift fix

publish-npm.yml and build-mcpb.yml now produce byte-identical
binaries across all 6 platforms. Verified by:

  • Go patch pin: go-version: "1.25.12" (was "1.25")
  • SOURCE_DATE_EPOCH env var sourced from git log -1 --format=%ct
    (commit timestamp; deterministic per tag)

Local + CI verification:

Binary SHA256
GitHub Release dark-mem-mcp-amd64.exe-win32 EB38AAD411D3F866...
npm package dark-mem-mcp-win32-x64/bin/dark-mem-mcp.exe EB38AAD411D3F866...

MATCH (drift eliminated).

3 new structural tests in tests/distribution/mcpb_v2_6_0_test.go:

  • TestV260_ReproducibleBuildsSetup_NPMWorkflow
  • TestV260_ReproducibleBuildsSetup_BuildMCPBWorkflow
  • TestV260_ReproducibleBuildsSetup_GoVersionsMatch (catches accidental version skew)

📦 Distribution

All channels live for v2.6.0:

  • npm: 6 platform packages + wrapper (verified published)
  • Official MCP Registry: io.github.Opita-Code/dark-memory-mcp@2.6.0
    (published after retry — see known issue below)
  • GitHub Releases: 9 assets (3 .mcpb bundles + 6 raw binaries)

⚠️ Known issue (post-tag fix)

publish-mcp-registry.yml failed on the initial tag push with
NPM package '@opitacode/dark-memory-mcp' exists, but version '2.6.0' was not found — a race condition: the registry workflow ran before
npm propagation completed. Fixed via manual workflow_dispatch -f version=2.6.0 retry (14s, success).

Follow-up for v2.6.1: add needs: [publish-npm-platform] or a
small wait + retry loop in publish-mcp-registry.yml.

🚀 Quick install

# Claude Desktop / Cursor / Cline / Continue
# Add to your MCP config:
{
  "mcpServers": {
    "dark-memory": {
      "command": "npx",
      "args": ["-y", "@opitacode/dark-memory-mcp@2.6.0"]
    }
  }
}

# Claude Code
claude mcp add dark-memory -- npx -y @opitacode/dark-memory-mcp@2.6.0

# opencode (in opencode.json)
{
  "mcp": {
    "dark-memory": {
      "type": "local",
      "command": ["npx", "-y", "@opitacode/dark-memory-mcp@2.6.0"]
    }
  }
}

Then on first connect, the LLM will see the 3 self-bootstrap tools
in its tool list. Recommend it call dark_memory_agent_bootstrap
with surface="all" to load the full operating manual.

📝 Commits since v2.5.2

5e410f6 ci: re-trigger CI to verify v2.6.0 drift fix
a720c3d chore(release): bump versions 2.5.2 -> 2.6.0
e9cd31a fix(ci): v2.6.0 reproducible-builds drift (Go pin + SOURCE_DATE_EPOCH)
be3ecb6 v2.6.0: dark-agent self-bootstrapping via embedded resources + 3 tools

🔮 Follow-ups (NOT in v2.6.0; deferred to v2.6.1)

  • Distribution: include agent-bootstrap/*.md in npm wrapper
    pre-build step + MCPB bundle manifest.json resources array
  • Docs: docs/agent-bootstrap.md overview + decision tree
  • README: "Self-Bootstrapping" section
  • Publish-mcp-registry race condition fix (retry loop)
  • migrate.CurrentSchemaVersion() exported constant

Full Changelog: v2.5.2...v2.6.0

v2.5.2

Choose a tag to compare

@github-actions github-actions released this 28 Jul 19:05

Full Changelog: v2.5.0...v2.5.2

v2.5.0 - npm wrapper (cross-platform one-line install) + Official MCP Registry

Choose a tag to compare

@nicourrutia98 nicourrutia98 released this 28 Jul 17:46

dark-memory-mcp v2.5.0 — npm wrapper + Official MCP Registry

Date: 2026-07-28
Version: 2.5.0
Schema: v20 (unchanged)
Canonical tool count: 35 (unchanged)
Wire contract: unchanged (additive packaging layer only)
Commit: 7ef6112
Tag: v2.5.0 (local only, NOT pushed — operator setup required first)
Drift_judge: eval 730 verdict=aligned confidence=0.92


What this release does

v2.5.0 ships a packaging-layer release that adds a cross-platform
one-line install path for vibe-coders. The end-user change is
literally a single line in their MCP host config:

{
  "mcpServers": {
    "dark-memory": {
      "command": "npx",
      "args": ["-y", "@opita-code/dark-memory-mcp"]
    }
  }
}

npx downloads the wrapper + the binary for the user's OS + arch on
first invocation. All subsequent calls hit the npm cache. This
collapses the previous 5-step install (download .exe → verify SHA-256
→ wire absolute path → restart host) into 1 step.

The Go binary, wire protocol, schema v20, and all 35 canonical tools
are unchanged.


What's new in this release

  1. npm wrapper @opita-code/dark-memory-mcp — Microsoft-pattern
    cross-platform wrapper that detects OS+arch via process.platform + process.arch, loads the matching platform sub-package via
    optionalDependencies, spawns the Go binary with stdio inherited.
  2. 6 platform sub-packages:
    • @opita-code/dark-memory-mcp-darwin-x64 (macOS Intel)
    • @opita-code/dark-memory-mcp-darwin-arm64 (macOS Apple Silicon)
    • @opita-code/dark-memory-mcp-linux-x64 (Linux x86_64)
    • @opita-code/dark-memory-mcp-linux-arm64 (Linux ARM64)
    • @opita-code/dark-memory-mcp-win32-x64 (Windows x86_64)
    • @opita-code/dark-memory-mcp-win32-arm64 (Windows ARM64)
  3. server.json at repo root — Official MCP Registry manifest
    declaring io.github.opita-code/dark-memory-mcp namespace.
  4. .github/workflows/publish-npm.yml — matrix cross-compiles
    all 6 platforms via GOOS/GOARCH, copies binaries into
    sub-packages, publishes 7 npm packages in order with --provenance
    (SLSA build attestation).
  5. .github/workflows/publish-mcp-registry.yml — publishes
    server.json to registry.modelcontextprotocol.io using GitHub
    OIDC (no long-lived secrets required).
  6. docs/npm-install.md — copy-paste host config snippets
    (Claude Code, Claude Desktop, opencode, Cursor) + troubleshooting
    matrix (Windows cmd /c wrapper, missing optionalDependencies,
    ENOENT, version pinning, cache reset).
  7. tests/distribution/ — new test category with 12
    static-analysis tests:
    • TestV250_AllPackageJSONsParse — 7 package.json files parse + shape
    • TestV250_WrapperPackageHasOptionalDependencies — all 6 platforms pinned
    • TestV250_WrapperPackageHasMCPNameio.github.opita-code/dark-memory-mcp
    • TestV250_WrapperPackageHasBinEntrydark-memory-mcpindex.js
    • TestV250_PlatformPackagesHaveOSAndCPU — per-platform os/cpu constraints
    • TestV250_AllPackageVersionsMatch — all 7 packages + server.json = same version
    • TestV250_ServerJSONSchema — Official MCP Registry schema
    • TestV250_AllIndexJSValidSyntaxnode --check on all 7 index.js files
    • TestV250_PlatformDetectionMapConsistent — PLATFORM_MAP == optionalDependencies
    • TestV250_PublishNPMWorkflowStructure — workflow has NODE_AUTH_TOKEN, tag trigger
    • TestV250_PublishMCPRegistryWorkflowStructure — workflow uses github-oidc

Distribution channels active

Channel Status Coverage
GitHub Releases binary download still works (unchanged) all OSes
npm wrapper (npx -y @opita-code/dark-memory-mcp) ready, needs operator setup all 6 platforms
Official MCP Registry (io.github.opita-code/dark-memory-mcp) ready, auto-syncs to Glama/PulseMCP/mcp.so/Smithery indexed by 5+ directories on publish
Homebrew tap (macOS) deferred to v2.5.1 n/a
Scoop bucket (Windows) deferred to v2.5.1 n/a
DXT (Claude Desktop one-click) deferred to v2.5.2 n/a

Operator setup required BEFORE pushing the tag

The CI workflows will not auto-publish until the operator does two
things on the GitHub repo:

  1. Create the @opita-code org on npmjs.com.
    npm view @opita-code/dark-memory-mcp currently returns 404.
    Once the org exists, npm publish will succeed.

  2. Add the NODE_AUTH_TOKEN repo secret.
    Create an automation token at
    https://www.npmjs.com/settings//tokens with type
    "Automation". Add as a repo secret in Settings → Secrets.

For the Official MCP Registry publish: no token required (uses
GitHub OIDC, configured by permissions: id-token: write in the
workflow YAML).


Operator runbook: publish v2.5.0

# Step 1: code is in main (already pushed). Verify:
git log --oneline -1
# should show: 7ef6112 feat(dist): v2.5.0 - npm wrapper + Official MCP Registry publish

# Step 2: configure secrets (one-time):
#   a. Create @opita-code org at https://www.npmjs.com/org/create
#   b. Generate automation token at https://www.npmjs.com/settings/opita-code/tokens
#   c. Add NODE_AUTH_TOKEN to repo: Settings -> Secrets and variables -> Actions -> New repository secret

# Step 3: tag and push (CI does the rest)
git push origin v2.5.0

# CI will:
#   - Cross-compile 6 platform binaries
#   - Publish 7 npm packages to https://www.npmjs.com/@opita-code
#   - Publish server.json to https://registry.modelcontextprotocol.io
#   - Auto-sync to Glama, PulseMCP, mcp.so, Smithery, mcpservers.org
#
# After CI succeeds (verify with `npm view @opita-code/dark-memory-mcp versions`):
gh release create v2.5.0 \
  --title "v2.5.0 - npm wrapper (cross-platform one-line install) + Official MCP Registry" \
  --notes-file release-notes.md \
  bin/dark-mem-mcp.exe
# (operator manually attaches the Windows binary; other 5 platforms
#  are served exclusively via npm wrapper.)

Wire contract (unchanged)

Zero protocol changes. The Go binary is identical to v2.4.3. All
existing MCP clients connecting via the GitHub Releases download
path keep working unchanged.


Why v2.5.0 and not v2.4.4

The operator-visible change ("you can now npx -y @opita-code/dark-memory-mcp")
is meaningful enough to warrant a minor bump per SemVer. Existing
v2.4.3 users on the GitHub Releases download path keep working
unchanged.


Checksums (no new binaries in this commit; binaries built by CI)

The Go binaries for v2.5.0 are identical to v2.4.3 (same source, same
git tag, same ldflags pattern). v2.4.3 SHA-256 sums:

dark-mem-mcp.exe      6FF3A109492241B5D76313BCB91AE90E083A24F559220B0A3CE22C68F1AF5849  25619968 bytes
dark-mem-cli.exe      17893DD6CC483C549B513222E1CA8149FD00904F2B1C68C56B09CB174C8C37F3  20588544 bytes
dark-mem-inspect.exe  FAC9E7778DEE94C820BD482D5E9B9D7924975397DDB2BB5B9AC7AC62064F33DD  20133376 bytes

The npm wrapper builds 6 fresh binaries (one per platform) on each
tag push via cross-compilation. SHA-256 sums for the npm-distributed
binaries will be reported by the CI run after the first publish.


Drift_judge journey

Eval Verdict Conf Trigger
729 drift_detected 0.92 Initial: judge flagged external irreversible actions need operator approval context
730 aligned 0.92 Revised artifact with operator approval chain + namespace ownership verification + supply-chain security review

After eval 730 verdict=aligned: code was committed, tag created locally,
main pushed to remote.


Files in this release

.github/workflows/publish-mcp-registry.yml       NEW (85 lines)
.github/workflows/publish-npm.yml                NEW (151 lines)
CHANGELOG.md                                     MOD (+129 lines v2.5.0 entry)
README.md                                        MOD (+104 lines: Quickstart rewritten)
docs/npm-install.md                              NEW (252 lines)
npm/wrapper/index.js                             NEW (83 lines)
npm/wrapper/package.json                         NEW (49 lines)
npm/wrapper/README.md                            NEW (109 lines)
npm/platform-{darwin,linux,win32}-{x64,arm64}/   NEW (6 dirs × 3 files = 18 files)
  ├── index.js                                   (spawn Go binary)
  ├── package.json                               (os/cpu constraints)
  └── bin/                                       (placeholder; CI fills with binary)
server.json                                      NEW (47 lines, Official MCP Registry manifest)
tests/distribution/npm_wrapper_v2_5_0_test.go   NEW (594 lines, 12 tests)

22 files changed, 1969 insertions(+), 42 deletions(-).


Risks + future work (judge flagged, not blocking)

  1. Hash-comparison test between npm-distributed binary and
    GitHub Releases binary — verify cross-compile matches local-build
    byte-for-byte. (Future: TestV260_NPMBinaryMatchesReleaseBinary.)
  2. Fallback behavior if user's platform package is missing —
    npm optionalDependencies should not silently fail. (Future:
    TestV260_OptionalDependenciesFallback.)
  3. OIDC verification depends on GitHub org admin account security.
    Out of scope for the workflow itself; mitigated by 2FA on operator's
    GitHub account.

Links

v2.4.3 - wire-layer MCP audit + 3 contract-drift fixes

Choose a tag to compare

@nicourrutia98 nicourrutia98 released this 28 Jul 16:15

v2.4.3 — wire-layer MCP audit + 3 contract-drift fixes

Date: 2026-07-28
Schema: v20 (unchanged across v2.4.x; v2.4.3 is test cleanup only)
Canonical tool count: 35 (unchanged — zero production code changes)
Commit: 198b92b

What this release does

v2.4.3 is the wire-layer hygiene audit the operator-approved roadmap
originally scoped as "vibe_spec/vibe_publish MCP wrapper fix".

The audit found that the original Form B JSON re-parse bug was
already fixed in F36 (v1.2.1, 2026-07-16)
— verified by the F36
wire tests passing against the v2.4.x binary. v2.4.3 ships the
actual hygiene fixes the audit revealed.

Three wire-layer bugs fixed

Bug A — TestWire_F37F38F39F40_BootAgainstDirtyDB schema drift

The dirty-boot test seeded a constitutions table with the OLDER
schema (is_active column instead of enabled). Production
migration v2 standardised on enabled. The watchdog SQL queries
enabled, so booting against the dirty DB crashed with
SQL logic error: no such column: enabled.

Fix: updated the test's constitutions schema to match the current
production schema (label, source, file_path, parsed_json,
sha256, enabled, activated_at, UNIQUE constraint). The test
still validates F37/F38/F39/F40 boot resilience scenarios.

Bug B — TestWire_HealthPingShape canonical count contract drift

Test asserted registry.canonical_tools == 29, frozen at v2.0.0
contract. v2.1.0 added AGENT_MEMORY namespace (5 tools); v2.3.0
added agent_memory_recall. Current canonical is 35.

Fix: updated assertion to expect 35. The contract documentation
was already updated in v2.3.0 — this propagates the contract update
to the remaining test.

Bug C — TestWire_RuntimeToolEnumeration tools/list contract drift

Test asserted tools/list returns 29 (un-armed) or 32 (armed),
frozen at v2.0.0. Current is 35 (un-armed) or 38 (armed).

Fix: updated wantUnarmed = 35 and wantArmed = 38. File-header
contract doc updated.

Why update tests, not production code (Bug A)

The dirty DB scenario is SIMULATED by the test. Real users always
run migrations in order; the production schema has been enabled-
based since v2 in early 2026. Adding a defensive fallback path
(enabled OR is_active) would mask future schema drift rather
than expose it. Minimal blast radius: update the test, keep
production code clean.

CHANGELOG cleanup

Updated the v2.3.0 "Process note" (describing the pre-F36 Form B
workaround) to reflect that F36 fixed it in v1.2.1 and the
workaround is no longer needed. Documentation drift fix.

Tests (all wire tests pass)

TestWire_F33_VibePublishHappyPath                  PASS
TestWire_INV8_DefaultDSNRespectsIsolation          PASS
TestWire_F35_TypeMismatchSurfacesFieldPath         PASS
TestWire_F36_VibeSpecAcceptsTasksAsArray           PASS  (regression guard for F36)
TestWire_F36_VibeSpecAcceptsTasksAsStringifiedArray PASS  (regression guard for F36)
TestWire_F37F38F39F40_BootAgainstDirtyDB           PASS  (Bug A fix)
TestWire_F37_DuplicateColumnDuringBoot             PASS
TestWire_HealthPingShape                           PASS  (Bug B fix)
TestWire_HealthPingLatency                         PASS
TestWire_INFRA002_ParseTasksFieldSurfacesFormAndCause  PASS
TestWire_RuntimeToolEnumeration                    PASS  (Bug C fix)

TestBridge7_* (4 tests) flaky under load (transport timeout when
cold-booting stdio subprocess + full suite in flight). All pass in
isolation. Same flake as v2.4.0/1/2 — not related to v2.4.3.

Drift governance

dark_memory_judge(eval_type=drift_judge) returned verdict=aligned
confidence 0.95 (evaluation 423). Release approved.

What v2.4.3 does NOT do (deliberate scope)

  1. Does not change the watchdog SQL to be schema-tolerant.
    Production code is clean; the dirty DB is a test scenario.
  2. Does not refactor F36's parseTasksField. The F36 dual-form
    dispatch (Form A vs Form B) is well-tested and stable.
  3. Does not add new tools or schema migrations. Zero production
    code changes. Tool count remains 35. Schema v20 unchanged.

Upgrade notes

  • Wire contract unchanged. Tool count remains 35.
  • Zero schema migration.
  • Existing v2.4.2 callers see no behavioral change.

Checksums (SHA-256)

dark-mem-mcp.exe      6FF3A109492241B5D76313BCB91AE90E083A24F559220B0A3CE22C68F1AF5849  25619968 bytes
dark-mem-cli.exe      17893DD6CC483C549B513222E1CA8149FD00904F2B1C68C56B09CB174C8C37F3  20588544 bytes
dark-mem-inspect.exe  FAC9E7778DEE94C820BD482D5E9B9D7924975397DDB2BB5B9AC7AC62064F33DD  20133376 bytes

Verified by dark-mem-inspect --versiondark-mem-inspect 2.4.3.

Carrying forward from v2.4.x

  • 35 canonical tools (no new tool in v2.4.3)
  • Schema v20 unchanged across v2.4.x
  • v2.4.0 drift_judge enrichment unchanged
  • v2.4.1 agent_id plumbing unchanged
  • v2.4.2 brand/compliance enrichment unchanged

v2.4.2 - brand_match + compliance_check enrichment with agent_memory

Choose a tag to compare

@nicourrutia98 nicourrutia98 released this 28 Jul 15:32

v2.4.2 — brand_match + compliance_check enrichment with agent_memory

Date: 2026-07-28
Schema: v20 (unchanged from v2.4.1; v2.4.2 is additive integration)
Canonical tool count: 35 (unchanged — no new tools, no schema migration)
Commit: 36c9513

What this release fixes

v2.4.0 wired agent_memory into the vibe-loop (ContextRecap on
session_start, drift_judge enrichment on publish_vibe, PriorFindings
on research_topic). But the canonical LLM-as-judge path (Judge,
JudgeConsensus) — used by brand_match, compliance_check, pii_detect,
prompt_injection_scan, grounding_check — was still blind to prior
context. A brand voice LLM scored new copy without seeing the brand
canon. A compliance LLM scored EU marketing copy without seeing GDPR
Article 13. v2.4.2 closes the "judges are blind" debt for
brand_match + compliance_check.

Strategy: PINNED memories, not BM25

v2.4.0 drift_judge enrichment (in PublishVibe) uses BM25 search
against the artifact text. v2.4.2 brand_match + compliance_check
enrichment uses PINNED memories instead, because:

  • Brand decisions are operator-curated: the operator pinned them
    because they're the brand canon. Pinned = explicit operator
    intent, not text similarity.
  • Compliance decisions + findings are similar: operator pinned them
    because they're jurisdictional canon.
  • BM25 against the artifact text is fragile for these judges: a
    compliance decision like "GDPR Article 13 disclosure" rarely
    shares keywords with the artifact copy being reviewed. Pinned
    gives predictable, curated context.
  • drift_judge keeps BM25 (in PublishVibe) because drift detection
    benefits from SPEC-relevant context, not pinned canon.

What gets enriched (per eval_type)

eval_type Kinds injected Why
brand_match [decision] Brand canon = operator-pinned decisions
compliance_check [decision, finding] Compliance rules + prior flags
drift_judge (unchanged) Lives in PublishVibe (v2.4.0)
pii_detect (none) Pattern-matching, not RAG
prompt_injection_scan (none) Pattern-matching, not RAG
grounding_check (out-of-scope) Future v2.4.4 candidate

Wire contract (additive)

// dark_memory_judge (orchestrator.O5):
{
  "eval_type": "brand_match" | "compliance_check" | ...,
  "content": "...",
  "agent_id": "...",                // NEW v2.4.2 — same priority chain as v2.4.1
  "no_enrich": false,               // NEW v2.4.2 — opt-out escape hatch
  // ... rest unchanged
}

// dark_memory_consensus (orchestrator.O8):
{
  "eval_type": "...",
  "content": "...",
  "agent_id": "...",                // NEW v2.4.2 — forwarded to all N samples
  "no_enrich": false,               // NEW v2.4.2 — forwarded to all N samples
  "n": 3,
  // ... rest unchanged
}

AgentID priority chain (unchanged from v2.4.1)

  1. Caller-supplied AgentID on the Judge call.
  2. projects.default_agent_id (set at tenant provisioning).
  3. Empty string — no agent filter; v2.4.0 backward compat.

NoEnrich opt-out

Operators who want raw, no-enrichment behavior (e.g., sensitive
audits where the brand canon must not leak into the verdict) can
pass no_enrich: true on the Judge call. The LLM receives the
raw content unchanged. Default false = enrichment on.

Operator procedure for stale canon

When brand voice or compliance rules evolve, the operator's
canonical workflow is:

  1. Identify stale canon: agent_memory_list(kind=decision, pinned_only=true, scope=project).
  2. Save new canon first: agent_memory_save(kind=decision, pinned=true, tags=brand,voice,2026-q3).
  3. Unpin stale canon (don't delete): agent_memory_update(id=stale_id, pinned=false).
  4. Verify new canon is the only one surfaced.
  5. Re-run brand_match verdicts if needed (use no_enrich=true during transition).

Limitations: v2.4.2 does NOT provide automatic staleness detection
or canon-versioning. Operators manage canon lifecycle manually.

Tests (9 new defensive tests, all pass)

Orchestrator-level (in tests/orchestration/agent_memory_v2_4_2_test.go):

  • TestV242_BrandMatch_EnrichesWithBrandDecisions — kind=decision
    surfaces; kind=finding + kind=link filtered out (all pinned to
    isolate the kind filter).
  • TestV242_ComplianceCheck_EnrichesWithDecisionsAndFindings
    both decision + finding surface; note is filtered.
  • TestV242_BrandMatch_NoEnrich_RespectsOptOutno_enrich=true
    → LLM sees raw content unchanged.
  • TestV242_PIIDetect_NoEnrichment — pattern-matching eval_type
    stays blind.
  • TestV242_Consensus_PassesAgentIDToAllSamples — N=3 consensus:
    each sample sees same agent-scoped enrichment.
  • TestV242_Consensus_PassesNoEnrichToAllSamplesno_enrich=true
    forwarded to all N consensus samples.
  • TestV242_AgentID_PriorityChain_ResolvesInJudge — Judge resolves
    AgentID via v2.4.1 priority chain.
  • TestV242_DriftJudge_EnrichmentUnchangedInPublishVibe — regression
    guard: drift_judge enrichment still in PublishVibe, NOT moved to
    Judge in v2.4.2.

Store-level (in tests/dual_driver/agent_memory_v2_4_2_test.go):

  • TestV242_Store_SearchAgentMemory_FilterByKind_DefenseInDepth
    — verifies the Store's Kind filter actually filters.

Full test suite green.

Drift governance

drift_judge evaluation converged in 3 iterations:

  • Eval 420: drift_detected confidence 0.78 (5 concerns,
    including legitimate NoEnrich-on-consensus-path bug)
  • Eval 421: drift_detected confidence 0.72 (concerns
    addressed but operator message needed verbatim citation)
  • Eval 422: aligned confidence 0.82 (all 5 concerns
    resolved; release approved)

The drift_judge artifact (rev3) cites the verbatim operator message,
provides operational impact analysis for stale pinned canon,
includes an explicit INV-1 recoverability matrix, and documents the
operator procedure for handling stale canon.

What v2.4.2 does NOT do (deliberate scope)

  1. Does not touch drift_judge enrichment — it still lives in
    PublishVibe (auditable since v2.4.0). Operators using
    dark_memory_judge(eval_type=drift_judge) directly without
    PublishVibe get NO enrichment — they must go through
    PublishVibe for enriched prompts.
  2. Does not enrich pii_detect, prompt_injection_scan, or
    grounding_check.
    Pattern-matching judges don't benefit from
    RAG; grounding_check is out-of-scope for v2.4.2.
  3. The enriched prompt is NOT persisted in the audit trail —
    only the LLM response (SDDEvaluation.VerdictJSON) is.
    Operators needing prompt-level audit get it in v2.4.4+.
  4. Memory-RAG is best-effort. If agent_memory is broken, Judge
    runs with raw content (same fail-safe as v2.4.0).

Upgrade notes

  • Wire contract is additive only. Existing v2.4.1 callers see no
    behavioral change unless they explicitly opt in to
    brand_match/compliance_check enrichment (which is on by default).
  • Operators who want raw, no-enrichment behavior can pass
    no_enrich: true per call.
  • Operators must PIN important brand + compliance decisions for
    them to surface as enrichment (pinned = operator-curated canon).
  • v2.4.0 drift_judge enrichment in PublishVibe is unchanged.
  • Tool count remains 35 (additive integration, no new tools).

Checksums (SHA-256)

dark-mem-mcp.exe      6AC77E507CC448B53F76A66864768E6FE959FF8AE5DD9E6F07017ACDF408EC11  25619968 bytes
dark-mem-cli.exe      6905E52261D266F6774D5163E5BA81AF93BEA79F91049CAD59CB900DF494F4C4  20588544 bytes
dark-mem-inspect.exe  500F757672786973B1F0DDCE96919863AB69712612E95930CA447B3BAE2567A3  20133376 bytes

Verified by dark-mem-inspect --versiondark-mem-inspect 2.4.2.

Carrying forward from v2.4.1

  • 35 canonical tools (no new tool in v2.4.2)
  • Schema v20 unchanged (additive integration only)
  • All v2.4.1 INV-10 backward compat preserved
  • drift_judge enrichment path unchanged

v2.4.1 - agent_id plumbing end-to-end

Choose a tag to compare

@nicourrutia98 nicourrutia98 released this 28 Jul 15:03

v2.4.1 — agent_id plumbing end-to-end

Date: 2026-07-28
Schema: v20 (was v19 in v2.3.0/v2.4.0)
Canonical tool count: 35 (unchanged — additive integration, no new tools)
Commit: a706646

What this release fixes

v2.3.0 added the agent_id column to agent_memory (Mem0 agent_id
semantics: the LLM that owns each memory). v2.4.0 wired
agent_memory into the vibe-loop (ContextRecap on session_start,
drift_judge enrichment on publish_vibe, PriorFindings on
research_topic) but used project-wide scope. As a result, when
multiple LLMs shared a project, each LLM's recap and judge
enrichment surfaced the OTHER LLM's decisions and findings —
exactly the cross-agent leakage the agent_id column was designed
to prevent.

v2.4.1 closes the plumbing. Every VLP integration point now has
a consistent agent_id resolution chain and forwards the resolved
agent_id to the Store filter.

Resolution priority chain (canonical, applies to all VLP integration points)

  1. Caller-supplied AgentID on the request — session_start.AgentID or publish_vibe.AgentID.
  2. projects.default_agent_id — set at tenant provisioning via project_create(default_agent_id="...").
  3. Empty string — no agent filter; v2.4.0 backward compat.

Helper: resolveActiveAgentID(ctx, requested) in
internal/orchestration/agent_id.go. Best-effort: Store errors
swallowed, falls through to empty string. Never panic.

Migration v20

ALTER TABLE projects ADD COLUMN default_agent_id TEXT;

Idempotent (SQLite ADD COLUMN without DEFAULT is a no-op on
re-apply; Postgres uses ADD COLUMN IF NOT EXISTS). No index
needed — read once per session_start / publish_vibe.

What v2.4.1 does NOT do (honest trade-off framing)

The empty-string fallback (priority 3) preserves v2.4.0 backward
compatibility. Projects that have NOT set projects.default_agent_id
retain v2.4.0 behavior: their ContextRecap and drift_judge
enrichment show ALL LLMs' memories, not just the active agent's.
This is a deliberate trade-off — the alternative (making empty
agent_id an error) would be a breaking change for v2.4.0 callers.

Operators who want per-LLM isolation must opt in by either:

  • calling project_create(default_agent_id="your-llm-id") at tenant provisioning, OR
  • passing agent_id explicitly on every session_start / publish_vibe call.

Wire contract (additive)

  • dark_memory_project_create: gains optional default_agent_id input (max 128 chars); echoed on idempotent replay.
  • dark_memory_session_start: gains optional agent_id input + active_agent_id output. ContextRecap.PinnedMemories and OpenTodos are filtered by the resolved agent_id.
  • dark_memory_publish_vibe: gains optional agent_id input + active_agent_id output. drift_judge enrichment is filtered by the resolved agent_id.

Store-layer change (the structural fix)

Store.ListAgentMemory now treats AgentID as an ADDITIVE
filter
that composes with any scope (Project, Session,
Operator, Agent). In v2.3.0, AgentID was only applied when
scope=agent; v2.4.1 applies it whenever non-empty. When AgentID
is empty, the filter is not applied (v2.4.0 backward compat).

This is the structural fix that mitigates the cross-agent leakage
at the data plane. The orchestrator-level integration just plumbs
the resolved agent_id into the filter; the actual prevention
happens at the Store boundary.

Checksums (SHA-256)

dark-mem-mcp.exe      769089F791ADEDDC32E320D3EEC4B56B191632CCC99AE7802923AFE64F81879E  25611776 bytes
dark-mem-cli.exe      B84B7D881BE55BACCCD7D26FF78BDEAC794BDC8002D5320F8FA2745A807C92A9  20588544 bytes
dark-mem-inspect.exe  0F50F51017A6B2F4640F8234CFF1655280A47A579D3A6A94FABB314CA5190DDA  20133376 bytes

Verified by dark-mem-inspect --versiondark-mem-inspect 2.4.1.

Drift governance

dark_memory_judge(eval_type=drift_judge) returned verdict=aligned
confidence=0.96 (evaluation 419). Approved for canonical artifact
publication.

drift_judge evolution:

  • Eval 417: needs_human 0.74 (initial; silent-fallback concern)
  • Eval 418: drift_detected 0.86 (after 3 defensive tests but before Store-level test + honest framing)
  • Eval 419: aligned 0.96 (final — Store-level test + honest "mitigates the debt" framing + INV-10 justification for empty fallback)

Tests

8 new defensive tests across 2 test files:

Orchestrator-level (helper + VLP integration) in
tests/orchestration/agent_memory_v2_4_1_test.go (7 tests):

  • TestV241_ContextRecap_RespectsAgentID
  • TestV241_ContextRecap_NoAgentID_FallsBackToProjectWide
  • TestV241_DriftJudge_EnrichesByActiveAgentID
  • TestV241_DefaultAgentID_ResolvesOnSessionStart
  • TestV241_AgentID_SessionStart_CallerWinsOverProjectDefault
  • TestV241_AgentID_PublishVibe_CallerWinsOverProjectDefault
  • TestV241_AgentID_EmptyChain_NoPanic_Deterministic

Store-level (structural fix verification) in
tests/dual_driver/agent_memory_v2_4_1_test.go (1 test):

  • TestV241_Store_ListAgentMemory_AdditiveAgentIDFilter (3 assertions: project+agent_id filter, project+empty, agent+agent_id)

Full test suite green (verified pre + post all 8 tests).

Upgrade notes

  • Wire contract is additive only. Existing v2.4.0 callers see no behavioral change.
  • New active_agent_id field on session_start / publish_vibe outputs is best-effort and empty when no agent_id is configured.
  • All integrations inherit INV-10 (rows survive session close). Resolution chain is project-level + per-call; per-session isolation is a v2.4.x follow-up.
  • The Store-layer additive filter is the structural fix; the orchestrator-level integration just plumbs the resolved agent_id.

Carrying forward from v2.4.0

  • 35 canonical tools (no new tool in v2.4.1)
  • Two behavior-default flips from v2.3.0 still apply:
    • scope=current default is project (was session pre-v2.3.0)
    • bind_session default is false (was implicit true pre-v2.3.0)

v2.4.0 - memory RAG into the vibe-loop

Choose a tag to compare

@nicourrutia98 nicourrutia98 released this 28 Jul 14:16

v2.4.0 — memory RAG into the vibe-loop

Date: 2026-07-28
Schema: v19 (unchanged from v2.3.0)
Canonical tool count: 35 (unchanged — additive integration, no new tools)
Commit: 621e297

What this release fixes

The agent_memory data plane shipped with producers and one consumer (recall), but the vibe-loop itself (session_start, drift_judge, research_topic, judge, consensus) never consulted it. Operators landed on every session with a blank slate. v2.4.0 closes that data-plane orphan debt.

What's new

  • session_start now emits a context_recap field with pinned_memories (top 10) + open_todos (top 20).
  • vibe_publish's drift_judge path now enriches the artifact text with relevant prior decisions + findings from agent_memory before calling the LLM judge (invisible at the wire level — the artifact is what gets persisted).
  • research_topic now populates a prior_findings field with top-5 in-project findings relevant to the query.
  • 5 helper functions added to internal/orchestration/agent_memory.go: recallForVibe, listPinnedForVibe, listOpenTodosForVibe, formatHitsForContext, firstLine.

Drift governance

dark_memory_judge(eval_type=drift_judge) returned verdict=aligned confidence=0.95 (evaluation 416). Approved for canonical artifact publication.

Checksums (SHA-256)

dark-mem-mcp.exe      2864CD419748C04AC31A3E0AE05DB1A1FBE5F9DD577920D41FDED82202B3719A  25602048 bytes
dark-mem-cli.exe      FA71CADAA9C11620CD6205823E8FB286CCEE63A9F2EE61B5D706F7889D687964  20589056 bytes
dark-mem-inspect.exe  AF0BC91A172FF094BC40353E8FA0F9D7E9E8CDA3994B9012928AC751326C46C6  20132864 bytes

Verified by dark-mem-inspect --versiondark-mem-inspect 2.4.0.

Pre-flight governance

  • dark_memory_session_start + dark_memory_judge(eval_type=drift_judge) (verdict=aligned confidence=0.95)
  • go build ./... exit 0
  • go test ./... all green (4 new orch tests + 6 prior dual_driver tests + full suite)

Upgrade notes

  • Wire contract is additive only. Existing callers see no behavioral change.
  • New ContextRecap on session_start and PriorFindings on research_topic are best-effort: errors swallowed; broken agent_memory does NOT block VLP paths.
  • All integrations inherit INV-10 (rows survive session close). Recap is project-wide scope by default; per-operator scope is a v2.4.x follow-up.
  • The drift_judge enrichment is INVISIBLE in the persisted artifact; only the LLM prompt sees it. This is intentional — the artifact is what humans/agents downstream consume, the prompt is what the judge consumes.

v2.3.0 → v2.4.0 — what carries forward from v2.3.0

  • Schema v19 (no migration in v2.4.0)
  • 35 canonical tools (no new tool in v2.4.0)
  • Two behavior-default flips from v2.3.0 still apply:
    • scope=current default is project (was session pre-v2.3.0)
    • bind_session default is false (was implicit true pre-v2.3.0)