chore(interface): release 1.0.0 with a stated compatibility promise - #195
Conversation
|
@tangletools review now |
tangletools
left a comment
There was a problem hiding this comment.
✅ Auto-approved drewstone PR — c62c45b3
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-16T10:52:10Z
tangletools
left a comment
There was a problem hiding this comment.
✅ Auto-approved drewstone PR — c62c45b3
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-16T10:52:19Z
tangletools
left a comment
There was a problem hiding this comment.
⚠️ Value Audit did not run — no verdict
This is not an approval and not a clean bill of health. Neither interrogation lens returned a judgment, so this PR has no value-audit evidence for or against it.
| Status | audit-incomplete (could not run) |
| Why | value: cli-bridge admission rejected (queue saturated); usefulness: cli-bridge admission rejected (queue saturated) |
| Lenses answered | 0 of 2 |
| What to do | re-run once the CLI bridge has capacity: pr-reviewerctl trigger <repo>#<pr> --force |
💰 Value — error
value agent never ran: the CLI bridge refused admission (no model was started).
- Model: opencode/deepseek/deepseek-v4-pro
- Bridge attempts: 4
- Bridge error: opencode/kimi-for-coding/k2p7: Bridge returned 503: bridge at capacity (queue_timeout, lane=reserved): active=20/20 queued=6/48 — no model was started
🎯 Usefulness — error
usefulness agent never ran: the CLI bridge refused admission (no model was started).
- Model: opencode/deepseek/deepseek-v4-pro
- Bridge attempts: 4
- Bridge error: opencode/zai-coding-plan/glm-5.2: Bridge returned 503: bridge at capacity (queue_timeout, lane=reserved): active=20/20 queued=5/48 — no model was started
No concerns are listed because nothing examined the change — absence of findings here is absence of evidence, not a pass.
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.
Value audit could not run (value: cli-bridge admission rejected (queue saturated); usefulness: cli-bridge admission rejected (queue saturated)). This approval was provisional on that audit running, so it is dismissed. Re-run the reviewer once the CLI bridge has capacity.
The published surface of 1.0.0 equals the published surface of 0.56.0. No file under packages/agent-interface/src changes. The version number changes so a caret range can read the promise the package already keeps. A 0.x minor has the force of a major under npm range rules, so every consumer declared a single-generation window and every interface minor started a coordinated release across five repositories. The artifact check now requires an internal runtime dependency range to admit the workspace version rather than equal it, so a package can hold one installed copy across additive minors.
c62c45b to
bfcb293
Compare
|
@tangletools review now |
tangletools
left a comment
There was a problem hiding this comment.
✅ Auto-approved drewstone PR — bfcb293b
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-16T11:02:31Z
tangletools
left a comment
There was a problem hiding this comment.
⚠️ Value Audit did not run — no verdict
This is not an approval and not a clean bill of health. Neither interrogation lens returned a judgment, so this PR has no value-audit evidence for or against it.
| Status | audit-incomplete (could not run) |
| Why | value: cli-bridge admission rejected (queue saturated); usefulness: cli-bridge admission rejected (queue saturated) |
| Lenses answered | 0 of 2 |
| What to do | re-run once the CLI bridge has capacity: pr-reviewerctl trigger <repo>#<pr> --force |
💰 Value — error
value agent never ran: the CLI bridge refused admission (no model was started).
- Model: opencode/deepseek/deepseek-v4-pro
- Bridge attempts: 6
- Bridge error: opencode/kimi-for-coding/k2p7: opencode: opencode error; opencode/zai-coding-plan/glm-5.2: Bridge returned 503: bridge at capacity (queue_timeout, lane=reserved): active=20/20 queued=12/48 — no model was started
🎯 Usefulness — error
usefulness agent never ran: the CLI bridge refused admission (no model was started).
- Model: opencode/deepseek/deepseek-v4-pro
- Bridge attempts: 4
- Bridge error: opencode/zai-coding-plan/glm-5.2: Bridge returned 503: bridge at capacity (queue_timeout, lane=reserved): active=20/20 queued=5/48 — no model was started
No concerns are listed because nothing examined the change — absence of findings here is absence of evidence, not a pass.
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.
Value audit could not run (value: cli-bridge admission rejected (queue saturated); usefulness: cli-bridge admission rejected (queue saturated)). This approval was provisional on that audit running, so it is dismissed. Re-run the reviewer once the CLI bridge has capacity.
…limits An adversarial review of the 1.0.0 cut found two gaps. The relaxed artifact check accepted any range that contains the workspace version, so ">=0.9.0" passed and admits a future major whose removals the package never compiled against. The check now also requires the range to stop below the next major. The promise said a widened union is minor without naming what that costs. An exhaustive switch that assigns the remaining case to `never` fails when a minor adds a member, and a caret floor of ^1.0.0 lets a resolver keep 1.0.0 for a package that reads a later export. Both limits are now stated in the changeset and the README.
Independent adversarial review — codex CLI, high effort, prompted to REFUTEThe So the second pass was run in a different model family instead. It was asked five questions and told to refute, not to help. Result: 3 findings, 2 clean.
All three are fixed in
The internal caret adoption is deliberate sequencing, not an omission: Not mergedThis PR is not being merged on the auto-approval alone. It waits for a real |
tangletools
left a comment
There was a problem hiding this comment.
✅ Auto-approved drewstone PR — 98853088
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-16T11:17:38Z
|
| State | Detail |
|---|---|
| Interrupted | webhook restarted |
No review verdict was produced for this run. Trigger a fresh review on the current PR head if the PR is still open.
tangletools · #195 · model: kimi-for-coding · updated 2026-08-16T11:24:05Z
tangletools
left a comment
There was a problem hiding this comment.
✅ Auto-approved drewstone PR — 98853088
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-16T11:35:07Z
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 | 3 (3 weak-concern) |
| Heuristic | 0.0s |
| Duplication | 0.0s |
| Interrogation | 251.6s (2 bridge agents) |
| Total | 251.6s |
💰 Value — sound-with-nits
Releases agent-interface as 1.0.0 with a documented semver promise and rewrites the repo's packaging guard from exact-pin equality to a bounded-range rule so internal consumers may adopt caret ranges — coherent, in-grain, and correctly sequenced; only transitional looseness in the guard is worth a n
- What it does: Three coordinated pieces. (1) A major changeset (.changeset/interface-1-0.md) bumps @tangle-network/agent-interface 0.56.0 → 1.0.0 with the published surface unchanged, plus a stated promise: minor = additive, patch = fix, major = removes/narrows, with two consumer limits (default branch in switches over exported unions; caret floor set to the lowest minor actually used). The same promise is docum
- Goals it achieves: Breaks the coordinated-release coupling measured in #190. Under 0.x, npm range rules gave every minor the force of a major, so all internal consumers exact-pinned (all seven still pin 0.56.0 — grep across packages/*/package.json) and external consumers needed single-generation windows, forcing a five-repo release on every interface minor. Once the promise is stated at 1.0.0, additive minors become
- Assessment: Good on its merits and in the grain of the codebase. The repo already centralizes publish hygiene in one hand-rolled guard (no workspace: specifiers at check-package-artifacts.mjs:341-345, no prepare scripts at :372-377, packed-tarball manifest equality at :296-325); extending that same guard is exactly where this policy belongs, and it runs in both CI and release workflows. Policy and enforcement
- Better / existing approach: none — this is the right approach. I searched for existing semver-range validation to reuse (grep for manypkg, syncpack, dependency-cruiser, and semver imports across .json/.mjs/*.ts excluding node_modules): nothing exists; this is the first and only semver import. The standard pnpm alternative — declaring 'workspace:^' and letting pnpm substitute at publish — is explicitly rejected by this repo
- 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, self-consistent policy change: it releases agent-interface 1.0.0 via a changeset whose published surface is unchanged, states the compatibility promise where consumers read it, and rewrites the existing CI/release gate to enforce the new caret-range rule instead of fighting it — immediat
- Integration: Fully wired and reachable now, not hypothetical. The relaxed rule lives in scripts/check-package-artifacts.mjs:346-369, which runs on the critical path in .github/workflows/ci.yml:22, .github/workflows/release.yml:56 (immediately before changesets/action publishes at line 58), and scripts/upstream-check.mjs:246 (UP-11). Its subjects are the 7 workspace packages that depend on @tangle-network/agent
- Fit with existing patterns: Fits the grain. It edits the established enforcement point in place — same loop, same error-message shape — rather than adding a competing checker; check-control-contract-artifacts.mjs is a different domain and untouched. Using the
semverpackage (root devDependency, lockfile updated in the diff) matches how the surrounding ecosystem (npm, changesets) reasons about ranges, and replaces string eq - Real-world viability: Holds up beyond the happy path, with one latent gap. Verified numerically against the installed semver 7.8.5: exact pins pass (current state), '^1.0.0' on a 1.0.0 workspace passes, open ranges like '>=0.9.0' are refused, and prerelease/unreadable versions are handled (inc returns null is guarded, check-package-artifacts.mjs:356-358). Gap: for a 0.x internal dependency, npm gives a minor the force
- Model: opencode/zai-coding-plan/glm-5.2
- Bridge attempts: 1
🎯 Usefulness Audit
🟡 ? [robustness] ``
scripts/check-package-artifacts.mjs:355 uses inc(version, 'major') as the excluded ceiling. Under npm semantics a 0.x MINOR carries the force of a major, so for a 0.x internal dep the checker admits ranges like '>=0.56.0 <1.0.0' that can resolve to a breaking next minor — verified with the installed semver: satisfies('0.57.0', '>=0.56.0 <1.0.0') is true. Not reachable in today's tree (the only internal dependency edge is agent-interface, promoted to 1.0.0 by this same PR), but new packages in th
💰 Value Audit
🟡 Guard permits the single-generation window the promise retires [maintenance] ``
The changeset and README (packages/agent-interface/README.md:174-175) say the '>=X.Y.0 <X.(Y+1).0' window 'is retired and must not be reintroduced', but the new check passes it: verified with node-semver, satisfies('1.5.0', '>=1.4.0 <1.5.0') fails the next-major stop test nowhere — '>=1.4.0 <1.5.0' admits 1.4.0 and excludes 2.0.0, so it PASSES. Likewise a multi-major OR whose lower arm predates the workspace major (e.g. '^0.9.0 || ^1.4.0') passes. The looseness is currently necessary — every int
🟡 The relaxed rule is dormant until a follow-up converts internal manifests [maintenance] ``
No manifest in this PR uses a range: all internal consumers of @tangle-network/agent-interface still declare exact '0.56.0' (packages/agent-core/package.json:200, agent-provider-tangle:103, daytona:47, testkit:71, cli-bridge:67, computesdk:47, e2b:47), and the changeset bump will rewrite them to exact '1.0.0', which the old equality rule would also have accepted. So the permissive branch of the new check exercises nothing until a deliberate conversion PR switches these to '^1.0.0'. The ordering
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 | 76 | 92 | 83 | 76 |
| Confidence | 85 | 85 | 85 | 85 |
| Correctness | 76 | 92 | 83 | 76 |
| Security | 76 | 92 | 83 | 76 |
| Testing | 76 | 92 | 83 | 76 |
| Architecture | 76 | 92 | 83 | 76 |
Reviewer score is advisory once the run is complete and the verdict has no blockers.
Full multi-shot audit completed 5/5 planned shots over 5 changed files. Global verifier still owns final merge decision. | Full multi-shot audit completed 5/5 planned shots over 5 changed files. Global verifier still owns final merge decision. | Full multi-shot audit completed 5/5 planned shots over 5 changed files. Global verifier still owns final merge decision.
🟠 MEDIUM inc(version,'major') on a prerelease returns same-major stable, falsely rejecting correct caret ranges — scripts/check-package-artifacts.mjs
const nextMajor = inc(version, 'major'). For a prerelease workspace version, node-semver returns the same-major stable: inc('1.0.0-rc.1','major') === '1.0.0' (verified against the repo's semver 7.8.5), not '2.0.0'. Then satisfies('1.0.0', '^1.0.0-rc.1') is true, so the check at line 364 throws 'must stop below 1.0.0' for the canonical correct range. Any dependent declaring ^X.Y.Z-rc.N while the workspace holds a prerelease (the standard 'changeset pre' workflow) fails CI with a misleading error. Latent today (all committed versions are stable), fail-closed direction. Fix: parse with new SemVer(version) and construct
${semver.major + 1}.0.0instead of inc()
🟡 LOW Single-generation window ban is stated but not enforceable by the shipped check — .changeset/interface-1-0.md
The changeset ends with 'The single-generation window >=X.Y.0 <X.(Y+1).0 is retired and must not be reintroduced.' The companion check in scripts/check-package-artifacts.mjs (same PR) only verifies satisfies(workspaceVersion, specifier) and !satisfies(nextMajor, specifier); a window such as '>=1.4.0 <1.5.0' satisfies both (admits 1.4.0, excludes 2.0.0), so the ban relies solely on review discipline. Impact: a future PR could reintroduce the window shape without CI failing, silently eroding the caret-range promise this release is built on. Fix: add a range-shape check (e.g. require the specifier to be an exact pin or a caret range parsed via semver.validRange plus a prefix test) or accept it as a documented convention. Not a release blocker; the 1.0.0 bump itself is unaffected.
🟡 LOW Surface-equality claim is asserted but not enforced at release time — .changeset/interface-1-0.md
Lines 7-8 assert 'The published surface of 1.0.0 equals the published surface of 0.56.0. No export is added, removed, or narrowed by this release.' This is true today because this PR touches no file under packages/agent-interface/src. However, the release happens later when
changeset versionruns (baseBranch main), and changesets only knows about changesets. A source change to packages/agent-interface landed before that version bump — with its own changeset — would be folded into the same 1.0.0 release, silently voiding the claim this promise is founded on. Nothing in this PR gates 1.0.0 on surface equality (e.g., a diff of the built dist/d.ts or exports of 0.56.
🟡 LOW README states semver-from-1.0.0 before the version actually is 1.0.0 — packages/agent-interface/README.md
The section opens 'This package follows semantic versioning from 1.0.0', but at this HEAD packages/agent-interface/package.json still declares version 0.56.0 (verified via git show at the head commit). The 1.0.0 promise only becomes true if the .changeset/interface-1-0.md major changeset is applied and the package is actually published as 1.0.0. If that release does not ship with this doc, the README overstates the current published contract. Impact: misleading consumer guidance on a published README (it is part of the npm
fileslist in publishConfig, so it ships to registry). Fix: ship the 1.0.0 release in the same PR/cycle, or gate the section wording on the release landing.
🟡 LOW Disjunctive ranges bypass the 'stop at next major' gate — scripts/check-package-artifacts.mjs
The gate probes a single point (nextMajor) rather than bounding the whole range. For version 1.0.0 and specifier '^1.0.0 || ^3.0.0', satisfies('2.0.0', specifier) === false so the gate passes, yet the range admits 3.0.0 — a future major the package 'has never compiled against', contradicting the rationale stated in the comment at lines 348-353. Rare in practice (an internal dep would have to be hand-written as a disjunction), but if the intent is 'must stop below the next major', the check should verify the range's own upper bound rather than one probe version. Not blocking.
🟡 LOW False positive: prerelease of a fresh major rejects its own caret range — scripts/check-package-artifacts.mjs
semver.inc(version,'major') for a version with minor=patch=0 and a prerelease does NOT bump the major (verified with semver@7.8.5: inc('1.0.0-beta.0','major') === '1.0.0'). Then the next-major probe at line 364 runs satisfies('1.0.0', '^1.0.0-beta.0') === true and throws 'must stop below 1.0.0', even though ^1.0.0-beta.0 caps at <2.0.0-0 and admits no future major. Consequence: publishing any X.0.0-beta.y while internal deps use the natural ^X.0.0-beta.y range fails the guard; deps would be forced to exact pins or hand-written upper bounds. Not triggered today (all internal pins are exact, version 0.56.0) but this PR's release cadence makes a major prereleas
🟡 LOW Next-major ceiling is looser than pre-1.0 semver breaking boundary — scripts/check-package-artifacts.mjs
inc('0.56.0','major') yields '1.0.0', so the check 'must stop below next major' accepts a range such as '>=0.56.0 <1.0.0' (satisfies('1.0.0', ...) is false). Under semver convention, pre-1.0 packages break on minor bumps, so such a range would admit a breaking 0.57+. This matches the comment's stated next-major contract, so it is intentional, and no current manifest uses such a range (all internal deps are exact '0.56.0'). Non-blocking; only matters if a future pre-1.0 range is introduced.
🟡 LOW Next-major guard only tests the immediate major; compound ranges admitting later majors pass — scripts/check-package-artifacts.mjs
satisfies(nextMajor, specifier) rejects a range admitting major+1 but not major+2 and beyond: '^1.0.0 || ^3.0.0' with workspace version 1.x passes (verified: satisfies('2.0.0') false, satisfies('3.0.0') true), even though the comment at lines 348-353 claims open ranges are refused because they 'admit a future major whose removals this package has never compiled against' — major 3 is exactly that. Contrived input for a CI guard, but the enforced invariant is weaker than the documented one. Fix: additionally reject if satisfies a high sentinel (e.g. '999999.0.0') or inspect the parsed Range's maximum.
🟡 LOW Unparseable specifier reported as 'must admit workspace version' instead of invalid range — scripts/check-package-artifacts.mjs
satisfies() returns false (does not throw) for unparseable ranges such as 'latest', 'not-a-range', git URLs, or npm: aliases, so the failure surfaces as 'must admit workspace version 1.2.0, received latest', masking the real cause. Still fail-closed, but the message misleads. Fix: validate with new Range(specifier) in a try/catch first and report 'invalid range' distinctly.
tangletools · 2026-08-16T11:52:26Z · trace
tangletools
left a comment
There was a problem hiding this comment.
✅ Approved — 9 non-blocking findings — 98853088
Full multi-shot audit completed 5/5 planned shots over 5 changed files. Global verifier still owns final merge decision. | Full multi-shot audit completed 5/5 planned shots over 5 changed files. Global verifier still owns final merge decision. | Full multi-shot audit completed 5/5 planned shots over 5 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-16T11:52:26Z · immutable trace
…very later major
semver inc() returns the same-major stable release for a prerelease, so
inc("1.0.0-rc.1", "major") is "1.0.0". The artifact check used that value as
the ceiling, so a prerelease workspace refused its own caret range.
The ceiling now comes from the parsed major. The check also probes majors
above the next one, because a disjunction such as "^1.0.0 || ^3.0.0" excludes
2.0.0 and still admits a major the package has never compiled against. An
unparseable specifier now reports an invalid range instead of a missing
workspace version.
Fixed the MEDIUM and four of the LOW findings —
|
| version | range | result |
|---|---|---|
1.0.0 |
^1.0.0 |
accept |
1.0.0 |
1.0.0 |
accept |
1.0.0-rc.1 |
^1.0.0-rc.1 |
accept (was a false reject) |
1.0.0-beta.0 |
^1.0.0-beta.0 |
accept (was a false reject) |
1.4.0 |
^1.0.0 |
accept |
1.0.0 |
>=1.0.0 <2.0.0 |
accept |
1.0.0 |
^1.0.0 || ^3.0.0 |
refuse (was a bypass) |
1.0.0 |
>=1.0.0 |
refuse |
1.0.0 |
latest |
refuse as invalid range |
0.56.0 |
^1.0.0 |
refuse |
The last row is the release mechanic, not a curiosity: ^1.0.0 cannot land on this PR because the workspace still publishes 0.56.0. The seven internal ranges move on the Version Packages branch, where the workspace already reads 1.0.0, which also saves a second agent-core and six-provider release round.
Negative control on the real repo, not only the harness:
$ pnpm check:package-artifacts # after setting agent-core's range to >=0.56.0
Error: @tangle-network/agent-core dependencies.@tangle-network/agent-interface
must stop below 1.0.0, received >=0.56.0
exit=1
Suite re-run by me on this head, not relayed:
build exit 0
check-types exit 0
test 1437 passed (interface 438, core 505, cli-bridge 144, tangle 138,
trace-contract 182, testkit 24, computesdk/daytona/e2b 2 each)
check:package-artifacts exit 0 (9 packages, 28 exports, 56 export targets)
check:control-artifacts 131 passed
The remaining LOW findings are accepted as stated: the surface-equality and window-shape claims are review conventions, and the README wording becomes true when this release ships.
tangletools
left a comment
There was a problem hiding this comment.
✅ Auto-approved drewstone PR — 8eb5d913
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-16T11:57:34Z
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 (2 weak-concern) |
| Heuristic | 0.0s |
| Duplication | 0.0s |
| Interrogation | 160.5s (2 bridge agents) |
| Total | 160.5s |
💰 Value — sound-with-nits
Releases agent-interface as 1.0.0 with a documented additive-minor compatibility promise, and relaxes the repo's manifest guard from 'internal deps must exactly equal the workspace version' to 'valid range that admits the workspace version and stops below the next major' — coherent, in-grain, and th
- What it does: Three pieces: (1) a major changeset bumping @tangle-network/agent-interface to 1.0.0 with an explicit promise (minor=additive, patch=fix, major=removal/narrowing) plus two stated limits (default branch in switches over exported unions; caret floor set to the lowest minor used) — .changeset/interface-1-0.md:1; (2) the same policy mirrored into packages/agent-interface/README.md:161 under 'Versionin
- Goals it achieves: Let the seven in-workspace consumers of agent-interface (agent-core, provider-cli-bridge, provider-computesdk, provider-daytona, provider-e2b, provider-tangle, provider-testkit — all currently exact-pinned at 0.56.0) migrate to ^1.x so an additive interface minor no longer forces a coordinated patch release of every dependent: with updateInternalDependencies:'patch' plus exact pins (.changeset/con
- Assessment: Good change, well matched to its goal and the codebase's grain. The repo concentrates all publish-manifest invariants in this one guard script (no workspace: specifiers, no prepare script, pack/repack export checks), and extending that script — rather than adding syncpack/manypkg or a new lint pass — is exactly the established pattern. The README 'Versioning' section follows an existing precedent
- Better / existing approach: No existing equivalent found — searched for other semver/range linting (rg 'semver|check-package-artifacts' across .github/workflows, package.json, scripts/): the only manifest guard is this script, and the repo deliberately bans workspace: specifiers in publishable fields (scripts/check-package-artifacts.mjs:341), so pnpm's workspace:^ protocol is not an option here. One simpler-and-complete refi
- 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, correctly-sequenced 1.0.0 release: the changeset rides the existing changesets flow, the promise is documented where consumers read it, and the artifact-check relaxation is the mechanically necessary enabler for caret-range adoption, wired into both CI and the release pipeline.
- Integration: Fully wired and reachable. The modified check runs on every PR (ci.yml:22, after install at :18) and before every publish (release.yml:33). The changeset (.changeset/interface-1-0.md) is consumed by the existing
changeset:version/changeset:publishflow (root package.json:8-9) and will produce 1.0.0 from 0.56.0. The checker relaxation is ahead of its caller by necessity, not by neglect: all six - Fit with existing patterns: Fits the codebase grain. It modifies the established artifact-guard in place (scripts/check-package-artifacts.mjs:347-388) rather than adding a competing mechanism, and the two new conditions map exactly onto real workspace mechanics:
satisfies(wsVersion, range)is the condition under which pnpm still links the workspace copy instead of fetching a registry copy, and later-major exclusion is the - Real-world viability: Held up under direct verification with the installed semver 7.8.5: open ranges (
*,>=0.9.0) are refused, the disjunction^1.0.0 || ^3.0.0is caught by the major+2 probe,~/1.x/>=1.0.0 <2.0.0behave as the comments claim, and the prerelease ceiling pitfall (documented at scripts/check-package-artifacts.mjs:361-364) is real and correctly avoided by building nextMajor from the parsed majo - Model: opencode/zai-coding-plan/glm-5.2
- Bridge attempts: 1
🎯 Usefulness Audit
🟡 Relaxed guard admits the single-generation window it exists to retire [problem-fit] ``
The changeset states the window
>=X.Y.0 <X.(Y+1).0'is retired and must not be reintroduced', but I verified with the repo's semver that>=1.4.0 <1.5.0and<=1.9.0at workspace 1.4.0 both pass the new logic (satisfies the floor, excludes all later majors). The check's stated scope — one installed copy, no uncompiled major — is exactly enforced, so this is a deliberate floor, but an internal window declaration would quietly re-impose the coordinated-release tax this PR is retiring. A cheap
💰 Value Audit
🟡 Ceiling enforcement samples three versions instead of reading the range's max bound [better-architecture] ``
scripts/check-package-artifacts.mjs:378-387 probes satisfies() at (major+1).0.0, (major+2).0.0, and 999999.0.0, but a range admitting a later major at a non-probed point slips through: I verified satisfies('2.5.0', '>=1.0.0 <2.0.0 || >=2.5.0 <3.0.0') === true while all three probes return false, so the invariant 'must stop below the next major' the comment claims is not fully enforced. A structural check — iterate range.set and reject any comparator set whose max is '*' or whose max version's ma
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.
Closes the version-scheme half of #190.
What this is
@tangle-network/agent-interface1.0.0. The published surface equals 0.56.0 exactly — this branch touches no file underpackages/agent-interface/src. Only the number changes, plus the promise that explains what the number now means.Why
#190 measured the mechanism. A 0.x minor has the force of a major under npm range rules, so every consumer declared a single-generation window (
>=X.Y.0 <X.(Y+1).0) and every interface minor started a coordinated release across five repositories. The measured publish cadence was eleven minors in 9.9 days, median gap 20.4h, minimum 24 minutes. An adoption wave is slower than that, so the fleet could not converge by chasing.The evidence that 1.0 is honest, from #190:
.d.tsdeletion audited across the same window. One breaking generation in ten (0.53.0 → 0.54.0:RequestedInteractionsnarrowed toReadonly<Record<...>>,ZodObject→ZodRecord).Under
^1.0.0, nine of those ten transitions would have resolved with no consumer release at all.The promise, stated in the CHANGELOG
Two limits are stated with it, because a caret range makes them reachable:
defaultbranch in everyswitchover an exported union. An exhaustiveness check that assigns the remaining case toneverfails when a minor adds a member, and the promise does not cover it.^1.4.0, because^1.0.0lets a resolver keep 1.0.0.All of it also lands in
packages/agent-interface/README.mdunder Versioning, so a consumer author reads it without opening a CHANGELOG.Contents
.changeset/interface-1-0.mdmajorbump foragent-interface, carrying the promise into the CHANGELOGpackages/agent-interface/README.mdscripts/check-package-artifacts.mjspackage.json,pnpm-lock.yamlsemverdev dependency for that checkThe artifact check previously required an exact match, which is the rule that forced the exact pin this release exists to retire. Admitting the version keeps the same safety — a packed tarball can never name a version the workspace will not publish — while allowing
^1.0.0. The next-major bound was added after an adversarial pass showed that admission alone lets>=0.56.0through, which would admit a future major the package never compiled against.Verified by table:
1.0.0and^1.0.0pass,>=0.55.0and*are refused, and0.9.4/^0.9.4still pass on a 0.x package.Proof
Run in this branch's worktree:
A second pass in a different model family, prompted to refute, returned 3 findings and 2 clean answers. All three are fixed in
9885308— see the review comment below.pnpm changeset versionwas run locally to confirm the outcome, then reverted: interface0.56.0→1.0.0,agent-core→ 0.9.4, six providers → patch. Substituting^1.0.0for the exact pins on top of that versioned state and rerunningpnpm check:package-artifactsalso exits 0, which is the proof that the follow-up in this workspace lands cleanly.What follows
Version PackagesPR publishes 1.0.0.^1.0.0(agent-core,agent-provider-{cli-bridge,computesdk,daytona,e2b,tangle,testkit}).^1.0.0— 5 peer ranges (agent-runtime,agent-app,agent-knowledge,agent-profile-materialize,sandbox-ui) and 3 exact deps (sandbox,sandbox-cli,agent-eval).The in-flight single-generation PRs — tangle-network/agent-runtime#878 and tangle-network/sandbox-ui#254 — are redirected to
^1.0.0rather than landing another window. This is intended as the last adoption wave.