fix(client-web): reject unknown web kind, lock fixture to contract, observe web card in boot smoke

- webCardModel returns null for an unknown web `kind` (wire from a newer host)
  instead of drawing it as a malformed fetch, matching the unknown-`card` and
  terminal-model wire-boundary default.
- Fixture WEB_SEARCH_RESULT/WEB_FETCH_RESULT and the source type derive from the
  contract's ToolResultView via Extract, so a new contract field fails at the
  type level rather than drifting silently.
- built-boot smoke asserts the web_search/web_fetch turns render their keyed
  WebRow cards, giving the registration and wire projection an assembled check.
- DetailsPanel comment no longer claims the card omits content for search.
- ui-primitives README inline-Chinese limitation now lists WebBlock's controls.
This commit is contained in:
Chinesezjc
2026-07-30 20:42:29 +08:00
parent 917e114b68
commit 224a9d5f09
8 changed files with 48 additions and 28 deletions

View File

@@ -108,6 +108,17 @@ it('boots the built plugin graph and renders a fixture session end to end', asyn
expect(document.querySelector('[data-sample="bash-global"]')).not.toBeNull()
}, { timeout: 10_000 })
// The web render intent reaches the assembled boot graph: the fixture's
// web_search / web_fetch turns render their keyed WebRow cards, proving the
// registration, wire projection, and card rendering survive the real bundle
// path (not just the per-package src benches). Without this the whole web
// card could silently fall back to the generic row and every new unit test
// would still pass.
await waitFor(() => {
expect(document.querySelector('[data-web="search"]')).not.toBeNull()
expect(document.querySelector('[data-web="fetch"]')).not.toBeNull()
}, { timeout: 10_000 })
// Every bundle injected its plugin-owned style tag (the loader's CSS path).
const styleOwners = [...document.head.querySelectorAll('style[data-plugin]')]
.map(style => style.getAttribute('data-plugin'))