Skip to content

peer-floors: add a sibling-coherence check — a floor that moves generation without its siblings publishes an unresolvable manifest #445

Description

@drewstone

The defect

A peer floor that moves a generation is never a single edit. @tangle-network/agent-interface, agent-runtime, agent-knowledge, agent-eval, sandbox, sandbox-ui, and agent-profile-materialize each declare the interface generation they accept. Moving one of them without its siblings publishes a manifest that cannot resolve, and nothing in this repo catches it: pnpm install succeeds, tsc --noEmit is clean, the suite is green, and the break appears only in a consumer's npm install.

src/peer-floors/ already owns the adjacent gate — it audits an installed tree against the floors this package declares, and its own header documents why typecheck cannot see a floor violation. It does not check whether the floors in one manifest are coherent with each other.

Measured evidence, from this repo

Precedent that got it right — #432 (chore(deps): move onto the agent-interface 0.47 line, merged 2026-08-12T22:06:48Z) touched 25 files: package.json, both create-agent-app template manifests, the lockfile, and the docs the pins appear in.

#444 initially did not. Its first two commits moved the interface line in package.json alone. The value audit on head a30eafce came back red:

🔴 Value Audit — redundant-or-flawed

Right and necessary lockstep move (the old interface cap made the published set un-installable), but executed across 2 files where the repo's own doctrine and prior lockstep PR (#432, 25 files) require the pin to move in every place it appears — it leaves the create-agent-app templates below the new floor

Two more commits were needed to clear it — d32749fd chore(create-agent-app): move template pins to the interface 0.53 lockstep and c435f3fc chore(deps): complete the lockstep — sibling peer floors and brand 1.5.0 — after which the audit returned sound. Net cost of the miss: one red audit, two extra commits, and roughly 90 minutes of review round-trips (05:11:58Z red → 06:43:05Z sound).

Why it matters beyond this repo. The same class of miss, one level up, produced a live break the same morning. agent-interface@0.54.0 published 2026-08-16T04:30:11Z; agent-knowledge@8.0.2 moved its interface peer to >=0.54.0 <0.55.0 while agent-runtime@0.135.3 still declared >=0.53.0 <0.54.0. Disjoint ranges, so no interface version satisfies both:

$ npm install --dry-run @tangle-network/agent-runtime@latest @tangle-network/agent-knowledge@latest
npm error   peer @tangle-network/agent-interface@">=0.54.0 <0.55.0" from @tangle-network/agent-knowledge@8.0.2
npm error Conflicting peer dependency: @tangle-network/agent-interface@0.53.0
npm error   peer @tangle-network/agent-interface@">=0.53.0 <0.54.0" from @tangle-network/agent-runtime@0.135.3

A manifest gate that ran on agent-knowledge's release would have failed that commit before it published. See tangle-network/agent-sdk#190 for the release-order half of the same arc.

Proposal — extend src/peer-floors/, do not add a new module

Add a sibling-coherence check on the same subpath and the same agent-app-peer-check bin, beside check.ts and dependency-source.ts. It reads manifests from the registry, not an installed tree, so it answers a different question from the existing gate:

For every first-party peer this manifest declares, does the version at the bottom of that peer's floor itself accept the interface generation this manifest declares?

Concretely, given this repo's own peerDependencies:

  1. Read the declared interface range R — for example >=0.53.0 <0.54.0.
  2. For each other @tangle-network/* peer, take the floor version (the >= bound) and read that exact published version's own interface range R_sibling.
  3. Fail when R ∩ R_sibling = ∅.

That is the exact shape of both failures above:

  • chore(deps): adopt interface 0.53 lockstep with runtime 0.135.3 and sandbox 0.27.0 #444, first commit: interface floor moved to >=0.53.0, while the agent-runtime floor still pointed at 0.133.0, whose own interface peer was on the 0.47 line. Empty intersection → fail.
  • agent-knowledge@8.0.2: interface peer >=0.54.0 <0.55.0, while its agent-eval floor would have to be a release that accepts 0.54. Any floor below 0.145.16 → empty intersection → fail.

Two properties worth keeping:

  • Fail on unreadable, never pass. The existing module already models this with the absent-but-declared verdict — "reported as a failure rather than a pass this did not earn". A registry read that fails must produce the same, not a silent skip.
  • Cover the template manifests too. create-agent-app/template/_package.json and create-agent-app/template-chat/_package.json are what chore(deps): adopt interface 0.53 lockstep with runtime 0.135.3 and sandbox 0.27.0 #444's red audit named, and they hold the same pins with no peerDependencies of their own. The check should treat a template pin below this repo's own floor as a violation, which is the drift the existing tests/create-agent-app.test.ts gate covers by assertion and this would cover by rule.

The result: a commit that moves one floor a generation without its siblings fails in the authoring repo, instead of on a consumer's npm install hours later.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions