Skip to content

feat(testing): version-staleness suffix on shape-drift hints (#850)#1030

Merged
bokelley merged 3 commits intomainfrom
claude/issue-850-version-staleness-hint
Apr 28, 2026
Merged

feat(testing): version-staleness suffix on shape-drift hints (#850)#1030
bokelley merged 3 commits intomainfrom
claude/issue-850-version-staleness-hint

Conversation

@bokelley
Copy link
Copy Markdown
Contributor

Closes #850

When a storyboard drift hint recommends a server-side helper (e.g. buildCreativeResponse()) and the agent self-reported a library_version in get_adcp_capabilities that predates the helper's minimum SDK release, the hint message is now suffixed: "Note: your agent reports @adcp/client@4.16.2 — buildCreativeResponse() ships in @adcp/client ≥5.14.0. Upgrade your SDK dep." Agents that don't emit library_version are unaffected. createAdcpServer now stamps library_version in the capabilities response automatically, so agents built on this SDK surface the version without any adopter changes.

Changes:

  • AgentProfile.library_version?: string — populated from get_adcp_capabilities response in discoverAgentProfile()
  • createAdcpServer — stamps library_version: "@adcp/client@X.Y.Z" as a forward-compat extension field (schema uses .passthrough() so no AJV rejection risk; comment notes this should migrate to ext.library_version when the spec formally defines it)
  • detectShapeDriftHints() — optional third param libraryVersion; HELPER_MIN_VERSION map; numeric semver comparison with pre-release strip and non-numeric guard
  • 6 new tests including the critical 5.9.0 < 5.14.0 case that guards against lexicographic sort bugs

Nits surfaced from pre-PR review (not fixed — low priority):

  • hint.message = appendVersionSuffix(...) mutates the fresh hint object in place; { ...hint, message } would be more consistent with the file's immutable style
  • library_version wire format is npm-scoped (@adcp/client@5.20.0); if a future AdCP minor formalizes the field, bare semver + separate library_name will be easier to schema-define
  • HELPER_MIN_VERSION needs updating alongside new server helpers; a test asserting every LIST_WRAPPER_TOOLS key has a corresponding entry would prevent silent drift

What was tested:

  • tsc --project tsconfig.lib.json --noEmitOnError false — zero new errors (2 pre-existing config warnings: deprecated moduleResolution=node10, missing @types/node)
  • node --test test/lib/storyboard-shape-drift-hints.test.js — 19/19 pass
  • Full suite baseline: 534 pre-existing failures before changes, 534 pre-existing failures after (my 6 new tests all pass; the +6 delta in total count is from the new describe block, not new failures)

Pre-PR review:

  • code-reviewer: approved after two blocker fixes (dead HELPER_MIN_VERSION entries removed, pre-release semver strip added) — nits noted above
  • ad-tech-protocol-expert: approved — schema uses .passthrough() so extension field is safe; nit on wire format convention noted above

Triage-managed PR. This bot does not currently iterate on
review comments or PR conversation threads (only on the source
issue). To unblock:

  • Push fixup commits directly: gh pr checkout <num>
    fix → push.
  • Or re-trigger: comment /triage execute on the source
    issue.

See adcp#3121
for context.

Session: https://claude.ai/code/session_01GePNjMP1gsdCwndoBMKhHJ


Generated by Claude Code

claude and others added 3 commits April 28, 2026 13:12
)

When detectShapeDriftHints fires and the agent self-reported a library_version
in get_adcp_capabilities that predates the recommended helper, the hint message
is now suffixed with an upgrade note so developers know to bump their SDK dep
rather than hunt for a missing import.

- AgentProfile.library_version: populated from get_adcp_capabilities response
- createAdcpServer: stamps library_version in capabilities so agents built on
  this SDK surface the version automatically
- detectShapeDriftHints: optional third param threads library_version; semver
  comparison uses segment-by-segment parseInt (guards lexicographic sort bug)
- HELPER_MIN_VERSION map tracks first-ship version for each hint-referenced helper
- 6 new tests covering absent/above/below minimum and the 5.9.0 < 5.14.0 case

https://claude.ai/code/session_01GePNjMP1gsdCwndoBMKhHJ
- Remove dead HELPER_MIN_VERSION entries for audioAsset/displayRender/parameterizedRender
  — none are referenced in any hint message, so the suffix would never fire
- Strip pre-release suffix in semverLessThan so 5.14.0-beta.1 is treated
  correctly rather than silently missing the version comparison
- Guard appendVersionSuffix against non-numeric library_version strings (e.g.
  "local-dev") to prevent spurious upgrade suffixes
- Strengthen list-tool test assertion to check the specific helper name in suffix

https://claude.ai/code/session_01GePNjMP1gsdCwndoBMKhHJ
After rebasing onto main, three issues surfaced from the merged work:

1. Prettier formatting on src/lib/testing/storyboard/runner.ts (the
   original CI failure — main's prettier config tightened slightly).
2. TypeScript noUncheckedIndexedAccess flagged the destructured semver
   segments in shape-drift-hints.ts:semverLessThan as possibly undefined.
   Defaulted aMaj/aMin/aPatch and bMaj/bMin/bPatch to 0 in the
   destructuring; semantically equivalent (parseInt(s, 10) || 0 already
   ran on every present segment) but satisfies strict indexing.
3. The original PR referenced `profile?.library_version` inside
   executeStep but `profile` is only in scope at runStoryboard's caller
   level. Threaded `agentLibraryVersion` through ExecutionState so
   executeStep reads it from runState. Both call sites
   (runStoryboard's per-step loop + runStoryboardStep's standalone
   path) now populate the field from the discovered profile.
4. The capabilitiesData cast at create-adcp-server.ts:2996 needed an
   intermediate `as unknown` per main's stricter type rules, since
   GetAdCPCapabilitiesResponse and Record<string, unknown> don't
   structurally overlap. Behavior unchanged — same hand-stamp of
   library_version onto the response object as a forward-compatible
   extension.

All targeted tests still pass (21 in shape-drift-hints + version-staleness
suite, 133 in controller-related tests).
@bokelley bokelley force-pushed the claude/issue-850-version-staleness-hint branch from 67c4695 to 1902876 Compare April 28, 2026 17:18
@bokelley bokelley marked this pull request as ready for review April 28, 2026 17:18
@bokelley
Copy link
Copy Markdown
Contributor Author

Took this over: rebased onto main and fixed the four breakages (one was the original CI failure, three surfaced from rebasing onto today's merges).

What I did:

  1. Rebased onto main — clean rebase, no conflicts. Branch was 8 commits behind (fix(testing): signals governance advisory block now fires correctly #1036, feat(server): pin-and-bind fetch for webhook DNS-rebinding defense (#1038) #1041, feat(server): dispatchSeed emits SeedSuccess (#1040) #1042, fix(crawler): guard against properties missing identifiers #1043, feat(cli): adcp storyboard run --no-sandbox (#841) #1047 + the three earlier).
  2. Prettier formatting on src/lib/testing/storyboard/runner.ts — the original CI failure. One file; prettier --write cleared it.
  3. shape-drift-hints.ts:semverLessThan strict indexingnoUncheckedIndexedAccess flagged the destructured semver segments. Defaulted aMaj/aMin/aPatch and bMaj/bMin/bPatch to 0 in the destructuring (semantically equivalent to the existing parseInt(s, 10) || 0 pattern; satisfies strict indexing).
  4. profile reference in executeStep — the original PR referenced profile?.library_version inside executeStep, but profile only exists at the caller level. Threaded agentLibraryVersion through ExecutionState so executeStep reads it from runState. Both call sites — runStoryboard's per-step loop and runStoryboardStep's standalone path — now populate the field from the discovered profile.
  5. capabilitiesData cast in create-adcp-server.ts:2996 — needed an intermediate as unknown (GetAdCPCapabilitiesResponse and Record<string, unknown> don't structurally overlap). Behavior unchanged.

Tests: all targeted suites pass (21 shape-drift / version-staleness + 133 controller).

PR is now marked ready. Watching CI.

@bokelley
Copy link
Copy Markdown
Contributor Author

Thanks for taking this over, @bokelley — the rebase + the four fixes (prettier, strict indexing defaults, agentLibraryVersion threading through ExecutionState, and the as unknown cast) all look like the right calls. Glad the targeted suites are green. Watching CI with you.


Generated by Claude Code

Comment thread src/lib/testing/storyboard/shape-drift-hints.ts Dismissed
Comment thread src/lib/testing/storyboard/shape-drift-hints.ts Dismissed
@bokelley bokelley merged commit c807ca6 into main Apr 28, 2026
8 of 9 checks passed
@bokelley bokelley deleted the claude/issue-850-version-staleness-hint branch April 28, 2026 17:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(testing): version-staleness hint when agent is on pre-factory @adcp/client

3 participants