From 033a5d384c99e5bb5e7bb192cd01cf4521ad99ca Mon Sep 17 00:00:00 2001 From: jochen Date: Tue, 15 Sep 2026 13:44:02 +0200 Subject: [PATCH] =?UTF-8?q?Issue=20053=20=E2=80=94=20the=20SDK=20is=20pinn?= =?UTF-8?q?ed=20twice=20and=20the=20two=20disagree,=20and=20ADR=200074=20a?= =?UTF-8?q?ccepted?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The tool runtime's manifest names the SDK as a git dependency at a pinned commit; its lock file names a sibling directory that exists on one workstation. It builds only because the recipe runs npm install, which tolerates a lock disagreeing with its manifest and re-resolves from the manifest — the one command that hides this. It matters because a lock exists to make a build reproducible and this one describes one machine, and because it is the first thing a fresh mesh builds: the toolchain carries the SDK and everything with code of its own compiles inside it, so a dependency resolved differently on the build machine than on a workstation is a difference in every module the mesh will ever build. And it is about to be copied. Each language's toolchain will carry that language's SDK the same way, so the shape is worth settling before there are four of them. Claude-Session: https://claude.ai/code/session_01D6qtiYU3P9jk3pnAXyAFyx --- ...074-the-wire-is-specified-not-the-types.md | 2 +- 02-DECISIONS/README.md | 2 +- .../00-report.md | 60 +++++++++++++++++++ 3 files changed, 62 insertions(+), 2 deletions(-) create mode 100644 04-ISSUES/053-the-sdk-is-pinned-twice-and-the-two-disagree/00-report.md diff --git a/02-DECISIONS/0074-the-wire-is-specified-not-the-types.md b/02-DECISIONS/0074-the-wire-is-specified-not-the-types.md index e7f454f..8517c20 100644 --- a/02-DECISIONS/0074-the-wire-is-specified-not-the-types.md +++ b/02-DECISIONS/0074-the-wire-is-specified-not-the-types.md @@ -1,6 +1,6 @@ --- topic: the tiers -status: proposed +status: accepted date: 2026-09-15 deciders: jochen reconstructed: false diff --git a/02-DECISIONS/README.md b/02-DECISIONS/README.md index d4e8558..362477f 100644 --- a/02-DECISIONS/README.md +++ b/02-DECISIONS/README.md @@ -106,7 +106,7 @@ python3 00-META/checks/index.py fail if stale - **0071** — [Genesis clones from a mesh, and checks what it got](0071-where-genesis-gets-its-source.md) - **0072** — [Two graphs, and a build chain that orders itself](0072-two-graphs-and-the-build-chain.md) - **0073** — [The installer carries a builder, and the registry stays where it is](0073-the-installer-carries-a-builder.md) -- **0074** — [The mesh defines a module protocol; an SDK is an implementation of it](0074-the-wire-is-specified-not-the-types.md) *(proposed)* +- **0074** — [The mesh defines a module protocol; an SDK is an implementation of it](0074-the-wire-is-specified-not-the-types.md) ### What runs on them, and how it gets there diff --git a/04-ISSUES/053-the-sdk-is-pinned-twice-and-the-two-disagree/00-report.md b/04-ISSUES/053-the-sdk-is-pinned-twice-and-the-two-disagree/00-report.md new file mode 100644 index 0000000..a38d49d --- /dev/null +++ b/04-ISSUES/053-the-sdk-is-pinned-twice-and-the-two-disagree/00-report.md @@ -0,0 +1,60 @@ +--- +status: open +opened: 2026-09-15 +located-in: [] +fixed-by: +amended-design: +--- + +# 053 — The SDK is pinned twice, and the two disagree + +## Symptom + +The module that carries the tool runtime names the SDK two ways, and they are not the same thing: + +``` +package.json @novox/mesh-sdk -> git+https:///mesh-sdk.git# +package-lock.json @novox/mesh-sdk -> ../mesh-sdk +``` + +The manifest names a commit in a repository any machine can reach. The lock names a **sibling +directory**, which exists on the workstation the lock was generated on and nowhere else. + +It builds anyway, because the recipe runs `npm install` — which tolerates a lock that disagrees +with its manifest and re-resolves from the manifest. It is the one command that hides this. + +## Why this matters + +**A lock file exists to make a build reproducible, and this one describes one machine.** `npm ci` — +the command for exactly the case a lock is for — fails here, or worse, succeeds against whatever +happens to be at that path. + +**It is the first thing a fresh mesh builds.** The toolchain image carries the SDK, and everything +with code of its own is compiled inside it. A dependency resolved differently on the build machine +than on a workstation is a difference in every module the mesh will ever build, arriving as a +compile error or a runtime mismatch far from here. + +**And it is about to be copied.** Each language's toolchain will carry that language's SDK the same +way ([ADR 0074](../../02-DECISIONS/0074-the-wire-is-specified-not-the-types.md)). Whatever this +repository does, the Rust and Python ones will do, so the shape is worth getting right before there +are four of them. + +## Open questions + +- **Is a git dependency at a pinned commit the intended mechanism?** It works, needs no package + registry, and reuses the forge a mesh already depends on to exist at all + ([ADR 0071](../../02-DECISIONS/0071-where-genesis-gets-its-source.md)). If so, the lock should say + so and the sibling path should never have been committed. +- **Or should the SDK be a published package?** The catalogue holds a private registry module, and a + published package is how the rest of the world does this — at the cost of a mesh needing that + registry up before it can build anything, which is a bootstrap problem where there is currently + none. +- **What generates the lock, and on what?** A lock produced on a workstation with sibling checkouts + will keep saying this. A lock produced the way the image builds would not. + +## How this would be checked + +| Rule | Checked by | +|---|---| +| A build does not depend on the machine it runs on | The toolchain image builds with `npm ci` rather than `npm install`, which refuses a lock that disagrees with its manifest. | +| The SDK a module compiles against is the one named | The commit baked into the toolchain image is compared with the one the manifest pins. |