Skip to content

Fix real-device follow-ups and harden JSON contracts#38

Merged
chenliuyun merged 15 commits intomainfrom
fix/3.3.1-real-device-followups
Apr 26, 2026
Merged

Fix real-device follow-ups and harden JSON contracts#38
chenliuyun merged 15 commits intomainfrom
fix/3.3.1-real-device-followups

Conversation

@chenliuyun
Copy link
Copy Markdown
Collaborator

Summary

  • fix real-device follow-up issues across device cache, policy validation, status/watch, MCP, and operator UX
  • harden JSON and stream contracts across CLI, MCP, and release-smoke coverage
  • expand catalog fidelity fixtures and release-time regression coverage for packed artifacts

Testing

  • npm run test:release-smoke
  • pre-push verify:pre-push (build, tests/version.test.ts, smoke:pack-install)
  • targeted command test suites added and updated across policy, devices, watch/events, doctor, auth/config, rules/plan, and MCP

chenliuyun added 15 commits April 26, 2026 14:27
Self-review of the 3.3.1 follow-up rollup surfaced a false breaking-change
record and several contracts that were only held in place by careful
reading. This commit corrects the record and pins each contract with a
test that fails loudly if it drifts.

- src/version-notes.ts: remove the 3.3.0 envelope entry from
  RELEASE_METADATA. The {schemaVersion,data} envelope actually shipped
  in commit 33d3825 (v2.0.0) and has been in every 3.x release; flagging
  3.3.0 as the breaking boundary would fire upgrade-check warnings on
  every 3.2.x → 3.3.x upgrade for no reason.
- tests/commands/upgrade-check.test.ts + tests/commands/doctor.test.ts:
  update the asserted contract to match — empty registry returns null;
  doctor release-notes check reports 'ok' for a version with no notice.
- tests/policy/validate.test.ts: add parametric coverage for pathological
  rule device refs (undefined, empty string, literal `<id>`) against
  validateLoadedPolicyAgainstInventory. The live validator's silent
  `continue` on null-resolved refs is only safe because the offline base
  pass catches the same shapes; the new test couples the two so weakening
  either side is caught immediately.
- tests/utils/audit.test.ts: spy ENOSPC and EACCES fs failures into
  writeAudit and assert it does not throw. Several callers (dry-run
  path in src/lib/devices.ts in particular) rely on this being
  best-effort; the contract is now a test, not a comment.
- src/policy/validate.ts: add clarifying comments on the permissive
  offline device-ID regex (real gate is alias-live-device-not-found)
  and on the findCatalogEntry ambiguous-array branch (rare, silence
  beats false positives against drifting upstream types).
- package.json: rename `test:release-smoke` → `test:release-smoke:manual`
  so future maintainers do not assume it runs in prepublishOnly or CI.
- package.json + package-lock.json + README.md: bump package version to
  match the branch-intended rollup and refresh the upgrade-check
  example.
Three follow-up fixes surfaced by deeper review of the 3.3.1 rollup. Each
was producing a user-visible regression despite passing tests, because the
existing tests pinned the wrong contract.

- src/status-sync/manager.ts: the --probe preflight was hitting the
  OpenClaw base URL with GET and treating any response (including 401 /
  404 / 5xx from upstream proxies) as success, so misconfigurations
  surfaced only after the detached daemon had already been spawned and
  was silently dropping writes. Probe now POSTs to the same endpoint
  the sink uses at runtime (`/v1/chat/completions`), with a body the
  server actually parses, and separates network-error handling from
  HTTP-error handling. Status-specific hints (401/403 → token, 404 →
  URL path, 400/422 → model, 5xx → server) point at the misconfigured
  input so the operator does not have to guess.

- src/commands/schema.ts + src/commands/health.ts: the bare fallback
  forms (`switchbot schema --type Bot`, `switchbot health --prometheus`)
  were previously declared with options on the root command, on the
  subcommand, or on both — none of which worked, because commander v12
  routes parsing of a parent/child dual-declared option to the PARENT
  command, leaving the subcommand action with empty opts. Options are
  now declared only on the root; subcommand actions pull them via
  `cmd.optsWithGlobals()`. The bare and explicit forms now behave
  identically, and `health serve --audit-log` still works because
  optsWithGlobals merges parent options into serve's own port/host.

- tests/status-sync/manager.test.ts: default fetch mock flipped from
  401-returning to 200-returning so existing success-path tests no
  longer accidentally exercised the failure hint. Three new tests pin
  the probe contract: POST to /v1/chat/completions with the model in the
  body, 401 surfaces a token hint, 404 surfaces a URL-path hint, and
  trailing slashes on the base URL are trimmed before appending the
  probe path.
@chenliuyun chenliuyun merged commit 375d297 into main Apr 26, 2026
11 checks passed
chenliuyun pushed a commit that referenced this pull request Apr 26, 2026
Backfill the CHANGELOG entry for the rollup merged in #38: status-sync
--probe false-negative fix, parent-command option inheritance fix for
schema / health bare forms, live-inventory policy validation, audit
best-effort contract, catalog-fidelity fixtures, and RELEASE_METADATA
correction (3.3.0 is not a breaking boundary; the envelope shipped in
2.0.0).
@chenliuyun chenliuyun deleted the fix/3.3.1-real-device-followups branch April 27, 2026 01:47
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.

1 participant