Skip to content

fix(run): read adapter health on exit 1 and adapter info by release - #28

Merged
roberts-pumpurs merged 2 commits into
mainfrom
fix/rote-contract-calls
Oct 30, 2026
Merged

roberts-pumpurs merged 2 commits into
mainfrom
fix/rote-contract-calls

Conversation

@roberts-pumpurs

@roberts-pumpurs roberts-pumpurs commented Oct 29, 2026 •

Copy link
Copy Markdown
Contributor

Two of Play's rote calls fail on current rote, so publishing an adapter-backed Play stops, and a run with a missing credential errors out instead of asking for it.

Closes modiqo/rote#3311
Closes modiqo/rote#3312

Before

  • Publish gate. For each adapter, validate_credential_contracts runs rote adapter info <adapter_id> --json with the bare name from play inspect. Rote 0.89.0 removed bare names, so the call returns adapter_invalid_id and the publish stops.
  • Run credential check. _credential_snapshot runs rote adapter list <id> --json --health. Rote prints the report and exits 1 when the adapter is unhealthy. run_text raises on any non-zero exit, so a missing token ends in "Play could not verify the static credential contract" instead of the authentication-required result. The auth.ensure poll stops on its first probe for the same reason.

The unit tests stubbed both rote calls with loaders that ignore their argument and exit 0, so neither failure showed.

flowchart TB
  gate[publish gate] --> info[rote adapter info github]
  info --> gateout[adapter_invalid_id, publish stops]
  recover[play run credential check] --> health[rote adapter list --health exits 1]
  health --> recout[CommandError, no sign-in guidance]
  classDef bad stroke:#d33,stroke-width:3px
  class gateout,recout bad
Loading

After

Run the same publish and the same run with a missing token.

  • The publish gate reads the adapter by the release that play inspect checked. It takes convergence.adapters[].release, which modiqo/rote#3310 adds. rote registry adapter info reports only the current release, so the inspected release must equal <selected_candidate>@<current version>. If it does not, or if rote does not report release, the gate stops and names the reason. It does not guess a release.
  • run_text and run_json take accepted_exit_codes. The credential check accepts exit 1 from --health and reads healthy: false, so Play returns its authentication-required result. An accepted exit still fails when rote prints an error envelope.
flowchart TB
  gate[publish gate] --> info[rote adapter info acme/github@1.1.0]
  info --> gateout[fingerprints and versions compared]
  recover[play run credential check] --> health[rote adapter list --health exits 1]
  health --> recout[report read, sign-in offered]
  classDef new stroke:#2a2,stroke-width:3px
  class info,gateout,recout new
Loading

The green nodes are what changes.

Validation

Against a dev rote binary in a sandbox ROTE_HOME with one static-token adapter:

  • _credential_snapshot with no token set returns usable: False, state: static_missing. Before, it raised. After rote token set, it returns usable: True.
  • _default_local_loader("@development/contract-api") returns the adapter. The bare name still returns adapter_invalid_id.

View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need.

Comment on lines +219 to +222
release = adapter.get("release")
if not isinstance(release, str) or not release:
release = f"{selected_source}@{selected_version}"
local = _unwrap_local_adapter(local_loader(release))

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

The fallback can verify a different adapter release. At publication_gate.py:219–222, selected_version comes from registry adapter info, which returns the latest version. It need not match the release selected by play inspect.

Reproduced with inspection selecting receipt-verified github@1.1.0, while registry latest is 1.2.0 with a different fingerprint. With both installed and unchanged credential names, the fallback loads 1.2.0 and returns ok: true, recording its fingerprint and version as verified. The inspected release was never checked.

Resolve the fallback from the inspected release’s identity, or fail explicitly when that identity cannot be established. Add a regression test where the inspected and latest versions differ.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Real. With both releases installed, the fallback loaded the registry's current release and never checked the inspected one. Fixed in 00976f0: the fallback is gone. The gate now requires release from play inspect and fails when it is absent. It also fails when the inspected release is not <selected_candidate>@<registry current version>, before it reads any local adapter. rote registry adapter info takes no version, so the gate cannot verify an older inspected release against the registry. Regression tests cover the missing field and inspected 1.1.0 against registry 1.2.0 with both installed.

@debasishg debasishg left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

approving with a comment

@roberts-pumpurs
roberts-pumpurs merged commit a9c29b9 into main Oct 30, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants