Skip to content
This repository was archived by the owner on Nov 4, 2026. It is now read-only.

Migrate to Tailwind CSS v4 PostCSS architecture - #86

Closed
hotlong with Copilot wants to merge 4 commits into
dependabot/npm_and_yarn/tailwindcss-4.1.18from
copilot/fix-action-run-issue-again
Closed

hotlong with Copilot wants to merge 4 commits into
dependabot/npm_and_yarn/tailwindcss-4.1.18from
copilot/fix-action-run-issue-again

Conversation

Copilot AI commented Jan 15, 2026 •

Copy link
Copy Markdown
Contributor

Tailwind CSS v4 moved the PostCSS plugin to a separate package @tailwindcss/postcss. The build was failing with:

[postcss] It looks like you're trying to use `tailwindcss` directly as a PostCSS plugin.
The PostCSS plugin has moved to a separate package

Changes

PostCSS Configuration

  • Install @tailwindcss/postcss package across workspace
  • Update postcss.config.js files to reference @tailwindcss/postcss instead of tailwindcss

CSS Syntax Migration

  • Replace @tailwind directives with @import "tailwindcss" (v4 syntax)
  • Replace @apply border-border with border-color: hsl(var(--border)) where @apply references custom theme values
  • Maintain existing CSS custom properties for theming

Example:

- @tailwind base;
- @tailwind components;
- @tailwind utilities;
+ @import "tailwindcss";

  @layer base {
    * {
-     @apply border-border;
+     border-color: hsl(var(--border));
    }
  }

Package Dependencies

  • Update peerDependencies to support both v3 and v4: "tailwindcss": "^3.0.0 || ^4.0.0"
Original prompt

引用: https://github.com/objectstack-ai/objectui/actions/runs/21031227714/job/60467556908#step:6:1


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

dependabot Bot and others added 2 commits January 15, 2026 12:25
Bumps [tailwindcss](https://github.com/tailwindlabs/tailwindcss/tree/HEAD/packages/tailwindcss) from 3.4.19 to 4.1.18.
- [Release notes](https://github.com/tailwindlabs/tailwindcss/releases)
- [Changelog](https://github.com/tailwindlabs/tailwindcss/blob/main/CHANGELOG.md)
- [Commits](https://github.com/tailwindlabs/tailwindcss/commits/v4.1.18/packages/tailwindcss)

---
updated-dependencies:
- dependency-name: tailwindcss
  dependency-version: 4.1.18
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
- Install @tailwindcss/postcss package
- Update PostCSS configs to use @tailwindcss/postcss
- Update CSS files to use Tailwind v4 syntax (@import "tailwindcss")
- Replace @apply directives with direct CSS properties
- Add @theme directive for custom colors
- Update peerDependencies to support Tailwind v4

Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
Based on code review feedback, removed the @theme directive since
the theme is already configured via tailwind.config.js and CSS
custom properties. This avoids duplication and potential inconsistencies.

Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
@dependabot
dependabot Bot force-pushed the dependabot/npm_and_yarn/tailwindcss-4.1.18 branch from 3b389ba to 50038f0 Compare January 15, 2026 13:13
@hotlong
hotlong marked this pull request as ready for review January 15, 2026 13:13
@github-actions

Copy link
Copy Markdown
Contributor

✅ All checks passed!

  • ✅ Type check passed
  • ✅ Tests passed
  • ✅ Lint check completed

Copilot AI changed the title [WIP] Fix action run issue in ObjectUI Migrate to Tailwind CSS v4 PostCSS architecture Jan 15, 2026
Copilot AI requested a review from hotlong January 15, 2026 13:22
@dependabot
dependabot Bot force-pushed the dependabot/npm_and_yarn/tailwindcss-4.1.18 branch 4 times, most recently from a65f8de to 2fc59a2 Compare January 19, 2026 08:20
@hotlong hotlong closed this Jan 19, 2026
os-tesla pushed a commit that referenced this pull request Sep 19, 2026
…nd delete the last cast on useChat

`useObjectChat`'s API-mode builder declared its part array as
`Array<Record<string, unknown>>` and pushed plain objects into it. That is not
the chat runtime's part union, and the mismatch was absorbed by an `as any` on
the `messages` option instead of being reported. Re-measured 2x2 on this branch,
each leg mutated on disk with hash proof and restored by state: only the
both-casts-removed leg is red, with one TS2322 in each of the two type-check
programs.

The builder now CONSTRUCTS each part, so the option is checked and the cast is
gone. Per the ruling on this chain (director seat, decision batch #86,
2026-09-08, option A, contract-first) the fix lands at the producer, never as a
wider cast at the consumer.

- The three approval states are reachable: they require the runtime's
  `approval` envelope alongside them, `ChatToolInvocation` gained it in the
  first clause of this chain, and the builder now constructs those arms from it.
- The legacy authoring states `partial-call` / `call` / `result` are folded onto
  the lifecycle arms they mean instead of passing through as states the
  round-trip reader refuses.
- The dead `toolName` member is no longer written onto a `tool-*` part: only the
  dynamic-tool arm declares one, and the reader derives the name off `type`.
- `UseObjectChatOptions.initialMessages`' optional `parts` narrows to the store's
  own part array. Breaking for an external host that passes pre-built parts;
  nothing in this repo sets it.

An invocation claiming an approval state with no envelope to back it is not
constructible, and no envelope is invented for it: the state is derived from the
data it does carry and the producer is told once. An ObjectStack HITL approval
is deliberately not reported, since it is carried by `pendingActionId` and the
mapper re-promotes the state from the tool result.

Also lifts the `approval` envelope in the mapper's tool-invocation extraction,
closing the disagreement where the hydrated path carried the envelope and the
live path dropped it. The lift lands in the same round as its first reader.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018HrVaotisyhgmot9o2MLRq
os-bill pushed a commit that referenced this pull request Sep 24, 2026
…sheds the three runtime-only approval states

The residual clause of the objectui#8426 ruling (decision batch #86):
`approval-requested`, `approval-responded` and `output-denied` leave the
authoring `ChatToolInvocation.state` union and its Zod mirror, so a
schema-authored invocation cannot claim an approval state, with or without an
`approval` envelope.

The authoring type also served as the base of the chat runtime's seam, so the
split is derived rather than copied: `SeamToolInvocation.state` is the union of
the authoring and runtime vocabularies, `useObjectChat`'s `initialMessages` is
the seam's input shape (app-shell hands it runtime values), and
`ChatbotSchema.onSend` hands back the authoring message widened by exactly the
three states, named by a non-exported alias. A compile-time Equal pin ties that
alias to `ChatbotEnhanced`'s runtime union. No export is added.

The un-backed-approval branch in the parts builder is kept: a runtime producer
(app-shell's `mergeToolResultsInto`) still constructs an envelope-less
`approval-requested`. Its docblock now says so.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BA3nKVUwKQJf8DBxrSVtNC
akarma-synetal pushed a commit to akarma-synetal/objectui that referenced this pull request Sep 28, 2026
…nd delete the last cast on useChat (objectui#8426) (objectstack-ai#10017)

Fixes objectstack-ai#8426

The API-mode parts builder in `useObjectChat` declared its part array as
`Array(Record(string, unknown))` and pushed plain objects into it. That
is not the chat runtime's part union, and the mismatch was absorbed by
an `as any` on the `messages` option rather than reported. This makes
the builder **construct** the discriminated parts, so the option is
checked and the cast is gone.

Ruling carried in, not re-decided: director seat, decision batch objectstack-ai#86,
2026-09-08, **option A — contract-first**. Its first clause landed as
objectui#9229; this is the remaining one. The three shortcuts the
dispatch forbids by name (widen the declared type to `any`; keep the
cast with a comment; re-litigate A) are all absent.

## The 2x2, re-run on this branch before repairing

Each leg mutated on disk through an anchor that must hit, with blob-hash
proof, and restored by state (`git diff HEAD` empty after every leg).
Two type-check programs per leg: `tsc --noEmit` and `tsc -p
tsconfig.test.json`.

| outer `} as any)` | nested `(aiInitialMessages as any)` | main | test
|
|:--|:--|:--|:--|
| present | present | exit 0 | exit 0 |
| absent (today's `main`, PR objectstack-ai#8401) | present | exit 0 | exit 0 |
| present | removed | exit 0 | exit 0 |
| **absent** | **removed** | **exit 2**, 1x TS2322 | **exit 2**, 1x
TS2322 |

All four legs reproduce the card's table. The red leg's diagnostic,
verbatim:

```
error TS2322: Type '{ id: string; role: "user" | "assistant" | "system"; parts: Record(string, unknown)[]; }[] | undefined'
  is not assignable to type 'UIMessage(unknown, UIDataTypes, UITools)[] | undefined'
  ...  Type 'Record(string, unknown)' is not assignable to type 'UIMessagePart(UIDataTypes, UITools)'
```

(angle brackets transliterated to round ones above so the body survives
sanitizing.)

⚠️ **One thing did not survive, and it is a method note rather than a
finding about the card.** The first attempt at the two nested-cast legs
was a NO-OP: the mutation tool refused the write because the replacement
text was a substring of the anchor, so its rise-count check could not
distinguish the two. The file was restored and both legs then ran
against a **pristine** tree — reading exit 0, i.e. a false green
pointing the wrong way. They were re-run with a distinguishable
replacement, and the table above is the re-run. Recorded because a
silently-reverted ablation reads exactly like a passing one.

## After: both casts gone, both programs green

```
pnpm --filter @object-ui/plugin-chatbot type-check    -> exit 0   (tsc --noEmit && tsc -p tsconfig.test.json)
pnpm exec vitest run packages/plugin-chatbot/         -> exit 0   47 files, 522 tests passed
```

Program membership proved with a lit control rather than assumed — main
program 1626 files: `src/useObjectChat.ts` 1, `src/mapMessages.ts`
(positive control) 1, `useObjectChat.honestMessages.test.tsx` (negative
control) 0, and the same negative pattern returns 1 against the test
program's file list.

Dependents, on a freshly built union closure (`Scope: 36 of 47` built,
then `Scope: 7 of 47` type-checked): all seven pass, zero `error TS` —
`plugin-chatbot`, `app-shell`, `console`, `site`,
`example-schema-catalog`, `example-console-starter`,
`example-byo-backend-console`. That is the measurement behind the claim
that the published-input narrowing breaks nothing in this repository.

## Reverse verification — the green is not vacuous

Both legs run from the **committed** fix, mutated through an anchor that
must hit, restored to a byte-identical blob, and the restore leg re-run.

1. **Type.** Put the dead `toolName` back on a constructed tool arm.
Predicted red; measured red: `exit 2`, `TS2353: Object literal may only
specify known properties, and 'toolName' does not exist in type ...`.
Restored: exit 0.
2. **Test.** Delete the HITL carve-out in the un-backed-approval report.
Predicted red, and only the HITL test; measured exactly that: `Tests 1
failed | 11 passed (12)`, the failure being `says NOTHING when the
invocation is an ObjectStack HITL approval`. Restored: 12 passed.

## What changed

- **The three approval states are now reachable.** `approval-requested`,
`approval-responded` and `output-denied` require the runtime's
`approval` envelope beside them; `ChatToolInvocation` gained it in
objectui#9229 and the builder now constructs those arms from it. The
per-arm shapes differ (`approved` is forbidden on the outstanding
request, required on the response, pinned to `false` on the denial) so
each is built rather than spread.
- **`tool-${toolName}` is expressible.** The dynamic member the card
feared was the blocker is not one: the runtime's tool set is open, so
the mapped type collapses to an index signature and the discriminant is
a template. Pinned by a test.
- **Legacy authoring states are folded, not passed through.**
`partial-call` / `call` / `result` are not runtime states; passing them
through left the round-trip reader refusing them, so the invocation came
back stateless. Each test pairs the folded subject with a control
asserting the authored spelling is still rejected by the runtime's own
`validateUIMessages`.
- **The dead `toolName` excess property is dropped.** Only the
dynamic-tool arm declares one, and the reader derives the name off
`type`, so this is behaviour-preserving.
- **`UseObjectChatOptions.initialMessages`' optional `parts` narrows**
to the store's own part array. Breaking for an external host that passes
pre-built parts; `minor` per this repo's version policy, with the
breaking note carried in the changeset.
- **`mapMessages`' tool-invocation extraction lifts `approval`.**
Assigned to this card when objectui#9229 shipped the additive half, and
deliberately held until its first reader existed — lifting it earlier
would have minted a declared-but-unread key. It closes the recorded
asymmetry where the hydrated path carried the envelope and the live path
dropped it.

An invocation claiming an approval state with **no** envelope to back it
is not constructible, and no envelope is invented for it (inventing
`approval.id` is the fabrication AGENTS.md #0.1 forbids): the state is
derived from the data the invocation does carry, and the producer is
warned once, by name. An ObjectStack HITL approval is deliberately
**not** warned about — it is carried by `pendingActionId` and a
`pending_approval` result, and the mapper re-promotes the state from
that result on the way back out, so the approval card survives the round
trip.

## Acceptance notes

⚠️ **The ruling's residual clause is NOT in this PR, and it is not
silently dropped.** The ruling says the authoring `state` union should
shed the three runtime-only approval states so that "a schema-authored
invocation cannot claim `approval-requested` without an envelope". That
union lives on `ChatToolInvocation` in `@object-ui/types`, which
objectui#9229 left alone and whose own doc records the narrowing as this
card's. The dispatch fences `packages/types` **out** with "if you find
it incomplete, report; do not extend it here". So the conflict is
reported rather than resolved by me: the narrowing is what would delete
the un-backed-approval branch added here by construction, and it wants
its own card or an explicit widening of this one's fence.

Out of scope, noted, **not** filed:

- `(aiMessages[idx] as any)?.metadata` in the same file is untouched and
unrelated to this card's call. Successor: the next card on this file's
message-output path.
- objectui#9233 (`mergeToolResultsInto` rewriting `state` to
`output-available` for every merged result) is recorded on this card as
possibly changing what "done" means here. It is unchanged by this PR:
building the arms does not by itself put an approval card in front of an
operator on that sub-path. Successor: objectui#9233 itself, which is
open.
- objectui#9232 (the localStorage cache write side rebuilding tool parts
without `approval`) is likewise untouched and open. Successor:
objectui#9232.

## Gates run locally

`check:control-bytes` 0 · `check:new-line-citations` 0 (`0 new
citation(s)`) · `check:changeset-claims` 0 ·
`check:pending-changeset-literals` 0 · `check-changeset-presence` 0 (`1
changeset(s)`) · `check-changeset-no-major` 0 ·
`check-governed-queue-guard --test` — NOT GOVERNED · `eslint
--no-inline-config` on the four changed source files exit 0, 9
pre-existing warnings, none from this diff.

---
🤖 Generated with [Claude Code](https://claude.com/claude-code)

https://claude.ai/code/session_018HrVaotisyhgmot9o2MLRq

---
_Generated by [Claude
Code](https://claude.ai/code/session_018HrVaotisyhgmot9o2MLRq)_

---------

Co-authored-by: Claude <noreply@anthropic.com>
akarma-synetal pushed a commit to akarma-synetal/objectui that referenced this pull request Sep 28, 2026
…sheds the three runtime-only approval states (objectui#10018) (objectstack-ai#10308)

Fixes objectstack-ai#10018
Clause-②: no

This executes the residual clause of the objectui#8426 ruling (director
seat, decision batch objectstack-ai#86, maintainer 「继续决策」), verbatim: 「the authoring
`state` union sheds the three runtime-only approval states, so a
schema-authored invocation cannot claim `approval-requested` without an
envelope」. The shape follows the seat's round-2 answers on the card
(comment `5817891136`): the fence against objectui#10273 is cleared for
the chat-invocation hunks, the file surface is widened, `onSend` uses
design B, and the envelope's enforcement is left to its own card.

## What changed

- **`@object-ui/types`.** `ChatToolInvocation.state` and its Zod mirror
`ChatToolInvocationSchema` drop `approval-requested`,
`approval-responded` and `output-denied`. An authored claim of one is
refused, with or without an `approval` envelope. The mirror refuses it
as one `invalid_value` at `state`.
- **The `onSend` slot (design B, zero new exports).**
`ChatbotSchema.onSend` hands a host the thread the runtime holds, and in
API mode that thread carries the three states. Its `messages` is
therefore typed as the authoring message widened by exactly those
states. Two NON-exported aliases in `complex.ts` do this:
`ChatToolRuntimeOnlyState` and `ChatMessageHandedBack`. The built
`complex.d.ts` emits both without `export`, and no barrel changes.
- **The seam, derived rather than copied (`chatMessageAdapter.ts`).**
`SeamToolInvocation.state` is the union of the authoring state and
`ChatbotEnhanced`'s runtime state. `toRuntimeToolState` takes that
union. The accepted set of values is unchanged, so existing callers
still compile.
- **`useObjectChat.ts`.** `initialMessages` is now the seam's input
shape, because app-shell hands it runtime values restored from server
history. The parts builder's un-backed-approval branch and its tests are
KEPT. A runtime producer still constructs an envelope-less
`approval-requested`: app-shell's `mergeToolResultsInto` promotes it
from a pending-action result, and `hydratedMessagesToChatMessages` hands
it to the builder. Its docblock now says this instead of predicting its
own removal.
- **One vocabulary across two packages.**
`chat-message-contract.test.ts` derives the types-side alias through
`ChatbotSchema['onSend']` and pins it EQUAL to `ChatbotEnhanced`'s
runtime-only states. It also pins the set to the SDK's approval triple,
pins the authoring union to hold none of them, and pins
`ObjectChatMessage` as assignable to the slot. The old
`_StillAnAuthoredMessage` pin asserted the subtype relation this change
removes, so it is inverted to `_NoLongerAnAuthoredMessage`.
- **Docblocks and published docs made true.** The envelope sentence
「Optional because the other seven states never carry one」 is replaced by
what holds after the shed: no authorable state requires the envelope;
the SDK admits an approved envelope on `output-available` and
`output-error` only; the three states that require one are not
authorable. The subtype promise is corrected in `ChatbotSchema.onSend`,
`ObjectChatMessage`, `UseObjectChatOptions.onSend`,
`packages/plugin-chatbot/src/renderer.tsx`'s header comment (comment
only, `3ce44937`), the plugin-chatbot README and
`content/docs/plugins/plugin-chatbot.mdx`.
- **Fixture triage (`chat-tool-approval-envelope-8442.test.ts`).**
`invocation()` now defaults to `output-available`. The id-judgment case
asserts its refusal AT `approval.id`: before this change it would have
kept passing on the state's refusal alone, a phantom check. The old 「is
OPTIONAL」 case becomes the refusal pin for the three states, envelope or
not.

## Changeset: `minor` with a BREAKING banner (版本号策略; `major` is banned)

- **Break 1.** Authored approval states are refused, at TS and at parse,
in `ChatbotSchema.messages` and anywhere else `ChatToolInvocation` is
authored.
- **Break 2.** An `onSend` handler typed against the authoring
`ChatMessage[]` stops type-checking, because the messages it receives
are no longer a subtype of that shape.
- **Declared, not newly accepted.**
`UseObjectChatOptions.initialMessages` now takes `SeamChatMessage`, so
nine optional runtime-only keys are declared on that option:
`buildProgress`, `blueprintProgress`, `charts`; `pendingActionId`,
`draftReview`, `proposedPlan`, `proposedChanges`, `builderHandoff`,
`replayOutcome`. The runtime is unchanged. Local mode keeps the six
tool-invocation keys (`normalizeMessages` forwards `toolInvocations`
whole) and drops the three message-level ones. API mode's
`aiInitialMessages` carries none of the nine into SDK parts.
- **Sibling pending changesets made true (`04ed6186`, prose only,
frontmatter byte-identical).** This change makes two other cards'
pending entries false in the same release, so they are corrected here
(the objectui#10019 precedent). In
`.changeset/8442-chat-tool-approval-envelope.md`, the 「ten declared
`state` values」 sentence and the closing no-narrowing paragraph are
corrected. In `.changeset/6169-chatbot-authoring-face-type.md`, the
`onSend` bullet is corrected.
- **Not measured.** Out-of-repo authors and hosts. In-repo, the
type-check of types, plugin-chatbot and app-shell below is the reading.

## Evidence

All readings are from the committed state. Code head: `3aa259d8`, which
merges `origin/main` at `8b1f0661`. The later commits change no
executable byte:
- **Round 3** (`3ce44937`, comments and changeset prose): plugin-chatbot
type-check exits 0. `check-changeset-presence`,
`check:changeset-claims`, `check:control-bytes` and
`check:new-line-citations` exit 0.
- **Round 4** (`04ed6186`, the two sibling changesets, prose only): the
same gates plus `check:pending-changeset-literals` exit 0, and
`check-changeset-overwrite` reads declared = declares for both.
- **Round 5** (`340efe60`, one changeset sentence): the Not-breaking
paragraph no longer claims the hook forwarded the nine keys; it states
what each builder does. The same gates exit 0.

The contract review of `3aa259d8..04ed618` found one false sentence,
and round 5 fixes it.

**Pins, red first on base `5ea623ea`, before any source edit:**
- `tsc -p tsconfig.test.json` on types exits 2 with exactly 7x TS2578
(unused `@ts-expect-error`). They sit on the six invocation literals
(each state, bare and enveloped) and the authored-message literal. No
control line errs.
- `vitest` on the new file reads `Tests 9 failed | 4 passed (13)`: the 9
refusals fail and the 4 controls pass.

**After the fix, at `3aa259d8`:**
- `type-check` (main + test programs, plus examples for types) exits 0
for `@object-ui/types`, `@object-ui/plugin-chatbot` and
`@object-ui/app-shell`. The new file's membership in the types test
program is shown by the red run above.
- From the repo root, `vitest run packages/types/
packages/plugin-chatbot/` reads `Test Files 263 passed (263)`, `Tests
5468 passed (5468)`.
- A verbose run of the touched files plus the app-shell hydration and
approval-rehydration suites reads `7 passed (7)`, `72 passed (72)`, and
lists each new case by name.

**Ablation 1: `approval-requested` re-added to the authoring union and
its mirror.**
- Setup: from the committed fix, through `ablation-replace.mjs` with
anchors hit x1; blobs `c7c58748` to `ff55f890` and `a1f3bd36` to
`39bdaf7d`. types was rebuilt, and the dist markers read 1
(`complex.d.ts` union member, `zod/complex.zod.js`).
- Prediction: the three `approval-requested` refusal pins red, the other
states' pins and every control green, `_IsTheApprovalTriple` red.
- Measured: types test program exits 2 with exactly 3x TS2578, all on
the `approval-requested` literals. vitest reads `4 failed | 15 passed
(19)`: the three `approval-requested` refusals plus the 8442 refusal
case, with all controls passing. plugin-chatbot main exits 0, and its
test program exits 2 with 1 error, `_IsTheApprovalTriple`.
- Restore: both blobs equal HEAD, `git diff HEAD` is empty, types was
rebuilt, and the dist markers read 0.

**Ablation 2: `output-denied` removed from the non-exported alias.**
This proves the Equal pin can fail.
- Measured: `_OneVocabulary`, `_IsWhatOnSendHandsBack` and
`_HandedBackIsAuthoringPlusTriple` go red, and so do renderer.tsx's
three `onSend: schema.onSend` forwards (main program TS2322).
- Restore: blob equals HEAD, types was rebuilt, and the dist marker
reads 0.

**Gates at `3aa259d8`, each exit 0:**
- `check:control-bytes` and `check:new-line-citations`.
- `node scripts/check-changeset-presence.mjs` and `changeset:check`
(fixed group, no-major).
- `check:changeset-claims` and `check:pending-changeset-literals`.
- Docs: `check:doc-types`, `check:doc-snippets` (672 of 672 blocks
judged), `check:doc-examples`, `check:doc-fences`,
`check:doc-example-ids`, `check:doc-example-readers`, `docs:check-links`
and `check:readme-exports`. The first runs of doc-snippets, doc-examples
and readme-exports read PRECONDITION NOT MET (unbuilt packages); they
are green after the scoped build each gate prints.
- `check:handler-key-reads`, `check:component-surface-parity` and
`check:test-path-roots`.
- `check-governed-queue-guard --test` reads NOT GOVERNED.
- `eslint --no-inline-config --format json` on the 7 changed TS files: 7
files, 0 errors, 20 warnings, 0 of them on an added line. The 20 are
pre-existing `no-explicit-any` and `react-hooks` warnings.

**NOT MEASURED:**
- Repo-wide `pnpm lint`, the full `pnpm test`, and CI convergence (left
to the seat per standing rules).
- Type-check of `apps/console`, `apps/site`, `examples/console-starter`
and `examples/schema-catalog`.
- Out-of-repo consumers.

## Overlap with objectui#10273 (per the seat's fence answer A)

This PR and objectui#10273 both edit `packages/types/src/complex.ts` and
`zod/complex.zod.ts`, and the hunks do not overlap:
- **This PR:** `ChatToolInvocation`, the two new non-exported aliases
after it and `ChatbotSchema.onSend` in `complex.ts`;
`ChatToolInvocationSchema` in `complex.zod.ts`. It does not edit
`zod-mirror-parity.test.ts`, because that pin's type equality moves with
both sides.
- **objectui#10273:** the import block and the Dashboard/Page twins in
`complex.ts`; `GlobalFilterSchema` in `complex.zod.ts`; the parity
census EXCLUSIONS.

Whichever lands second merges `origin/main`; the union of both is the
resolution.

## Acceptance notes

- The authoring `approval` envelope now has no authorable state whose
builder arm reads it. The seat is filing its enforcement as its own
card; this PR only makes its docblock true.
- `renderer.tsx`'s header comment made the same subtype promise. It is
retracted in `3ce44937` (comment only). The seat widened the claim
surface to that file.
- The warning text `warnApprovalStateWithoutEnvelope` prints ("not
representable as authored") was left unchanged to avoid churning the
tests that pin it. The docblock above it is what was rewritten.

The seat's session is
`https://claude.ai/code/session_01BA3nKVUwKQJf8DBxrSVtNC`. This PR was
implemented by a dispatched `os-dev` run in that session (seat
`domain:ui#1`, claim `5817363473`).

---
_Generated by [Claude
Code](https://claude.ai/code/session_01BA3nKVUwKQJf8DBxrSVtNC)_

---------

Co-authored-by: Claude <noreply@anthropic.com>
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants