Skip to content

feat(provider-testmu): publish @agent-device/testmu on plugin contract v2 - #3770

Merged
thymikee merged 3 commits into
feat/plugin-registry-v2-docsfrom
feat/plugin-registry-v2-testmu
Oct 17, 2026
Merged

thymikee merged 3 commits into
feat/plugin-registry-v2-docsfrom
feat/plugin-registry-v2-testmu

Conversation

@thymikee

@thymikee thymikee commented Oct 16, 2026 •

Copy link
Copy Markdown
Member

Summary

Part 4 of 4, closes #3756 (stack of #3755, umbrella #3747). Stacked on the docs PR. Blocked by #3748: do not merge before it.

@agent-device/testmu is now a plugin contract v2 package.

import testmu from '@agent-device/testmu';
testmu({ credentials: { username, accessKey } }); // or testmu() to read LT_USERNAME / LT_ACCESS_KEY
  • The default export of the package root and of ./agent-device is the testmu(options) factory. Credentials passed as options replace the environment variables, which stay the fallback. With options, the plugin declares no environment variables, so the daemon doesn't fingerprint them.
  • The v1 agentDevicePlugin declaration and its ./dist/plugin.mjs entry stay, so agent-device plugins add @agent-device/testmu still works on hosts without v2. Hosts with v2 prefer the export. The v1 entry goes in 0.22: remove superseded plugin, client and environment APIs #3759.
  • scripts/check-provider-plugin.mjs takes AGENT_DEVICE_CORE_SPEC to install a published core instead of packing this checkout.

Validation

pnpm check:affected --run --head a304bb7f40 (the stack top, which contains this layer): passed (exactCommit). Packed plugin via node scripts/check-provider-plugin.mjs packages/provider-testmu: passed against this checkout's packed core and with AGENT_DEVICE_CORE_SPEC=agent-device@0.21.28.

🤖 Generated with Claude Code

View guided diff Turn on auto-fix

@github-actions

github-actions Bot commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor
PR Preview Action v1.8.1
Preview removed because the pull request was closed.
2026-10-17 12:47 UTC

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 12 files

You’re at about 93% of the monthly reviewed-line limit. You may want to disable incremental reviews to conserve quota. Reviews will continue until that limit is exceeded. If you need help avoiding interruptions, please contact contact@cubic.dev.

View guided diff | Turn on auto-fix | Re-trigger cubic

@github-actions

github-actions Bot commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor

Size Report

Metric Base Current Diff
Installed (including dependencies) 5.37 MB 5.37 MB 0 B
Package (unpacked) 5.37 MB 5.37 MB 0 B
Package (download) 1.62 MB 1.62 MB -9 B

Startup median (7 runs, lower is better):

Scenario Base Current Diff
CLI --version 26.3 ms 27.2 ms +1.0 ms
CLI --help 76.0 ms 75.9 ms -0.1 ms

@thymikee
thymikee force-pushed the feat/plugin-registry-v2-testmu branch from ae3c4f2 to d35d87e Compare October 16, 2026 23:02
@thymikee
thymikee force-pushed the feat/plugin-registry-v2-testmu branch from d35d87e to f8555c9 Compare October 16, 2026 23:17
@thymikee

Copy link
Copy Markdown
Member Author

This PR is ready at f8555c9, and all 18 checks pass. I found no code problems. I did not rerun the packed-plugin check (including the agent-device@0.21.28 run), read built dist output, or run on a live TestMu AI device. The claim that a published 0.21.28 host loads the v1 entry rests on the PR body.

Not blocking, and you can take or leave these: the README import example gets an untyped module from the published tarball, because the build sets dts:false and publishConfig.exports has no types condition, so either emit declarations with a types condition or show a .js example. Also, each resolve, verify and setup call builds both the webDriver descriptor and the connection and discards one, and a partial credentials object from a JS caller sets the missing key to undefined, which shadows the environment value and reports a missing credential with no test covering it. You could export createTestMuWebDriver and call it and createTestMuConnection directly, and in #3759 read credentials from options instead of rewriting env.

Merge order is the only remaining step: the PR says it is blocked by #3748 and stacked on the docs PR, and I did not check that gate. The repo has no .changeset directory, so the CHANGELOG Unreleased entry covers the changeset item.

@thymikee thymikee added the ready-for-human Valid work that needs human implementation, judgment, or maintainer merge label Oct 17, 2026
@thymikee
thymikee force-pushed the feat/plugin-registry-v2-testmu branch from f8555c9 to 7f449c5 Compare October 17, 2026 05:06
@thymikee

Copy link
Copy Markdown
Member Author

Thanks. Taken in 7f449c5:

  • The README example is now plain JS, since the tarball ships no declarations.
  • A credentials object missing one key now falls back to the environment for that key instead of shadowing it with undefined; test added.
  • I left each call building both the descriptor and the connection: v2 delegates to the v1 composition so the v1 entry stays the single place that wires them (and stays reachable for the production-exports gate). The cost is two small closure objects per call. Reading credentials from options instead of rewriting env is a good fit for 0.22: remove superseded plugin, client and environment APIs #3759.

@thymikee
thymikee force-pushed the feat/plugin-registry-v2-testmu branch from 7f449c5 to 495046c Compare October 17, 2026 05:23
@thymikee

Copy link
Copy Markdown
Member Author

The PR is ready at 495046c. The earlier review at f8555c9 was also clean, and the new changes in provider-testmu look good.

All 18 checks pass and I know of no conflicts. Nothing blocks merge.

Not blocking, and you can take or leave these: a partial credentials object now reads the missing key from host.env (index.ts#L29), but credentials.variables stays [] for any passed object, so the fallback LT_* name is never listed and the host and remote clients will not fingerprint or forward it; should variables come from the same per-key resolution, or should the factory reject a partial object? The new test in index.test.ts#L111 passes a partial object through as never, checks the fallback value but not .credentials.variables, and an empty-string value falls back silently because the check is a truthiness test, so it would help to assert variables for the partial case and state the empty-string rule once.

I did not run the tests locally. I did not trace the fingerprint or forwarding consumers past the contract comment. The delta also showed unrelated daemon changes from the base rebase, and I reviewed only the provider-testmu changes.

@thymikee
thymikee force-pushed the feat/plugin-registry-v2-testmu branch from 495046c to 2dd219b Compare October 17, 2026 07:32
@thymikee
thymikee force-pushed the feat/plugin-registry-v2-testmu branch from 2dd219b to 73a0bbc Compare October 17, 2026 08:01
@thymikee
thymikee added this pull request to stack #3779 October 17, 2026 08:16
@thymikee
thymikee force-pushed the feat/plugin-registry-v2-testmu branch from 73a0bbc to 4c5b159 Compare October 17, 2026 08:41
@thymikee
thymikee force-pushed the feat/plugin-registry-v2-testmu branch from 4c5b159 to c09dbc6 Compare October 17, 2026 09:32
@thymikee

Copy link
Copy Markdown
Member Author

Rebased onto the new #3769 (no conflicts). check:affected --run --head c09dbc6c4f passes.

@thymikee
thymikee force-pushed the feat/plugin-registry-v2-testmu branch from c09dbc6 to 1c548fb Compare October 17, 2026 10:10
@thymikee
thymikee force-pushed the feat/plugin-registry-v2-testmu branch from 1c548fb to dfb5230 Compare October 17, 2026 10:34
@thymikee

Copy link
Copy Markdown
Member Author

The code in 1c548fb is unchanged from the patch I reviewed earlier in 73a0bbc, so the earlier clean code review still holds. What is now fixed is that the PR has been rebased onto a new head, and the required evidence is in place. Local fake-server tests cover the HTTP behavior, so live TestMu cloud validation is not needed here.

Not blocking: the factory in packages/provider-testmu/src/index.ts#L32 declares no credential variables when a partial credentials object is passed (for example {credentials:{username:'x'}}), yet the plugin still reads LT_ACCESS_KEY from the daemon env, so the fingerprint is empty; declaring only the variables the overlay does not supply, or rejecting partial credentials, would fix it. Could the v2 factory also own the provider directly through createTestMuWebDriver and createTestMuConnection, with plugin.ts as a thin v1 shim and the capabilities read from the package.json manifest instead of the mirrored TESTMU_CONNECTION constant? The first note is optional. For the second, please say whether that smaller shape would do, or why it was rejected.

CI is still pending. Two Smoke Tests jobs are queued or in progress with no failure, and the other 21 checks are green. This PR changes the packed-plugin exports and scripts/check-provider-plugin.mjs, so those lanes may exercise it; there is no failure to attribute yet.

I ran no tests or builds, and I relied on the range-diff showing the patch as identical rather than re-diffing it. I did not re-run the pack-and-install check, with or without AGENT_DEVICE_CORE_SPEC. The PR body cites head 1c548fb, while your latest comment cites c09dbc6, so please confirm which head you meant. No review threads exist on this head.

Before merge, the two Smoke Tests jobs must finish green, and #3748 and the stacked base PR must merge first.

This review covers 1c548fb. The newer head dfb5230 is the same commit rebased onto 22f4e58, with no content change.

thymikee and others added 3 commits October 17, 2026 12:53
…t v2

The package default-exports testmu(options) at ./agent-device and the root.
Credentials come from options with LT_USERNAME and LT_ACCESS_KEY as the
fallback. The v1 agentDevicePlugin declaration and its entry stay, so the
package still loads on hosts without the v2 contract.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…ion leaves to the environment

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
… capabilities from package.json

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@thymikee

Copy link
Copy Markdown
Member Author

This PR is ready at dfb5230. The earlier review at 73a0bbc is still the base, and the code now holds up.

CI shows 23 checks, none failing, and there are no conflicts.

Not blocking, and you can take or leave these: a partial credentials object from an untyped JS caller, such as {credentials:{username:'x'}}, gives an empty variables list at https://github.com/callstack/agent-device/blob/dfb5230/packages/provider-testmu/src/index.ts#L18, so the daemon does not fingerprint LT_ACCESS_KEY (you already disclosed this; one rule would settle it, either declare the variables when any key is missing or drop the per-key fallback and the cast test); and each connection.resolve, connection.verify and setup call rebuilds the whole v1 registration at https://github.com/callstack/agent-device/blob/dfb5230/packages/provider-testmu/src/index.ts#L34, which fits into #3759.

I did not run the packed-plugin check against agent-device@0.21.28, so that result is your report. I did not review the stacked base (plugin contract v2, daemon and registry), which is upstream. There is no live TestMu cloud run, but the change does not touch the device path and the fake-server tests cover the HTTP behavior.

Merge waits for #3748 to land and for the stacked base PRs to merge first.

@thymikee
thymikee force-pushed the feat/plugin-registry-v2-testmu branch from dfb5230 to a304bb7 Compare October 17, 2026 11:50
@thymikee

Copy link
Copy Markdown
Member Author

Pushed a304bb7f40. Applied: (1) the v2 factory now owns the provider directly through createTestMuWebDriver and createTestMuConnection; plugin.ts is a thin v1 shim. (2) The connection capabilities are read from agentDevicePlugin.connection in package.json instead of the mirrored TESTMU_CONNECTION constant. (3) A partial credentials option declares only the variables the options leave to the environment, so a missing accessKey still puts LT_ACCESS_KEY in the fingerprint (tested). The connection and WebDriver code load lazily, which keeps the eager-closure budget; connection.resolve is therefore async. The v1 entry is declared in .fallowrc.json next to the existing index.ts rule. The PR body cites a304bb7f40. check:affected --run --head a304bb7f40 and scripts/check-provider-plugin.mjs packages/provider-testmu pass.

@thymikee

Copy link
Copy Markdown
Member Author

The PR is ready at a304bb7. The earlier review at dfb5230 found nothing to fix, and this update keeps that result.

Not blocking: index.test.ts:121 now compares testmu().connection?.capabilities with the same manifest object that index.ts:48 reads, so that assertion can never fail, and only the provider and credentialVariables checks still guard v1/v2 parity; and the as ConnectionCapabilities cast at index.ts:48 could use the registry's capability validator instead. Take or leave both.

All checks now pass at a304bb7. The PR's own diff touches only packages/provider-testmu, scripts/check-provider-plugin.mjs, .fallowrc.json and docs, and the daemon changes in the delta come from the stack base. There are no conflicts.

I did not re-run the packed-plugin check against the local core or agent-device@0.21.28, so that result comes from the PR body. I did not inspect the bundled dist/agent-device.mjs. I ran no live TestMu cloud session, and unit tests cover the credential-precedence fix through the plugin's setup and connection entry points.

The PR body says not to merge before #3748. That issue was closed as completed, so please update the body if it no longer blocks this PR.

@thymikee
thymikee merged commit e6340d2 into main Oct 17, 2026
23 checks passed
@thymikee
thymikee deleted the feat/plugin-registry-v2-testmu branch October 17, 2026 12:46
thymikee added a commit that referenced this pull request Oct 17, 2026
…ment

* origin/main:
  feat(provider-testmu): publish @agent-device/testmu on plugin contract v2 (#3770)
  docs(plugins): document plugin contract v2, the inventory and ADR 0034 (#3769)
  feat(daemon): daemon status lists the registered provider plugins (#3768)
  feat(plugins): plugin contract v2 and one provider registry (#3767)

# Conflicts:
#	packages/daemon/src/sessions/handlers/lease.ts
#	src/__tests__/cloud-connect-testmu.test.ts
#	src/cli/commands/connection.ts
#	src/cli/commands/daemon.ts
#	src/daemon-client/daemon-client-metadata.ts
#	src/daemon-client/daemon-client.ts
thymikee added a commit that referenced this pull request Oct 17, 2026
…-no-process-globals

* refactor/host-environment:
  feat(provider-testmu): publish @agent-device/testmu on plugin contract v2 (#3770)
  docs(plugins): document plugin contract v2, the inventory and ADR 0034 (#3769)
  feat(daemon): daemon status lists the registered provider plugins (#3768)
  feat(plugins): plugin contract v2 and one provider registry (#3767)

# Conflicts:
#	packages/daemon/src/server/http/daemon-runtime-composition.test.ts
#	packages/daemon/src/server/http/daemon-runtime-metadata-ownership.test.ts
#	packages/daemon/src/server/http/daemon-runtime.ts
#	src/daemon-composition.ts
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ready-for-human Valid work that needs human implementation, judgment, or maintainer merge

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(provider-testmu): publish @agent-device/testmu on plugin contract v2

1 participant