chore(release): 0.137.0 — declare the agent-interface peer as a caret range - #881
Conversation
… range The peer held >=0.53.0 <0.54.0, a window one generation wide. agent-knowledge and sandbox-ui had moved past it, so the two halves of the fleet held disjoint ranges and an app could not install this package beside them. Interface 1.0.0 publishes the surface of 0.56.0 unchanged and states a compatibility promise, so a caret range reads it and a later additive minor needs no release here. The catalog moves with the peer, because a caret on the peer alone does not dedupe: sandbox 0.27.0 and agent-core 0.9.0 each pinned an interface exactly and dragged a second copy into the tree. A clean install now resolves one agent-interface 1.0.0 and one agent-core 0.9.4. Minor, not patch: the interface range narrows, so a consumer still holding an interface below 1.0.0 stays on 0.136.0. The testing fixtures embed runtimeVersion and are regenerated.
tangletools
left a comment
There was a problem hiding this comment.
✅ Auto-approved drewstone PR — 237279b8
This PR was opened by the trusted drewstone account.
The full PR reviewer audit still runs separately and will publish findings if it detects issues.
This approval is provisional. It rests on the audit running. If the audit cannot run — for example the CLI bridge rejects it — this approval is dismissed rather than left standing, so an unrun check never reads as a passing one.
tangletools · auto-approval · reason: drewstone_author · 2026-08-16T14:22:44Z
tangletools
left a comment
There was a problem hiding this comment.
✅ Auto-approved drewstone PR — 237279b8
This PR was opened by the trusted drewstone account.
The full PR reviewer audit still runs separately and will publish findings if it detects issues.
This approval is provisional. It rests on the audit running. If the audit cannot run — for example the CLI bridge rejects it — this approval is dismissed rather than left standing, so an unrun check never reads as a passing one.
tangletools · auto-approval · reason: drewstone_author · 2026-08-16T14:22:55Z
agent-bench resolves the first-party cohort through the workspace catalog, so the catalog move changes its published manifest. publish.yml skips a version the registry already holds, so without this bump the change would never reach a consumer.
…caret range The sandbox peer floor tracks its catalog version, so it moves to 0.27.1. Three guards refused the caret range this release adopts: verify-official-optimizers built a one-generation window from the development pin, verify-packed-cohort required agent-eval to declare agent-interface by exact equality, and check-docs-freshness matched only a >= floor in the doc. The shared helper now derives the range shape from the dependency's own versioning: a package at 1.0.0 or above states that a minor is additive, so it earns a caret; a pre-1.0 package still stops at the next minor. Cohort membership is checked by admission, and the one-physical-copy assertion each guard protects is unchanged.
Guards that encoded the shape being retired —
|
| check | demanded | why it failed |
|---|---|---|
verify-official-optimizers.mjs |
>=1.0.0 <1.1.0 |
built the window from the development pin |
verify-packed-cohort.mjs |
agent-eval's interface dep to equal the packed version | agent-eval now declares ^1.0.0, not 1.0.0 |
check-docs-freshness.mjs |
a >=x.y.z floor in the doc |
matched no caret, so the pin read as "never asserted" |
Rather than special-case agent-interface, the shared helper now derives the shape from the dependency's own versioning:
// From 1.0.0 a package states that a minor is additive and only a major removes
// or narrows, so a caret range holds one installed copy across later minors. A
// pre-1.0 package states no such promise, so its range still stops at the next minor.
expectedPeerRange(version)That rule is why agent-eval and sandbox keep their windows while agent-interface gets a caret — all three from one function, no per-package branch. Verified:
| version | expected peer range |
|---|---|
1.0.0 |
^1.0.0 |
1.4.2 |
^1.4.2 |
8.0.5 |
^8.0.5 |
0.145.21 |
>=0.145.21 <0.146.0 |
0.27.1 |
>=0.27.1 <0.28.0 |
Cohort membership is checked by admission (caretAdmits), and the one-physical-copy assertion each guard exists for is unchanged. ^0.9.0 is deliberately refused by caretAdmits — a pre-1.0 caret carries no promise.
The sandbox peer floor moves to >=0.27.1 <0.28.0 because the floor tracks the catalog version.
One pre-existing flake, not a regression
tests/candidate-execution-claim.test.ts > linearizes expired recovery across independent processes fails intermittently. It is not caused by this change — this branch touches no file under src/candidate-execution/.
Measured on the unmodified merge base (ecda1bdf, a separate clean worktree):
main, isolated runs: 0 0 0 0 0 0 1 0 0 0 0 → 1/11 failed
Same rate on this branch. It is a race between independent processes over a temp claim file, and this machine is at 99% disk, which is the kind of pressure that surfaces it.
Full run on this head
pnpm typecheck exit 0
pnpm run check:version-bump exit 0 root 0.136.0 -> 0.137.0, bench 0.8.11 -> 0.8.12
pnpm run verify:package exit 0
pnpm run verify:official-optimizers exit 0
pnpm run docs:check exit 0
pnpm test 2733 passed | 6 skipped (217 files)
tangletools
left a comment
There was a problem hiding this comment.
✅ Auto-approved drewstone PR — 8a1dadd0
This PR was opened by the trusted drewstone account.
The full PR reviewer audit still runs separately and will publish findings if it detects issues.
This approval is provisional. It rests on the audit running. If the audit cannot run — for example the CLI bridge rejects it — this approval is dismissed rather than left standing, so an unrun check never reads as a passing one.
tangletools · auto-approval · reason: drewstone_author · 2026-08-16T14:41:33Z
The packed-cohort check builds Interface, Eval and Knowledge from pinned sibling revisions and verifies the four archives resolve together. Those revisions still named the 0.53 generation, so the check packed agent-knowledge 8.0.1 against a catalog that now names 8.0.5. Each ref moves to the commit that published the version this release declares: agent-interface 1.0.0, agent-eval 0.145.21, agent-knowledge 8.0.5.
tangletools
left a comment
There was a problem hiding this comment.
✅ Auto-approved drewstone PR — ba59547a
This PR was opened by the trusted drewstone account.
The full PR reviewer audit still runs separately and will publish findings if it detects issues.
This approval is provisional. It rests on the audit running. If the audit cannot run — for example the CLI bridge rejects it — this approval is dismissed rather than left standing, so an unrun check never reads as a passing one.
tangletools · auto-approval · reason: drewstone_author · 2026-08-16T14:56:47Z
tangletools
left a comment
There was a problem hiding this comment.
✅ Auto-approved drewstone PR — ba59547a
This PR was opened by the trusted drewstone account.
The full PR reviewer audit still runs separately and will publish findings if it detects issues.
This approval is provisional. It rests on the audit running. If the audit cannot run — for example the CLI bridge rejects it — this approval is dismissed rather than left standing, so an unrun check never reads as a passing one.
tangletools · auto-approval · reason: drewstone_author · 2026-08-16T15:08:09Z
tangletools
left a comment
There was a problem hiding this comment.
🟡 Value Audit — sound-with-nits
| Verdict | sound-with-nits |
| Coverage | 2 of 2 lenses (value, usefulness) |
| Concerns | 1 (1 weak-concern) |
| Heuristic | 0.0s |
| Duplication | 0.0s |
| Interrogation | 350.2s (2 bridge agents) |
| Total | 350.2s |
💰 Value — sound-with-nits
A release that re-declares the agent-interface peer as ^1.0.0 and moves the whole first-party catalog to the 1.0.0 generation, ending a real disjoint-peer-range install breakage — verified against the registry and the resolved lockfile; the guard changes extend the existing shared helper in the file
- What it does: Release 0.137.0 (4 commits): (1) package.json:172-176 re-declares peer '@tangle-network/agent-interface' from the one-generation window '>=0.53.0 <0.54.0' to '^1.0.0', bumps the agent-eval peer floor to 0.145.21 and sandbox floor to 0.27.1; (2) pnpm-workspace.yaml:21-28 moves six first-party catalog pins (interface 0.53.0→1.0.0, core 0.9.0→0.9.4, eval 0.145.15→0.145.21, knowledge 8.0.1→8.0.5, prof
- Goals it achieves: Ends a real install breakage: the published agent-knowledge@8.0.5 peer-declares '@tangle-network/agent-interface': '^1.0.0' (verified via npm view), which is disjoint from the old runtime peer '>=0.53.0 <0.54.0', so an app could not install agent-runtime beside the current knowledge/sandbox-ui half of the fleet. After the change, pnpm-lock.yaml resolves exactly one physical copy of every first-par
- Assessment: Good on its merits and built in the grain of the codebase. The semver policy in expectedPeerRange matches npm's real caret semantics (caret on 0.x is already >=0.x <0.x+1.0, so the branch is a display choice, not a semantic fork). The guard loosening follows the direction already written into assertSharedContractPeer's own comment (verify-packed-cohort.mjs:626-629: 'Requiring every owner's develop
- Better / existing approach: none — this is the right approach. Searched for an existing semver utility to reuse: 'semver' appears nowhere in scripts/ or package.json (the scripts are deliberately zero-dependency node builtins — verify-packed-cohort.mjs imports only node:* plus the local lib), so importing the semver package would fight that grain for a 9-line check. The alternative of 'always caret' would be semantically ide
- Model: opencode/zai-coding-plan/glm-5.2
- Bridge attempts: 2
- Bridge warning: opencode/kimi-for-coding/k2p7: opencode: opencode error
🎯 Usefulness — sound
A coherent release that fixes a real installability break (disjoint agent-interface peer ranges across the fleet) by moving the peer to ^1.0.0, moving the catalog in lockstep, and teaching every existing guard the caret shape — all wired into CI and publish.
- Integration: Fully reachable. The peer declaration itself is the consumer-facing surface (every app installing @tangle-network/agent-runtime beside agent-knowledge/sandbox-ui hits it). Every touched guard runs in CI or publish: verify-packed-cohort.mjs at ci.yml:108 and publish.yml:160 (with cohort source refs moved to the 1.0.0-generation commits in ba59547), verify:official-optimizers at ci.yml:162 and publi
- Fit with existing patterns: Follows the codebase's established grain rather than inventing a new mechanism: the repo's pattern is guarded peer floors with mechanical verification, and this extends each guard to a second range shape keyed off the dependency's own major (>=1.0.0 earns a caret, pre-1.0 keeps the one-minor window — scripts/lib/packed-package-test.mjs:51-55). assertExactDependency switches from equality to admiss
- Real-world viability: The design does not trust its own regex logic where it matters: both packed-verification scripts perform a real registry-resolution install with strict peer checks after the fast admission checks, so a mis-declared range fails at install, not at string comparison. caretAdmits (packed-package-test.mjs:58-66) correctly requires major match and major>=1, and its admission arithmetic is right for rele
- Model: opencode/zai-coding-plan/glm-5.2
- Bridge attempts: 1
💰 Value Audit
🟡 caretAdmits hand-rolls npm caret semantics and is prerelease-permissive [maintenance] ``
scripts/lib/packed-package-test.mjs:58-66 parses 'x.y.z' with a prefix regex and compares minor*1e6+patch, so a prerelease like '1.1.0-beta' is admitted where a real '^1.0.0' range would reject it, and a prerelease floor would also parse as its release tuple. Harmless today because the packed cohort pins concrete published releases, but if prereleases ever enter the cohort the hand-rolled matcher silently diverges from npm's resolution — the very drift these guards exist to catch. Worth a one-li
What this audit checks
It judges the change on its merits — not whether it was tasked out in an issue. Unticketed, fast-moving work is fine; the question is whether the change is good and whether a better or existing approach should be used instead.
| Pass | What it asks |
|---|---|
| Heuristic | Vague title? Whitespace-only or cruft-bearing diff? (content signals only) |
| Duplication | Do added function/class names already exist elsewhere in the repo? |
| Value Audit | What does it do? What goal does it achieve? Is it good? Better architecture or already-exists? |
| Usefulness Audit | Does it integrate and fit? Will it hold up in real use and actually get used? |
Findings are concerns, not blocks — the human reviewer decides what to do with them.
tangletools
left a comment
There was a problem hiding this comment.
🟡 Value Audit — sound-with-nits
| Verdict | sound-with-nits |
| Coverage | 2 of 2 lenses (value, usefulness) |
| Concerns | 2 (1 medium-concern, 1 weak-concern) |
| Heuristic | 0.0s |
| Duplication | 0.0s |
| Interrogation | 252.5s (2 bridge agents) |
| Total | 252.5s |
💰 Value — sound
Declares the agent-interface peer as ^1.0.0, moves the catalog in lockstep to end a two-copies-of-interface install split, and teaches the three verification guards the caret shape — coherent, verified in the lockfile, and in the grain of the repo's guard scripts; ship.
- What it does: Release 0.137.0 with four coordinated parts. (1) package.json:173 peer for @tangle-network/agent-interface moves from the one-generation window >=0.53.0 <0.54.0 to ^1.0.0; agent-eval and sandbox floors move to 0.145.21 / 0.27.1. (2) pnpm-workspace.yaml catalog moves with it: interface 0.53.0→1.0.0, agent-core 0.9.0→0.9.4, agent-eval 0.145.15→0.145.21, agent-knowledge 8.0.1→8.0.5, agent-profile-mat
- Goals it achieves: Three goals, all read from the change. First, fix an install-blocking split: the fleet's two halves held disjoint interface ranges, and the lockfile had two physical copies of agent-interface (0.53.0 dragged in by sandbox 0.27.0 and agent-core 0.9.0 exact pins); after the change pnpm-lock.yaml resolves exactly one @tangle-network/agent-interface@1.0.0 tree-wide (verified: only 1.0.0 entries remain
- Assessment: Good on its merits. The core insight is correct and stated in the commit: a caret on the peer alone does not dedupe — the catalog must move too, because siblings pin the interface exactly. The dedupe is proven in the lockfile, not just asserted. The guard update is the strongest part: expectedPeerRange derives the range shape from a principled rule (a 1.0.0 package promises additive minors; pre-1.
- Better / existing approach: none — this is the right approach. Searched for duplication and alternatives: (a) no semver library exists anywhere in the repo (searched package.json, bench/package.json, pnpm-workspace.yaml, and imports across scripts/ and src/ — no 'semver' dependency, no satisfies/validRange usage in scripts), and packed-package-test.mjs already builds ranges by regex (currentMinorPeerRange at :37), so hand-ro
- Model: opencode/zai-coding-plan/glm-5.2
- Bridge attempts: 2
- Bridge warning: opencode/kimi-for-coding/k2p7: opencode: opencode error
🎯 Usefulness — sound-with-nits
A coherent, in-grain fix for the fleet's disjoint one-generation peer windows (caret from a 1.0 semver promise), with all guards moved in lockstep — but publish.yml's pinned cohort refs were left at the pre-caret generation, so the v0.137.0 tag's own publish verification will fail until those three
- Integration: Fully wired and immediately exercised. expectedPeerRange/caretAdmits (scripts/lib/packed-package-test.mjs:51,58) are consumed by verify-official-optimizers.mjs:47-57, verify-packed-cohort.mjs:607, and assertPeerMatchesDevelopmentDependency (packed-package-test.mjs:70); all run in CI on this PR (ci.yml:50,108,162) and at publish time (publish.yml:160,166). The docs-freshness SUBSTRATE regex change
- Fit with existing patterns: Extends an established pattern rather than competing with one. verify-packed-cohort.mjs:626-630 already documents the 'a required peer deliberately admits later compatible patches; the strict packed install proves one physical copy' rationale for peers — this PR applies the same reasoning to 1.0+ dependency declarations (assertExactDependency comment, verify-packed-cohort.mjs:602-604) and to the d
- Real-world viability: Holds up beyond the happy path. The invariant moved from 'declared spec equals packed version' to 'declared spec admits packed version AND the strict install resolves one physical copy' — the cohort consumer still proves single-copy resolution via realpath dedup (verify-packed-cohort.mhs:419-435 in verify-packed-cohort.mjs:419-435) and byte-identical archive manifests. caretAdmits fails closed on
- Model: opencode/zai-coding-plan/glm-5.2
- Bridge attempts: 1
🎯 Usefulness Audit
🟠 publish.yml cohort pins left at interface@0.53.0 — the v0.137.0 publish run will fail its own cohort verification [integration] ``
Commit ba59547 pinned ci.yml's cohort checkouts to the caret-range cohort (interface@1.0.0 at ci.yml:84, eval@0.145.21 at ci.yml:91, knowledge@8.0.5 at ci.yml:98) but publish.yml:138,146,154 still pin interface@0.53.0 / eval@0.145.15 / knowledge@8.0.1 and run the same
node scripts/verify-packed-cohort.mjs(publish.yml:160). The tagged runtime@0.137.0 declares peer^1.0.0on interface (package.json:174); the consumer install enforcesstrict-peer-dependencies=true(verify-packed-cohort.mjs:3
🟡 caretAdmits over-admits prereleases relative to npm semver [robustness] ``
scripts/lib/packed-package-test.mjs:58-66 parses the leading
x.y.zof a prerelease version and admits it when the release tuple would be admitted, so caretAdmits('^1.0.0', '1.2.0-rc.1') is true while npm semver would reject it. Theoretical today because the cohort packs stable first-party releases only; if a prerelease sibling is ever pinned into publish.yml's cohort the guard becomes looser than the real resolver. Note for the reviewer; does not gate this merge.
What this audit checks
It judges the change on its merits — not whether it was tasked out in an issue. Unticketed, fast-moving work is fine; the question is whether the change is good and whether a better or existing approach should be used instead.
| Pass | What it asks |
|---|---|
| Heuristic | Vague title? Whitespace-only or cruft-bearing diff? (content signals only) |
| Duplication | Do added function/class names already exist elsewhere in the repo? |
| Value Audit | What does it do? What goal does it achieve? Is it good? Better architecture or already-exists? |
| Usefulness Audit | Does it integrate and fit? Will it hold up in real use and actually get used? |
Findings are concerns, not blocks — the human reviewer decides what to do with them.
✅ No Blockers —
|
| opencode GLM 5.2 | opencode DeepSeek v4 Pro | opencode DeepSeek v4 Flash | aggregate | |
|---|---|---|---|---|
| Readiness | 71 | 61 | 71 | 61 |
| Confidence | 95 | 95 | 95 | 95 |
| Correctness | 71 | 61 | 71 | 61 |
| Security | 71 | 61 | 71 | 61 |
| Testing | 71 | 61 | 71 | 61 |
| Architecture | 71 | 61 | 71 | 61 |
Reviewer score is advisory once the run is complete and the verdict has no blockers.
Full multi-shot audit completed 8/8 planned shots over 15 changed files. Global verifier still owns final merge decision. | Full multi-shot audit completed 8/8 planned shots over 15 changed files. Global verifier still owns final merge decision. | Full multi-shot audit completed 8/8 planned shots over 15 changed files. Global verifier still owns final merge decision.
🟠 MEDIUM Changelog misstates sandbox peer range as unchanged — CHANGELOG.md
Line 26 reads 'The
sandboxpeer stays>=0.27.0 <0.28.0, which 0.27.1 satisfies.' This is contradicted by package.json: the diff changes@tangle-network/sandboxfrom>=0.27.0 <0.28.0to>=0.27.1 <0.28.0(head line 175). The peer floor DID move to 0.27.1, not stay at 0.27.0. Impact: a consumer holding sandbox 0.27.0 (valid under the old range) is told by the release note that nothing changed for them, when in fact 0.27.0 no longer satisfies the peer and they must bump sandbox too. The surrounding text otherwise correctly documents that this is a minor (not
🟡 LOW Changelog falsely claims the sandbox peer range is unchanged — CHANGELOG.md
The entry says 'The
sandboxpeer stays>=0.27.0 <0.28.0, which 0.27.1 satisfies.' The package.json diff shows the peer actually moves from '>=0.27.0 <0.28.0' to '>=0.27.1 <0.28.0'. A consumer on sandbox 0.27.0 who upgrades to agent-runtime 0.137.0 will get an unmet-peer warning the changelog told them would not occur. Since this entry's stated purpose is to document the exact peer contract, fix the sentence to: 'Thesandboxpeer floor moves to>=0.27.1 <0.28.0with the catalog.' Optional peer, docs-only impact, one-line fix.
🟡 LOW Changelog says sandbox peer 'stays' but the floor moved — CHANGELOG.md
Line 26 reads: 'The
sandboxpeer stays>=0.27.0 <0.28.0, which 0.27.1 satisfies.' The actual change in package.json:176 is@tangle-network/sandboxfrom>=0.27.0 <0.28.0to>=0.27.1 <0.28.0. Commit 8a1dadd states the floor deliberately moves: 'The sandbox peer floor tracks its catalog version, so it moves to 0.27.1.' The changelog's 'stays' wording is wrong and its parenthetical 'which 0.27.1 satisfies' is satisfied by the old range too, so the sentence reads as no-op when a range break did occur. A consumer on sandbox 0.27.0 is now excluded by the peer range, contradicting [line 28](https://github.com/tangle-network/agent-runtime/blob/ba59547a7c17f21078e6ef1b3eacb7e0
🟡 LOW Caret peer for agent-interface is intentionally wide; no floor on minor behavior — package.json
^1.0.0admits any 1.x minor, relying entirely on agent-interface's compatibility promise that minors are additive. If a future 1.1.0 narrows a type the runtime consumes, this package would accept it with no release here. This is a documented design decision (changelog: 'a later additive minor no longer needs a release here') and the devDependency catalog pins 1.0.0 for CI, so the risk is forward-looking, not a defect in this change. No action required; noted for the global verifier.
🟡 LOW Release note contradicts the actual sandbox peer floor — package.json
The diff moves @tangle-network/sandbox peer from
>=0.27.0 <0.28.0to>=0.27.1 <0.28.0, but the 0.137.0 changelog entry states: 'The sandbox peer stays >=0.27.0 <0.28.0, which 0.27.1 satisfies.' The changelog text (out of this shot's file scope) describes a range this manifest does not declare. Impact: a consumer holding sandbox 0.27.0 reads that 0.137.0 still accepts it, but pnpm's strict peer resolution rejects the install. The manifest change itself is correct and required by the guard (currentMinorPeerRange(0.27.1)); only the release-note narrative is stale. Fix: correct the changelog sentence to say the floor moves to >=0.27.1.
🟡 LOW Sandbox peer floor moved to 0.27.1 but release notes claim it 'stays' — package.json
package.json line 175 changes the sandbox peer from '>=0.27.0 <0.28.0' to '>=0.27.1 <0.28.0'. The CHANGELOG entry for 0.137.0 states 'The sandbox peer stays >=0.27.0 <0.28.0, which 0.27.1 satisfies' — contradicting the actual diff. Commit 8a1dadd confirms the move is intentional ('The sandbox peer floor tracks its catalog version, so it moves to 0.27.1'), so the code is correct and the CHANGELOG is stale. Impact is negligible (sandbox is optional via peerDependenciesMeta, and 0.27.1 is a patch of 0.27.0), but a consumer pinned to exactly 0.27.0 will now get a peer warning. Fix: update the CHANGELOG sentence to reflect the floor move.
🟡 LOW sandbox peer floor bump excludes 0.27.0 consumers — package.json
Floor moves from >=0.27.0 to >=0.27.1, so consumers holding sandbox 0.27.0 cannot install agent-runtime 0.137.0 without a patch-dep bump. This is forced by the repo's peer-floor==devDep-floor guard policy (catalog pins 0.27.1) and 0.27.1 is a patch release, so friction is minimal and intentional. No action required in this file; note only.
🟡 LOW Frozen-lockfile install not executed locally; integrity hashes unverified — pnpm-lock.yaml
All six bumped integrity hashes (agent-core@0.9.4, agent-eval@0.145.21, agent-interface@1.0.0, agent-knowledge@8.0.5, agent-profile-materialize@0.16.0, sandbox@0.27.1) are new sha512 hashes that I could not verify against the registry tarballs: this worktree has no node_modules and no offline pnpm store, so
pnpm install --frozen-lockfilewas not run. If any hash is wrong, install fails hard (fail-closed, no silent corruption), and CI's frozen install is the gate that will catch it. Static consistency, registry existence, and peer-range resolution all check out; the hash check is the only unverified link.
🟡 LOW Major-version bump of @tangle-network/agent-interface 0.53.0 -> 1.0.0 — pnpm-lock.yaml
The catalog bumps agent-interface from 0.53.0 to 1.0.0, a MAJOR semver jump. The lockfile itself is internally consistent (all peer ranges updated: agent-knowledge peer moves from '>=0.53.0 <0.54.0' to '^1.0.0', agent-profile-materialize peer from '>=0.47.0 <0.54.0' to '^1.0.0', and every snapshot resolves to 1.0.0). No lockfile defect exists. The residual risk is that a major bump implies breaking API changes that must be reconciled against source code in the sibling shots and proven via a clean
pnpm install --frozen-lockfile+ typecheck/test run; if the source changes do not account for the interface v1.0.0 breaking surface, the build will fail at typecheck, not in the lockfile. Treat this as a flag for the global verifier, not a blocker on this file.
🟡 LOW agent-interface 0.53.0 -> 1.0.0 is a semver-major bump — pnpm-workspace.yaml
The catalog pins '@tangle-network/agent-interface' from 0.53.0 to 1.0.0, a major version jump. pnpm-lock.yaml shows the cohort's peer ranges were updated to match (agent-knowledge@8.0.5 declares agent-interface ^1.0.0; agent-core/sandbox depend on 1.0.0), and the PR commit history indicates this was deliberate, so no stale peer is left behind. Risk is limited to runtime API breakage in the bench package that consumes it, which is outside this shot's file scope. No action required in this file beyond confirming the bench build/typecheck passes against 1.0.0.
🟡 LOW Composite minor*1_000_000+patch comparison is a fragile numeric encoding — scripts/lib/packed-package-test.mjs
minor * 1_000_000 + patch >= floorMinor * 1_000_000 + floorPatch is only order-correct while both minor and patch stay below 10^6; npm does not cap version field width, so 7+ digit fields would silently invert the comparison. Realistic published versions never approach this, and I verified the common cases (^1.10.0 vs 1.9.1 → false, ^1.9.10 vs 1.10.0 → true), so it is a robustness nit, not an active bug. Fix: compare as tuples ((minor === fm ? patch >= fp : minor > fm)) with an explicit major guard.
🟡 LOW Hand-rolled numeric comparison instead of semver — scripts/lib/packed-package-test.mjs
Admission is computed as minor1_000_000 + patch >= floorMinor1_000_000 + floorPatch. This is a heuristic, not semver: it assumes patch < 1_000_000 (semver allows arbitrary patch integers) and cannot order prerelease/build tuples. It is correct for the current exact non-prerelease pins, so it is a nit rather than a live bug. Consider a minimal dedicated comparison (or an explicit doc of the patch<1e6 assumption) if caret ranges are ever applied to arbitrary published versions.
🟡 LOW JSDoc omits the deliberate pre-1.0 caret rejection — scripts/lib/packed-package-test.mjs
caretAdmits('^0.2.3','0.2.5') returns false even though npm semver admits it (verified live). The floorMajor < 1 early return encodes the repo convention that pre-1.0 ranges use the '>= <' form, but the one-line JSDoc ('admits a version when the major matches and the floor is at or below it') does not state it, so a future reader may treat the false as a bug and loosen it. Fail-closed direction, so nit only; add one sentence to the doc comment.
🟡 LOW New exported pure functions have no unit tests — scripts/lib/packed-package-test.mjs
expectedPeerRange and caretAdmits are pure string functions with several boundary conditions (pre-1.0 fallback, prerelease floors, major-mismatch rejection) but are covered only indirectly by the end-to-end verification scripts, which need packed tarballs and network installs to run. A small table-driven unit test would pin the exact admission semantics, including the prerelease divergence above.
🟡 LOW New semver helpers have no unit tests; edge behavior only covered indirectly — scripts/lib/packed-package-test.mjs
grep found no test importing packed-package-test.mjs; expectedPeerRange and caretAdmits encode subtle semver rules (caret floor, prerelease exclusion, pre-1.0 minor-range split) but are only exercised end-to-end by scripts/verify-packed-cohort.mjs and scripts/verify-official-optimizers.mjs, which pack four external repos and install a consumer. Those CI jobs cover exactly the release's versions, so the false-positive prerelease admission above is invisible to them. Adding a small unit test (plain node:test, no deps) for the boundary cases would lock the gate's semantics.
🟡 LOW caretAdmits admits prerelease versions a caret range excludes — scripts/lib/packed-package-test.mjs
Executed: caretAdmits('^1.0.0', '1.0.0-rc.1') === true and caretAdmits('^1.2.3', '1.2.3-rc.1') === true, but npm semver treats ^1.0.0 / ^1.2.3 as not admitting those prereleases (lower than the floor; prerelease exclusion rule). The version regex /^(\d+).(\d+).(\d+)/ strips the prerelease tail before comparing. Impact today is limited because the cohort pipeline packs released tags, but if a prerelease artifact ever flows through assertExactDependency the guard false-passes while a strict-peer-dependencies consumer install would reject it — the gate claims admission it cannot guarantee. Fix: reject versions with a -/ + tail (compare the full version string, e.g. also check /^(\d+).(\d+).(\d+)$/ anchored at end) or delegate to a semver library.
🟡 LOW caretAdmits ignores semver prerelease ordering — scripts/lib/packed-package-test.mjs
The found regex /^(\d+).(\d+).(\d+)/ is not anchored to end-of-string and does not inspect a prerelease suffix, so a version whose numeric tuple equals the caret floor but carries a prerelease is admitted. Verified with node: caretAdmits('^1.0.0','1.0.0-beta.1') returns true, but npm semver defines ^1.0.0 as >=1.0.0 <2.0.0-0, and 1.0.0-beta.1 < 1.0.0, so real caret semantics reject it. Impact: if a shared-contract dependency is ever published as a prerelease (e.g. 1.0.0-beta.1), assertExactDependency would wrongly accept it as matching a ^1.0.0 dependency instead of failing the exact-resolution check. Not reachable today because pnpm-workspace.yaml pins exact non-prerelease versions (1.0.0, 8.0.5). Fix: anchor the version regex (add (?:-.*)?$) and reject versions whose numeric tuple equa
🟡 LOW caretAdmits is more permissive than npm semver for prerelease versions — scripts/lib/packed-package-test.mjs
The version regex /^(\d+).(\d+).(\d+)/ is unanchored, so '1.1.0-beta.1' and '1.0.0-rc.1' both pass caretAdmits('^1.0.0', ...) (verified by live execution). npm semver excludes prereleases unless the comparator tuple matches and the comparator itself carries a prerelease. Because assertExactDependency (verify-packed-cohort.mjs:607) checks deps installed from file: tarballs, which bypass pnpm's range enforcement, this helper is the only range gate and would bless a packed RC pairing that consumers installing from the registry cannot reproduce. Fix: reject a prerelease suffix in
versionunless the floor regex also captured one and the (major,minor,patch) tuples are equal.
🟡 LOW caretAdmits rejects valid pre-1.0 caret ranges — scripts/lib/packed-package-test.mjs
The guard
if (floorMajor < 1 || major !== floorMajor) return falsereturns false for any ^0.x.y floor. Semver does define caret for 0.x: ^0.2.3 means >=0.2.3 <0.3.0. Verified: caretAdmits('^0.53.0','0.53.5') returns false where semver says true. Impact: if a pre-1.0 package ever declares a caret dependency on a shared contract (as agent-interface did at 0.53.x), assertExactDependency would spuriously throw. Not reachable today: assertExactDependency is only called with agent-interface (1.0.0) and agent-knowledge (8.0.5), both >=1.0, and the comment documents this as intentional policy. Fix: either implement 0.x caret (>=0.x.y <0.(x+1).0) or add an explicit note/error message clarifying pre-1.0 caret is unsupported so a future false failure is diagnosable.
🟡 LOW No unit coverage for the new admission branch — scripts/verify-packed-cohort.mjs
The new caretAdmits branch is exercised only end-to-end via the CI cohort job (verify:cohort), which requires three sibling repo checkouts and pinned refs; there is no fast unit test for caretAdmits or for assertExactDependency's three outcomes (exact, admitted, rejected). The verification script is itself a test harness so this is tolerable, but the lib already exports caretAdmits as a pure function (scripts/lib/packed-package-test.mjs:58) — a 10-case table test would pin the pre-1.0-caret rejection and the floor semantics against future edits.
🟡 LOW Prerelease packed versions are over-admitted by the caret path — scripts/verify-packed-cohort.mjs
caretAdmits (scripts/lib/packed-package-test.mjs:60) parses the packed version with /^(\d+).(\d+).(\d+)/, dropping any prerelease suffix. Verified empirically: caretAdmits('^1.0.0','1.1.0-beta.1') and caretAdmits('^1.0.0','1.0.0-beta') both return true, while real semver admits neither against ^1.0.0. Impact is bounded: dependency.version comes from the packed artifact's own package.json built from clean git checkouts (currently release versions like 1.0.0), the error is over-admission only (an out-of-range release version is still rejected), and assertArchiveResolution plus the single-physical-copy check downstream still catch a mismatched tree. Fix in the callee: reject a version whose remainder after the tuple starts with '-' unless the tuple equals the floor. Root-cause lives in the
🟡 LOW assertExactDependency name no longer matches behavior — scripts/verify-packed-cohort.mjs
The function now accepts caret ranges that admit the packed version, not only exact equality, so the name overstates strictness. Pure readability nit; the inline comment already documents the admission semantics. Consider renaming to assertAdmittedDependency for clarity.
🟡 LOW assertExactDependency name no longer matches its caret-admission behavior — scripts/verify-packed-cohort.mjs
The function is named assertExactDependency but now returns successfully when caretAdmits(declared, dependency.version) is true, i.e. the declared spec is a caret range with a floor at or below the packed version. The inline comment (lines 602-604) documents the intent, so this is a readability nit, not a correctness bug: a future reader grepping for where exactness is enforced will be misled by the name. Rename to assertAdmittedDependency (or assertDeclaredRangeAdmitsPacked) in a follow-up; call sites at [lines 589-590](https://github.com/tangle-network/agent-runtime/blob/ba59547a7c17f21078e6ef1b3eacb7e008bf04f9/scripts/verify-packed-cohort.mjs#L589-L
🟡 LOW caretAdmits falsely admits prerelease versions, weakening the cohort floor check — scripts/verify-packed-cohort.mjs
The imported caretAdmits (scripts/lib/packed-package-test.mjs:58) matches version with /^(\d+).(\d+).(\d+)/, so a prerelease packed version is admitted when node-semver would exclude it: caretAdmits('^1.0.0','1.0.0-alpha.1') -> true and caretAdmits('^8.0.5','8.0.6-alpha.1') -> true, but npm's satisfies() returns false for both (prereleases are excluded from a range unless a comparator shares the same major.minor.patch tuple with its own prerelease). Impact: if a cohort repo is checked out at a prerelease tag (e.g. agent-knowledge 8.1.0-beta.1) while the owner declares ^8.0.5, the guard passes, yet a real registry consumer resolving ^8.0.5 will NOT get the prerelease - the admission the guard claims (and the comment on [line 602-604](https://github.com/tangle-network/agent-runtime/blob/ba
🟡 LOW caretAdmits unanchored version regex falsely admits pre-release versions — scripts/verify-packed-cohort.mjs
assertExactDependency now relies on caretAdmits(declared, dependency.version). In scripts/lib/packed-package-test.mjs:58, caretAdmits parses the version with /^(\d+).(\d+).(\d+)/ (no end anchor), so '1.2.3-beta.0' is treated as 1.2.3 and '^1.2.3' admits it (verified by execution), whereas npm semver ^1.2.3 (>=1.2.3 <2.0.0-0) excludes 1.2.3-beta.0 since pre-releases sort below the release. This is a false-admit in the loose direction, so it cannot mask a real cohort mismatch for release versions; it only matters if a packed version carried a pre-release suffix, which the stable release cohort does not produce. No action required for this PR; optionally anchor the regex as /^(\d+).(\d+).(\d+)$/ for exactness.
tangletools · 2026-08-16T15:40:20Z · trace
tangletools
left a comment
There was a problem hiding this comment.
✅ Approved — 25 non-blocking findings — ba59547a
Full multi-shot audit completed 8/8 planned shots over 15 changed files. Global verifier still owns final merge decision. | Full multi-shot audit completed 8/8 planned shots over 15 changed files. Global verifier still owns final merge decision. | Full multi-shot audit completed 8/8 planned shots over 15 changed files. Global verifier still owns final merge decision.
Full immutable report for this review: trace
Summary comment for this run: full summary
tangletools · 2026-08-16T15:40:20Z · immutable trace
The entry said the sandbox peer stays at >=0.27.0, which was true when it was written and false once the floor moved to >=0.27.1 with the catalog. A consumer on sandbox 0.27.0 would have read that nothing changed for them and then met an unmet peer.
Fixed the MEDIUM —
|
tangletools
left a comment
There was a problem hiding this comment.
✅ Auto-approved drewstone PR — 69a120f6
This PR was opened by the trusted drewstone account.
The full PR reviewer audit still runs separately and will publish findings if it detects issues.
This approval is provisional. It rests on the audit running. If the audit cannot run — for example the CLI bridge rejects it — this approval is dismissed rather than left standing, so an unrun check never reads as a passing one.
tangletools · auto-approval · reason: drewstone_author · 2026-08-16T15:43:29Z
tangletools
left a comment
There was a problem hiding this comment.
🟢 Value Audit — sound
| Verdict | sound |
| Coverage | 2 of 2 lenses (value, usefulness) |
| Concerns | 0 (none) |
| Heuristic | 0.0s |
| Duplication | 0.0s |
| Interrogation | 241.6s (2 bridge agents) |
| Total | 241.6s |
💰 Value — sound
Widens the agent-interface peer from a one-generation window to a caret range over the newly published 1.0.0 compatibility promise, moves the catalog in lockstep so one copy resolves fleet-wide, and teaches the repo's three existing guard scripts the caret shape — coherent, general, and in the grain
- What it does: Releases 0.137.0: peer
@tangle-network/agent-interfacegoes from>=0.53.0 <0.54.0to^1.0.0; agent-eval and sandbox peer floors advance with the catalog (pnpm-workspace.yaml: interface 0.53.0→1.0.0, agent-core 0.9.0→0.9.4, agent-eval 0.145.15→0.145.21, agent-knowledge 8.0.1→8.0.5, agent-profile-materialize 0.15.1→0.16.0, sandbox 0.27.0→0.27.1). It also generalizes the guard machinery: `expec - Goals it achieves: Fix a real installability break: the one-generation peer window was disjoint from what agent-knowledge and sandbox-ui already required, and exact pins inside sandbox@0.27.0 and agent-core@0.9.0 dragged a second interface copy into the tree (PR-body measurement; verified post-change: pnpm-lock.yaml resolves exactly one
@tangle-network/agent-interface@1.0.0and oneagent-core@0.9.4). Secondary: - Assessment: Good on its merits. The strong part is that it does not just edit package.json — it moves every guard that would have rejected the new shape (verify-official-optimizers.mjs asserts peers via
expectedPeerRange; verify-packed-cohort.mjs'sassertExactDependencybecomes admission-with-proof via the packed install; check-docs-freshness regex reads both notations), so the caret is a first-class rule - Better / existing approach: none — this is the right approach. Searched for alternatives: (1) an existing semver-satisfaction helper to reuse —
grep -rn '"semver"|from .semver.|satisfies('finds no semver dependency anywhere in the repo, and the scripts already hand-roll light range parsing (lowerBoundat scripts/check-docs-freshness.mjs:43,currentMinorPeerRangeat scripts/lib/packed-package-test.mjs:37), so a 9-line - Model: opencode/zai-coding-plan/glm-5.2
- Bridge attempts: 2
- Bridge warning: opencode/kimi-for-coding/k2p7: opencode: opencode error
🎯 Usefulness — sound
The trailing edge of a fleet-wide move to the interface caret range: runtime 0.136.0's one-generation peer was disjoint from every first-party package's ^1.0.0, and this release reunifies co-installation, with all three version guards taught the caret shape and CI wired to run them.
- Integration: Directly reachable and imminently used: registry evidence (npm view @tangle-network/{agent-knowledge@8.0.5,agent-core@0.9.4,sandbox@0.27.1,agent-eval@0.145.21,agent-profile-materialize@0.16.0}) shows every first-party peer already declares agent-interface ^1.0.0, so an app installing runtime 0.136.0 beside them hit an unresolvable peer conflict; a fresh pnpm co-install of knowledge+sandbox+eval no
- Fit with existing patterns: Moves with the ecosystem's declared direction rather than competing with it: interface 1.0.0's own published README documents the caret policy ('Do not declare a single-generation window such as >=1.4.0 <1.5.0'), the fleet already adopted ^1.0.0, and this PR retires the one-generation-window pattern that CHANGELOG.md shows runtime used since 0.36.0. The policy is centralized in expectedPeerRange (
- Real-world viability: Holds beyond the happy path: interface 1.0.0's dist is byte-identical to 0.56.0 (tarball diff shows only package.json version and README differ), so the catalog jump 0.53.0->1.0.0 carries no source-level surprise for this repo's imports. The assertExactDependency loosening from equality to caretAdmits admission (verify-packed-cohort.mjs:601-611) is compensated by the packed install later in the sa
- Model: opencode/zai-coding-plan/glm-5.2
- Bridge attempts: 1
No concerns — sound change, no better or existing approach found. ✅
What this audit checks
It judges the change on its merits — not whether it was tasked out in an issue. Unticketed, fast-moving work is fine; the question is whether the change is good and whether a better or existing approach should be used instead.
| Pass | What it asks |
|---|---|
| Heuristic | Vague title? Whitespace-only or cruft-bearing diff? (content signals only) |
| Duplication | Do added function/class names already exist elsewhere in the repo? |
| Value Audit | What does it do? What goal does it achieve? Is it good? Better architecture or already-exists? |
| Usefulness Audit | Does it integrate and fit? Will it hold up in real use and actually get used? |
Findings are concerns, not blocks — the human reviewer decides what to do with them.
✅ No Blockers —
|
| opencode GLM 5.2 | opencode DeepSeek v4 Pro | opencode DeepSeek v4 Flash | aggregate | |
|---|---|---|---|---|
| Readiness | 61 | 70 | 74 | 61 |
| Confidence | 95 | 95 | 95 | 95 |
| Correctness | 61 | 70 | 74 | 61 |
| Security | 61 | 70 | 74 | 61 |
| Testing | 61 | 70 | 74 | 61 |
| Architecture | 61 | 70 | 74 | 61 |
Reviewer score is advisory once the run is complete and the verdict has no blockers.
Full multi-shot audit completed 8/8 planned shots over 15 changed files. Global verifier still owns final merge decision. | Full multi-shot audit completed 8/8 planned shots over 15 changed files. Global verifier still owns final merge decision. | Full multi-shot audit completed 8/8 planned shots over 15 changed files. Global verifier still owns final merge decision.
🟠 MEDIUM Changelog misstates the sandbox peer range (says it stays at 0.27.0, actual floor is 0.27.1) — CHANGELOG.md
Line 26 reads: 'The
sandboxpeer stays>=0.27.0 <0.28.0, which 0.27.1 satisfies.' The head package.json peerDependencies declares@tangle-network/sandbox: >=0.27.1 <0.28.0(changed from >=0.27.0 in commit 8a1dadd, 'chore(release): move the sandbox peer floor ... to 0.27.1'). That commit's file list does not include CHANGELOG.md, so the entry is stale. Impact: the release note understates the actual constraint and omits the migration note that a consumer pinned to sandbox 0.27.0 must bump to 0.27.1 to install this release — the exact class of install failure this release exists to document. Fix: change the line to 'Thesandboxpeer floor moves to>=0.27.1 <0.28.0with
🟠 MEDIUM caretAdmits admits prerelease versions that npm would not resolve into the range — scripts/lib/packed-package-test.mjs
The candidate regex /^(\d+).(\d+).(\d+)/ is unanchored at the end, so caretAdmits('^1.0.0', '1.1.0-beta') and caretAdmits('^1.0.0', '1.0.0-rc.1') both return true (verified by execution), but npm semver excludes prerelease versions from ranges whose comparators carry no prerelease on the same major.minor.patch tuple. Because the packed-cohort install uses file: tarball specs, caretAdmits is the only check that validates the declared dependency range against registry semantics; a cohort packed at a prerelease (e.g. 1.0.1-rc.1) would pass assertExactDependency while a real consumer declaring ^1.0.0 resolves the stable 1.0.x line instead. Fix: reject candidates matching /-\w/ (or anchor with a full-prerelease-aware parse) unless the floor carries a prerelease on the same tuple.
🟡 LOW Changelog sandbox peer range contradicts the released package.json — CHANGELOG.md
Line 26 reads 'The sandbox peer stays >=0.27.0 <0.28.0, which 0.27.1 satisfies.' But commit 8a1dadd (same PR, landed after the changelog entry) moved the peer floor to >=0.27.1 <0.28.0, and the head package.json:175 declares '@tangle-network/sandbox': '>=0.27.1 <0.28.0'. The changelog was not updated to match, so a consumer on sandbox 0.27.0 would believe it is supported when the released peer range rejects it. Fix: reword line 26 to state the floor moved to >=0.27.1 <0.28.0 with the catalog. Everything else in the entry (interface caret, catalog table, agent-eval
🟡 LOW Changelog says the sandbox peer 'stays >=0.27.0 <0.28.0' but the release moved the floor to 0.27.1 — CHANGELOG.md
Line 26 reads: 'The
sandboxpeer stays>=0.27.0 <0.28.0, which 0.27.1 satisfies.' The head package.json peerDependencies declares@tangle-network/sandbox:>=0.27.1 <0.28.0— commit 8a1dadd in this same PR ('chore(release): move the sandbox peer floor and teach the guards the caret range') changed it from>=0.27.0 <0.28.0and did not touch CHANGELOG.md, so the entry is stale. Impact: a consumer pinned to sandbox 0.27.0 reading these release notes would believe 0.137.0 accepts it, when the published peer range rejects 0.27.0 — precisely the class of install-contract fact this entry exists to state (the 0.135.3 entry documents the same class of floor move explicitly). N
🟡 LOW Interface peer change described as a 'narrow', but the range widens (floor shift is the breaking part) — CHANGELOG.md
Line 28: 'This is a minor release, not a patch: the interface range narrows...'. The interface peer moves from
>=0.53.0 <0.54.0(a single minor, 0.53.x) to^1.0.0(=>=1.0.0 <2.0.0, a full major). The new range is wider in admitted versions, not narrower; the release is breaking because the floor jumps from 0.53 to 1.0.0, leaving the ranges disjoint. 'Narrows' is factually backwards and could confuse a reader reasoning about the semver effect. Fix: 'the interface floor moves from 0.53 to 1.0.0' (or 'the interface range becomes disjoint from the previous one').
🟡 LOW Mixed constraint syntax in the peer-pin banner — docs/canonical-api.md
Line 11 states agent-interface as '^1.0.0' while lines 9-10 use bounded ranges ('>=0.145.21 <0.146.0', '>=0.27.1 <0.28.0'). The mixed style is faithful to package.json peerDependencies (the gate's ground truth) and justified by agent-interface reaching 1.0.0 with a semver compatibility promise; scripts/check-docs-freshness.mjs:205-208 in this same PR documents and enforces the equivalence. Cosmetic only — no action required; if desired, a one-line note in the banner explaining the caret convention would preempt reviewer confusion.
🟡 LOW CHANGELOG misstates the sandbox peer floor this manifest raises — package.json
package.json moves the sandbox peer from '>=0.27.0 <0.28.0' to '>=0.27.1 <0.28.0', but the 0.137.0 CHANGELOG entry says 'The
sandboxpeer stays>=0.27.0 <0.28.0, which 0.27.1 satisfies' — understating that a consumer holding sandbox 0.27.0 is now rejected by the new floor. Impact: consumers reading the release notes may expect 0.27.0 to keep installing; pnpm strict-peer resolution will fail for them on 0.137.0. Fix: correct the CHANGELOG sentence to 'moves to >=0.27.1 <0.28.0'. The manifest itself is consistent with the catalog (0.27.1) and lockfile.
🟡 LOW Caret peer widens the interface window on an external semver promise — package.json
^1.0.0 accepts any 1.x (>=1.0.0 <2.0.0), up from a one-generation window. Correctness of the widened window depends on agent-interface honoring its stated promise that a minor is always additive. The commit and CHANGELOG document this deliberately, exports match 0.56.0, and the lockfile dedupes cleanly, so this is a monitored policy risk rather than a defect: if a future 1.1.0 violates additivity, agent-runtime inherits an incompatibility with no release trigger to re-tighten the peer. No code change proposed.
🟡 LOW Major bump of @tangle-network/agent-interface 0.53.0 -> 1.0.0 cannot be validated from the lockfile alone — pnpm-lock.yaml
The 1.0.0 interface release is a major-version boundary. The lockfile resolves it consistently (single copy, all dependent peer ranges moved to ^1.0.0), so this is not a lockfile defect — but breaking-API compatibility for agent-core 0.9.4, agent-eval 0.145.21, agent-knowledge 8.0.5, and agent-profile-materialize 0.16.0 is a package.json/peer-shot concern. No lockfile finding; noted for the global verifier to confirm the interface 1.0.0 peer floor is intended across consumers.
🟡 LOW agent-interface major bump (0.53.0 -> 1.0.0) requires code-level compat check — pnpm-lock.yaml
The lockfile raises @tangle-network/agent-interface from 0.53.0 to 1.0.0 (a semver-major jump) and correspondingly tightens peer deps in agent-knowledge (>=0.53.0 <0.54.0 -> ^1.0.0) and agent-profile-materialize (>=0.47.0 <0.54.0 -> ^1.0.0). The lockfile itself is internally consistent; this is not a lockfile defect. Flag is a hand-off signal: the runtime .ts sources (outside this shot) must be verified for API breakage against the 1.0.0 interface, since a major bump often carries removed/renamed exports. Fix: confirm build+typecheck pass in the PR's other shots.
🟡 LOW New range helpers have no direct unit tests — scripts/lib/packed-package-test.mjs
scripts/lib/ has no test file (glob of test/.spec. confirms only the lib and static-imports.mjs exist). expectedPeerRange, caretAdmits, and the assertPeerMatchesDevelopmentDependency reroute are only exercised indirectly via the CI verify scripts (verify-packed-cohort.mjs, verify-official-optimizers.mjs, verify-package-exports.mjs). The caret semantics split (>=1.0.0 vs pre-1.0), the prerelease gaps, and the exact-string equality assertion are exactly the kind of logic a small vitest case would pin; their absence let the two edge-case defects above ship.
🟡 LOW No unit tests for the new exported pure functions — scripts/lib/packed-package-test.mjs
expectedPeerRange and caretAdmits are pure string functions with no unit coverage; scripts/lib has no test files and repo searches show no test referencing them. Their only exercise is the heavyweight verify scripts (full pnpm pack + cohort install), so the npm-semver divergences above have no cheap regression net. Fix: add table-driven unit tests for both functions (admission at bounds, prereleases, 0-major floors, malformed inputs).
🟡 LOW caretAdmits admits prerelease versions real semver would reject — scripts/lib/packed-package-test.mjs
The
foundregex (/^(\d+).(\d+).(\d+)/, line 60) is not anchored and ignores a prerelease suffix, so caretAdmits('^1.2.3', '1.2.3-beta.0') returns true (verified by execution), while real semver caret ^1.2.3 does NOT admit any prerelease of that tuple. Impact: the packed-install admission check in verify-packed-cohort.mjs could accept a prerelease build that pnpm would not actually resolve under the declared range, weakening the guard. Fix: reject versions carrying a-prerelease when the floor has none, or anchor/parse the full version.
🟡 LOW caretAdmits returns false for ^0.x ranges npm admits, contradicting its doc comment — scripts/lib/packed-package-test.mjs
The floorMajor < 1 early-return makes caretAdmits('^0.5.3', '0.5.4') false (verified), yet npm caret on 0.5.3 is >=0.5.3 <0.6.0 and does admit 0.5.4. The doc comment says 'A caret range admits a version when the major matches and the floor is at or below it' with no >=1.0.0 qualifier, so the function reads as general caret semantics but implements only the post-1.0 case. This fails closed (assertExactDependency throws), which is safe under the repo's convention that pre-1.0 peers use minor-bounded ranges, but a ^0.x declaration would get the misleading error 'requires ^0.5.3, packed 0.5.4'. Fix: state the >=1.0.0-only contract in the doc comment, or handle the 0-major case.
🟡 LOW expectedPeerRange can emit ^1.0.0-beta.1 shapes that caretAdmits cannot evaluate — scripts/lib/packed-package-test.mjs
expectedPeerRange('1.0.0-beta.1') returns '^1.0.0-beta.1' (verified) because the version regex accepts prereleases and the major check passes, but caretAdmits's floor regex /^^(\d+).(\d+).(\d+)$/ rejects prerelease floors, so caretAdmits('^1.0.0-beta.1', '1.0.0-beta.1') is false (verified). The two helpers disagree on the exact range shape expectedPeerRange itself produces: if a 1.x prerelease ever lands in the catalog, assertPeerMatchesDevelopmentDependency demands the caret-prerelease string while assertExactDependency's admission path rejects it. Fix: either make the floor regex accept a prerelease suffix or make expectedPeerRange throw for >=1.0.0 prereleases.
🟡 LOW expectedPeerRange can emit a caret floor caretAdmits cannot parse — scripts/lib/packed-package-test.mjs
expectedPeerRange's regex allows a prerelease suffix (line 52: (?:-.+)?), so for version '1.2.3-beta.1' it returns '^1.2.3-beta.1'. But caretAdmits's floor regex (line 59: /^^(\d+).(\d+).(\d+)$/) requires a bare x.y.z and returns false for that range, so the two functions are internally inconsistent. Impact: none today, since these release guards only ever see stable versions; but a future prerelease bump of agent-interface would produce a peer range the admission check silently rejects. Fix: reject prereleases in exp
🟡 LOW Caret admission ignores prerelease suffixes, so below-floor prerelease versions pass the cohort gate — scripts/verify-packed-cohort.mjs
caretAdmits parses version with the end-unanchored regex /^(\d+).(\d+).(\d+)/ (scripts/lib/packed-package-test.mjs:60), so '1.0.0-rc.1' under declared '^1.0.0' evaluates floor==candidate and passes — but 1.0.0-rc.1 < 1.0.0, so strict semver rejects it (prereleases only satisfy a range via a comparator with the same tuple and a prerelease tag). Same for '1.1.0-beta.1' under '^1.0.0'. Impact: if the cohort packs a >=1.0.0 prerelease (plausible now that agent-interface hit 1.0.0 and RC flows exist), the gate blesses a dependency combination a default registry install would not reproduce — precisely the drift this script exists to catch. The strict-peer consumer install does not close this hole because overrides bypass range satisfaction. Fix: in caretAdmits, reject any version with a prerel
🟡 LOW Exact-dependency guard now accepts stale caret floors silently — scripts/verify-packed-cohort.mjs
Pre-change, this check forced the declared spec to equal the packed version, catching any drift in the release process. Post-change, any caret floor at-or-below the packed version passes (e.g. declared ^1.0.0 with packed 1.5.0), so a stale floor is no longer surfaced. This is a documented, deliberate tradeoff (comment lines 602-604) and is backed by the stronger consumer-install proof, so the primary single-copy safety property is intact; the loss is only that floors no longer need to track the latest packed minor. Acceptable as designed; flagging because the function name 'assertExactDependency' no longer matches its semantics.
🟡 LOW Import ordering nit — scripts/verify-packed-cohort.mjs
caretAdmits is inserted before assertPublishableDependencySpecs, breaking the alphabetical ordering of the named import list from ./lib/packed-package-test.mjs. Not enforced: lint scope is 'biome check src tests examples' and excludes scripts/. Cosmetic only.
🟡 LOW New admission predicate has no direct test coverage — scripts/verify-packed-cohort.mjs
grep shows caretAdmits is referenced only by this call site and defined in scripts/lib/packed-package-test.mjs; no unit test file exercises it. Its only coverage is verify-packed-cohort.mjs itself, which packs four sibling git repos and runs only in a specialized CI lane — so a regression in the regex (e.g., the pre-1.0 floor guard at packed-package-test.mjs:64) would surface as a confusing cohort failure or, worse, silently pass. Fix: add table-driven unit tests for caretAdmits (pre-1.0 floors, major mismatch, below-floor, prerelease, non-caret ranges) next to the existing lib tests.
🟡 LOW assertExactDependency name no longer describes its behavior — scripts/verify-packed-cohort.mjs
After this change the function admits caret ranges (caretAdmits(declared, dependency.version)) in addition to exact equality, so 'assertExactDependency' is now misleading. The in-function comment explains the intent, but the name will mislead future readers into thinking the dependency must pin an exact version. Suggest renaming to assertCompatibleDependency (or similar) for accuracy. Non-blocking.
🟡 LOW caretAdmits admits a prerelease of the exact floor, semver does not — scripts/verify-packed-cohort.mjs
caretAdmits (scripts/lib/packed-package-test.mjs:58) strips prerelease tags via /^(\d+).(\d+).(\d+)/ before comparing, so caretAdmits('^1.2.3','1.2.3-alpha.0') returns true (verified by execution) even though semver ^1.2.3 does NOT admit 1.2.3-alpha.0 (a prerelease of the exact floor sorts below the floor). Impact: if a cohort package is ever packed at a prerelease equal to a caret floor, the guard would pass a spec no real consumer satisfies. Mitigated by the consumer install in this script, which installs the archive directly and still proves single-copy resolution, and by the unlikelihood of prerelease versions in this cohort flow. Fix: compare (major,minor,patch) strictly and return false when the version string carries a prerelease suffix equal to the floor, or strip the prerelease
tangletools · 2026-08-16T15:51:04Z · trace
tangletools
left a comment
There was a problem hiding this comment.
✅ Approved — 22 non-blocking findings — ba59547a
Full multi-shot audit completed 8/8 planned shots over 15 changed files. Global verifier still owns final merge decision. | Full multi-shot audit completed 8/8 planned shots over 15 changed files. Global verifier still owns final merge decision. | Full multi-shot audit completed 8/8 planned shots over 15 changed files. Global verifier still owns final merge decision.
Full immutable report for this review: trace
Summary comment for this run: full summary
tangletools · 2026-08-16T15:51:04Z · immutable trace
Problem
The
@tangle-network/agent-interfacepeer was>=0.53.0 <0.54.0— a window exactly one generation wide.agent-knowledgeandsandbox-uihad already moved past it, so the two halves of the fleet held disjoint ranges and an app could not install this package beside them at all.Measured in this worktree before the catalog moved, with the peer already at
^1.0.0:Two copies. The second is dragged by
sandbox@0.27.0, which pinned interface0.53.0exactly, and byagent-core@0.9.0, which pinned it through its own exact dependency. A caret range on the peer alone does not fix that — the catalog has to move with it.Change
@tangle-network/agent-interface>=0.53.0 <0.54.0^1.0.0@tangle-network/agent-eval>=0.145.15 <0.146.0>=0.145.21 <0.146.0@tangle-network/sandbox>=0.27.0 <0.28.0>=0.27.1 <0.28.0agent-interfaceagent-coreagent-evalagent-knowledgeagent-profile-materializesandboxversionInterface 1.0.0 publishes the surface of 0.56.0 unchanged and states the promise the caret needs: a minor is additive, a patch is a fix, and only a major removes or narrows. A later additive minor now needs no release here.
sandboxdeliberately stayed inside 0.27.x when it adopted the caret, precisely so the peer above still admits it.Why 0.137.0 and not 0.136.0
scripts/check-version-bump.mjsrequires a strictly higher version than the merge base whenever a consumer-visible field changes, becausepublish.ymlskips a version the registry already holds and the change would silently never reach a consumer. The base is 0.136.0, so this is 0.137.0. Minor rather than patch: the interface range narrows, and a consumer still holding an interface below 1.0.0 stays on 0.136.0.Proof on this head
Resolved in the tree, and the point of the whole change:
Measured on a clean
node_modules— the count is one, where before this change the same tree held1.0.0beside a0.53.0dragged in bysandbox@0.27.0.src/testing/fixtures/*.jsonmove because they embedruntimeVersion, andscripts/generate-agent-improvement-proposal-fixtures.tsregenerates them.check-version-bump.mjspasses.