Skip to content

feat(release): publish an installable memd artifact and reconcile /v1/version with client revision pins #151

Open

Description

@waterbro-8
schemaVersion: requirement-record.v1
revision: R1
status: ready
priority: P0
productOwner: "@PeterGuy326"
technicalOwner: "@waterbro-8"
implementationOwner: "@waterbro-8"
humanReviewOwner: "@Bindy-lbb"
userOutcome: "An operator can start a mem server from a published artifact, and a pinned client passes its version/contract preflight without hand-editing build flags or an out-of-band admin grant."
requirements: [REQ-001, REQ-002, REQ-003, REQ-004]
acceptanceCriteria: [AC-001, AC-002, AC-003, AC-004]
parent: null
dependencies: []
supersedes: []
lastDecisionAt: "2026-09-01T07:20:00Z"

Problem

mem publishes no installable server artifact, and the version coordinate it exposes is not the coordinate clients pin against. Together these make "connect digital-employee to mem" impossible for anyone who is not building from source.

Baseline: origin/main = 10d4bf7a48fd5ab0ce6fc67caa407a717f81830e.

  • No memd artifact. .github/workflows/release.yml:75-141 builds exactly one target across six platforms: go build ./cmd/mem-mcp. server/cmd/memd, mem-migrate, mem-healthcheck and mem exist on disk but are never built or published by the release workflow. The only npm surface is @fullstack-ai-infra/mem-mcp@0.1.1 (npm/package.json:2-3), whose bin is mem-mcp — a MCP shell that connects to an already-running memd. So there is no supported way to install the server; today a server exists only if you build the Docker image.
  • Two incompatible version grammars. server/internal/api/api.go:53 declares var Version = "dev", overridden via -X ...api.Version=${VERSION} (server/Dockerfile:11-12), and docs/DEPLOYMENT.md:66 + :70 fill that ARG with a semver tag (export MEM_VERSION=0.1.1 → --build-arg VERSION="$MEM_VERSION"). The handler serves that value verbatim at /v1/version (api.go:211-213). Meanwhile digital-employee's adapter hard-requires the response to equal a 40-hex git revision — packages/core/src/mem-http-memory-adapter.ts:25-26 pins 4c714aa352f79f0080a24904668210d6c445ba10, and :450-457 throws contract_unsupported on any mismatch, before any capability check. Net effect: every documented deployment fails closed on every operation, and the release workflow cannot fix it even by accident, because it does not build the server binary at all.
  • Recall needs a grant nobody can mint from the client path. /v1/durable-context/recall requires a scope grant created by an admin (api.go:353-355). There is no first-run/bootstrap path that produces a workspace, a token and its grant as one unit; mem doctor (feat(cli): add mem doctor and first-run guidance that names the documented deploy/compose path #112) and the compose-first onboarding (docs(onboarding): make deploy/compose the primary onboarding path #109) point at the deploy directory but do not close this loop.

Requirements

  • REQ-001: the release workflow builds and publishes the server binaries — memd at minimum, plus the migration and healthcheck helpers the documented deployment already assumes — for darwin/arm64, darwin/amd64, linux/arm64, linux/amd64, as versioned release assets with checksums.
  • REQ-002: exactly one version coordinate is defined for client/server preflight and is written down. /v1/version (or /v1/capabilities) must expose the git revision and the semantic version and the contract version as distinct fields, so a client can pin a revision or accept a version range without inventing a third mechanism.
  • REQ-003: the value injected at build time satisfies REQ-002 for both build paths that exist — the release workflow and the Docker image. A binary produced by either path must be preflightable by a pinned client.
  • REQ-004: a documented, non-admin-juggling first-run path yields a reachable endpoint, a workspace, a token whose scopes cover both write and recall, and the corresponding grant; failure to satisfy any of these reports a named missing precondition rather than a generic connection error.

Acceptance criteria

  • AC-001: a clean checkout of a release tag produces the server assets listed in REQ-001; the workflow log and asset list are attached to that release, and go version -m on the asset shows the exact release commit.
  • AC-002: a running artifact built by the release path answers /v1/version with all three REQ-002 fields populated; a client pinning either the revision or the version range passes preflight against that same artifact. A test asserts both directions.
  • AC-003: docs/DEPLOYMENT.md and the release docs describe one version grammar, name the field that carries the git revision, and state what a client is allowed to pin. No step in the documented path requires hand-editing a build flag to become compatible.
  • AC-004: following only the REQ-004 path against a release artifact, a digital-employee adapter instance completes one write and one recall against that same artifact. Recorded as live evidence with the artifact version, not as a mocked test.

Non-goals

No embedded/single-file storage mode, no change to durable-context.v1 semantics, no hosted multi-tenant service, no Windows-specific work.

Open question blocking the desktop ask

org-workbench is being asked to ship an out-of-the-box installer with memory enabled. docs/DEPLOYMENT.md:18-21 offers two deployment profiles and neither is a single installable thing on macOS:

  • Single-node Compose runs Web, memd, Worker and a one-shot migration on one Linux host, with PostgreSQL, Redis and MinIO as local containers on named volumes. Workable, but it is a Linux host plus a compose stack, not something a .app can carry.
  • Multi-node Helm requires external PostgreSQL, Redis and S3-compatible storage, and the chart intentionally does not install them or their operators (docs/DEPLOYMENT.md:23-24), plus an explicit PostgreSQL URL / Redis URL / S3 configuration (:45).

So "out of the box" needs a product decision recorded as an ADR before REQ-001/REQ-004 can be called sufficient: either a supported single-machine topology the installer can reach and configure, or an installer that points at company-hosted memd. This issue does not assume an answer, and no amount of packaging work in mem alone makes an embedded-storage mode appear — that would be a storage-layer change, not a build change.

Activity

  1. waterbro-8 commented on Sep 3, 2026

    @waterbro-8
    CollaboratorAuthor

    Coverage read-back: this issue lost its only candidate today, and "redo in-repo" is not sufficient for it

    #157 feat(release): publish installable memd and reconcile /v1/version with client revision pins (head 2813d2ad) was this issue's only implementation. It was closed on 2026-09-03 under the decision that fork workflow permissions stay off and the work is redone in-repo, and no code was imported -- its single commit is authored and committed by sun-970 <3843544764@qq.com>, so cherry-picking it would put a personal external identity onto main, which is the thing the attribution rule excludes. Nothing was deleted; the fork branch is untouched and the head is still inspectable.

    This issue carries technicalOwner / implementationOwner: @waterbro-8, so unlike #110 and #111 the redo has a named owner. Two findings from reviewing #157 should travel with that work, because both are things a fresh in-repo attempt will trip over:

    1. REQ-002 cannot be satisfied from this repository alone

    Re-read on digital-employee HEAD 83e5acf today, packages/core/src/mem-http-memory-adapter.ts:

    export const MEM_HTTP_PINNED_REVISION =
      "4c714aa352f79f0080a24904668210d6c445ba10" as const          // :25-26
    
    const version = await requestJson(config, "/v1/version")        // :449-457
    if (!record(version) || !exactKeys(version, ["version"]) ||
        version.version !== MEM_HTTP_PINNED_REVISION) {
      throw contractError("The mem server revision is not the pinned revision.")
    }
    
    function exactKeys(value, required, allowed = required)         // :178-188

    allowed defaults to required, so a fourth field is itself a contract violation: exposing the git revision, the semantic version and the contract version as distinct fields -- what REQ-002 asks for -- makes every current client fail preflight with MEMORY_CONTRACT_UNSUPPORTED before it reaches the capabilities check. AC-002's "a test asserts both directions" therefore needs a matching change on the digital-employee side, and this org has no push access there, so it can only arrive as a fork PR with its own review queue. Worth stating before anyone budgets this as a mem-only task.

    The second half of the same check is the pin itself: version.version !== MEM_HTTP_PINNED_REVISION compares against a hardcoded commit that is nine days behind main, so even a correctly-shaped /v1/version is rejected until the client's pin moves. REQ-003's "a binary produced by either path must be preflightable by a pinned client" cannot be true while the pin is a literal in the consumer.

    2. Two build-shape facts, both measured rather than inferred

    • -buildvcs=true is a go build flag, not a linker flag. Putting it inside -ldflags hands it to the link step: flag provided but not defined: -buildvcs. AC-001's go version -m readback depends on VCS stamping actually happening, so the flag has to sit with go build -- release.yml:137's existing mem-mcp job already does it correctly (go build -buildvcs=true -trimpath -ldflags='-s -w').
    • The checksums asset name is part of the install contract. npm/install.js:35 looks up mem-mcp-checksums.txt under releases/download/v<version>/ (:615). A release change that replaces that name with a new one -- feat(release): publish installable memd and reconcile /v1/version with client revision pins #157 renamed it to mem-checksums.txt rather than adding a second manifest -- breaks npm installation on every platform, and nothing in the repository's guards catches it, because they grep -Fq the workflow's text rather than executing the assertion. Adding memd assets means adding to the list, and the existing manifest keeps its name.

    Status of this issue as of now

    Unassigned work with a named owner, zero implementation candidates, and one cross-repository prerequisite. No label, status, or body change made here by me; the dependencies: [] in the R1 block does not yet reflect the digital-employee constraint above, and that is the owner's call to record.

  2. sun-970 commented on Sep 8, 2026

    @sun-970
    Contributor

    Thanks for the detailed status write-up. A few suggestions to unblock this:

    On the cross-repo prerequisite (REQ-002 / digital-employee):

    1. Open a tracking issue in digital-employee (or link an existing one) so the dependency is visible and has its own queue. Even if this org can't push directly, a fork PR with a clear description referencing this issue gives the other repo's reviewers context.
    2. Decouple the pin from the contract shape change. The hardcoded MEM_HTTP_PINNED_REVISION and the /v1/version response schema are two separate concerns. The schema change (allowing additional fields) could land first with a backwards-compatible approach — e.g. keep the existing version field and add git_revision / contract_version alongside it, so old clients still pass preflight. Then bump the pin in a follow-up once the server side is live.
    3. Consider a feature-flag or negotiation path — if /v1/version returns extra fields but the client only checks version.version, the exactKeys check is the real blocker. A client-side change to relax exactKeys to a superset check would remove the hard dependency between the two repos' release cadences.

    On the build-shape issues:

    1. Add an integration-level guard that actually runs go version -m on the built binary and asserts VCS info is present, rather than only grepping the workflow text. This catches the -buildvcs placement mistake at CI time.
    2. For checksums, keep mem-mcp-checksums.txt as-is and add memd-checksums.txt as a separate manifest. A simple addition to the existing list in npm/install.js covers both without breaking the install contract.

    Happy to help with the digital-employee fork PR if that would move things forward.

  3. wadrzl commented on Sep 8, 2026

    @wadrzl

    Issue #151 Verification (2026-09-08)

    No open PR targets this issue. PR #157 closed without merge; no successor.

    Requirements: 0/4 met.

    • REQ-001 (publish memd release assets): release.yml builds only mem-mcp. Dockerfile builds all binaries but only as container layers.
    • REQ-002 (three-field /v1/version): api.go:211-212 returns single field {"version": "dev"}.
    • REQ-003 (build-time injection for both paths): Dockerfile injects semver via -X (one field). Release workflow has no -X at all.
    • REQ-004 (first-run bootstrap): no path exists in code or docs.

    Acceptance criteria: 0/4 met. AC-001/002/003/004 all fail for the reasons above.

    Blockers from PR #157 review still apply:

    1. digital-employee exactKeys check rejects any new /v1/version field. Cross-repo fix needed, no push access.
    2. npm/install.js:35 expects mem-mcp-checksums.txt — must not rename.
    3. -buildvcs=true belongs with go build, not -ldflags.

    Adjacent: PR #168 bumps versions 0.1.1 to 0.1.2, does not address any REQ.

  4. PeterGuy326 commented on Sep 10, 2026

    @PeterGuy326
    Collaborator

    Initial triage — labels applied

    Per docs/maintainers/triage.md §"Label taxonomy" ("During initial triage, a mem maintainer applies the type, status, area, evidence, and—when applicable—severity labels"), this issue carried no labels at all. Applied:

    type:feature (new user-visible capability: an installable server artifact) · area:server (/v1/version contract, build-time injection) · area:infra (.github/workflows/release.yml asset matrix) · evidence:e2-source (every claim below is source-level; nothing was executed) · status:needs-triage.

    Not applied: severity: — the taxonomy reserves severity for bugs and incidents. Not raised: evidence: stays at E2.

    The two-area set is justified by the taxonomy's "Multiple area labels are acceptable only when work genuinely crosses components": REQ-001 lands in the release workflow, REQ-002/REQ-003 in server/internal/api.

    Every factual claim re-verified against main at 55d09b203ba9 (2026-09-10T16:23:43Z) — all still true

    1. No memd artifact. .github/workflows/release.yml still builds exactly one target: go build … -o "${output}" ./cmd/mem-mcp (line 138), across the six-entry matrix at :82-101 (mem-mcp-{linux,darwin}-{amd64,arm64}, mem-mcp-windows-{amd64,arm64}.exe). The live GitHub Release v0.1.1 confirms it: its asset list is exactly those six binaries plus mem-mcp-checksums.txt. memd appears in only one workflow, .github/workflows/ci.yml:141 (go build -trimpath -o "${output}/memd" ./cmd/memd) — a CI compile check that publishes nothing. server/cmd/memd, mem-migrate, mem-healthcheck and mem remain unbuilt and unpublished by any release path.
    2. Two incompatible version grammars. server/internal/api/api.go:54 is still var Version = "dev", and the route still serves that one value verbatim: r.Get("/v1/version", … writeJSON(w, http.StatusOK, map[string]any{"version": Version})) (around api.go:211-213). It returns one field, not the three REQ-002 asks for (git revision, semantic version, contract version).
    3. The consumer pin is live and unchanged. bytefolk/digital-employee packages/core/src/mem-http-memory-adapter.ts:26 still hard-codes "4c714aa352f79f0080a24904668210d6c445ba10" as const, and :456 still throws contractError("The mem server revision is not the pinned revision."). 4c714aa352f7 is mem's own fix(ci): restore reproducible repository gates (PR fix(ci): restore reproducible repository gates #93, merged 2026-08-23) — a commit that predates every release tag. So the fail-closed-on-every-operation claim holds today, and no mem release could satisfy it as things stand, because the release path never builds the server.

    The one prior implementation attempt, #157, was closed unmerged (never merged, no SHA). Nothing in the xref timeline delivered any part of this.

    Readiness-gate note (not a status:ready recommendation)

    Bullets 1–5, 8 and 9 pass: not a duplicate (the audit found no other issue covering the memd artifact or the version-coordinate split); no sensitive detail exposed; labels now accurate; clear problem; AC-001/AC-002/AC-003 are objective and testable; non-goals recorded; dependencies and risks identified; validation approach concrete (go version -m on the asset, a two-directional preflight test, one live digital-employee write + recall).

    Two bullets do not pass yet, which is why this is needs-triage and not ready:

    • Bullet 7 (scope and explicit non-goals recorded) — the record's own final section, "Open question blocking the desktop ask", states that "org-workbench is being asked to ship an out-of-the-box installer … needs a product decision recorded as an ADR before REQ-001/REQ-004 can be called sufficient", and explicitly "does not assume an answer". That is a named undecided dependency.
    • Bullet 10 (small enough for one reviewable PR) — as written this is a release-workflow change, an API contract change, two build-path changes, a docs rewrite, and a cross-repository live-evidence run. feat(release): publish installable memd and reconcile /v1/version with client revision pins #157 attempted it in one PR and did not land. REQ-001+REQ-003 (build and publish memd) is cleanly separable from REQ-002+REQ-004 (version grammar and first-run grant path); splitting would let the artifact half proceed without the ADR.

    Recommendation: either split into two linked issues as above, or resolve the ADR question first. Note also that REQ-002 is a breaking contract change for any client that currently reads {"version": …} — worth labelling breaking-change when it is scoped.

    Sequencing against the release train

    This issue is not on the #122 → #153 → #163 → #168/#193 path, but it collides with it: REQ-001 adds assets to the same release.yml matrix that #168/#193 are synchronizing to 0.1.2, and docs/maintainers/releasing.md:100 currently asserts the Release exposes "the six binaries plus mem-mcp-checksums.txt". Publishing memd changes that sentence and the checksum manifest's scope. Whoever lands one should rebase the other.

  5. added
    type:featureA new user-facing capability
    area:serverGo API, CLI, MCP, storage, or server runtime
    area:infraCI, release, packaging, and repository infrastructure
    evidence:e2-sourceSource or log evidence identifies the likely cause
    on Sep 10, 2026
  6. waterbro-8 commented on Sep 17, 2026

    @waterbro-8
    CollaboratorAuthor

    Re-landed #157 onto current main as organization branch feat/151-memd-release-artifacts.

    Conflicts with post-#199 checksum output protections were resolved: two manifests (mem-mcp-checksums.txt + mem-checksums.txt), still refuse existing/late output symlinks, still avoid wc -l / process-substitution find. Local: test_release_checksum_output_safety.sh, test_release_guards.sh, and test_release_helpers_compat.sh all PASS.

    If the PR is not yet visible, git push to github.com from this environment timed out; the branch exists locally and will be pushed as #216 when git.github.com is reachable. Human review remains @Bindy-lbb. No tag or release.

  7. waterbro-8 commented on Sep 17, 2026

    @waterbro-8
    CollaboratorAuthor

    Follow-up: organization PR is up at #216 (feat/151-memd-release-artifacts).

    Local checksum/guard/compat scripts passed. Go 1.25 tests and an actual tag cut are NOT VERIFIED. Review owner remains @Bindy-lbb.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:infraCI, release, packaging, and repository infrastructurearea:serverGo API, CLI, MCP, storage, or server runtimeevidence:e2-sourceSource or log evidence identifies the likely causestatus:needs-triageAwaiting maintainer classificationtype:featureA new user-facing capability

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions