Repository navigation
Commit 6d5eb34
fix(plugin-chatbot): the build panel reads the build-verify part beside the tree, and an unknown phase is not "Building" (objectui#11988) (#11997)
Fixes #11988
Clause-②: yes
The build-progress receiver in `@object-ui/plugin-chatbot` now reads
cloud's post-apply verification loop. This is the receiver that
objectstack-ai/cloud#2172's ruling A orders re-filed. Implemented in
session `https://claude.ai/code/session_01CGZy1BGCjdN5cXqL9cnvB8` (seat
`domain:ui#3`, claim `6064346951`).
## What changed
- **`mapMessages.ts`**
- `extractBuildProgress` reads the tree from the `data-build-progress`
parts whose id is not `build-verify`.
- A new `extractBuildVerify` reads the `build-verify` part: its phase,
`hop` and `tool`.
- The caller attaches the verify state to the tree it verifies, as
`buildProgress.verify`. A `build-verify` part never displaces the tree,
in either part order.
- Phases are read against the spec vocabulary. A value outside it, or a
frame without one, is `unknown` and is no longer coerced to `structure`.
- **`ChatbotEnhanced.tsx`**
- `ChatBuildProgress.phase` widens to the spec's four phases plus
`unknown`.
- `ChatBuildProgress` gains an optional `verify: { phase, hop?, tool?
}`.
- In `BuildProgressPanel`, an unknown tree phase shows a warning header
("Unknown build phase") instead of "Building X…".
- Under the tree, a verify line reads "Checking the change… step N" for
each hop, with the tool name as its tooltip, and "Checked the change" on
`done`. An unknown verify phase shows the warning.
- **All ten language packs:** four new keys, `chatbot.build.verifying`,
`chatbot.build.verifyStep`, `chatbot.build.verified` and
`chatbot.build.unknownPhase`.
- **`.changeset/11988-build-verify-receiver.md`:** `minor` on both
packages.
## The wire shape these pins read
This session cannot read objectstack-ai/cloud#2721: the GitHub API
answers 403, and attaching `objectstack-ai/cloud` is refused for lack of
access. The fixtures therefore follow the card's restatement of the wire
shape:
- the part type is `data-build-progress`;
- the part id is `build-verify`, beside `build-progress`;
- a hop is `{ phase: 'verify', hop, tool }`;
- the exit is `{ phase: 'done' }`.
## Two measurements changed the route the claim names
The claim says the phase values come from the spec's runtime
`BUILD_PROGRESS_PHASES` / `BuildProgressFrameSchema`. Two measurements
ruled that out.
1. **First-load bytes.** A value import of `BUILD_PROGRESS_PHASES` and
`BUILD_PROGRESS_FRAME_TYPE` from `@objectstack/spec/ai` puts the spec's
AI module on the first load, because that module is not tree-shaken.
Measured with a local console `vite build` and `pnpm
check:eager-closure` on commit ee4fbd1:
- the aggregate went from 3,390,981 to 3,418,790 B gzip (+27,809), of
which `vendor-objectstack` was +27,540;
- aggregate verdict: "❌ Console eager closure is 3338.7 KB gzipped
across 337 chunks — 26.7 KB over the 3312.0 KB budget."
- per-chunk verdict: "❌ vendor-objectstack 1595.1 KB / 1585.0 KB ceiling
(OVER by 10.1 KB)".
2. **The spec floor.** Naming the spec's `BuildProgressPhase` in the
exported `ChatBuildProgress` puts an `@objectstack/spec/ai` symbol into
the published `.d.ts`. `pnpm check:spec-floors`, which runs on pushes to
`main` and before publish, then reports "@object-ui/plugin-chatbot
[floor-too-low] packages/plugin-chatbot/dist/ChatbotEnhanced.d.ts
references `BuildProgressPhase` from @objectstack/spec/ai, which
@objectstack/spec@17.0.0 does not export". Fixing that needs
`package.json` and the lockfile, which are outside the claim.
**What landed instead.** The vocabulary is read through the spec's
TYPES. That costs nothing at runtime and puts no spec symbol in the
typings.
- `mapMessages.ts` imports the spec's types with `import type`, which is
erased from the typings. Its phase table is a Record over the spec's
`BuildProgressPhase`, so a missing or extra phase is a compile error.
Its frame type is typed `typeof BUILD_PROGRESS_FRAME_TYPE`.
- The exported phase union is spelled out. `buildVerify-11988.test.tsx`
asserts at compile time, through the package's `tsconfig.test.json`,
that it equals the spec's union in both directions.
- The same test iterates the spec's runtime `BUILD_PROGRESS_PHASES` and
pins every member.
- The four literals therefore appear once in the source, and the
compiler holds them to the spec both ways. Whether that meets the card's
"not restated" is raised for the PM in the report.
## First-load bytes
**This change's own cost**, from a local console `vite build` and `pnpm
check:eager-closure`, base fff07fb against 22a59ea: +377 B gzip. Of
that, `plugin-chatbot` is +345, `i18n-locale-en` +41 and `index` +9.
**At head 4549bcf**, which merges `main` 5d77c09, after the eager
ceiling was re-pinned to 3,281,467 B by objectui#11982 under ruling
6070754914:
- `main`'s own push run at 5d77c09 reads "✅ Console eager closure is
3160.0 KB gzipped across 289 of 2474 chunks (budget: 3204.6 KB,
headroom: 44.5 KB)."
- This PR reads 3160.3 KB against 3204.6 KB: Status **PASS** (budget bot
comment 6071849392). That is about +0.3 KB over `main`, within the
margin.
- The local reading at 4549bcf is 3,236,156 B against the 3,281,467 B
ceiling: "✅ Console eager closure is 3160.3 KB gzipped across 289 of
2474 chunks (budget: 3204.6 KB, headroom: 44.2 KB)."
- Every per-chunk row is ✅: `vendor-objectstack` 1561.8 / 1585.0 KB,
`ui-components` 278.8 / 282.2 KB, `framework` 73.5 / 97.7 KB and
`i18n-locale-en` 44.2 / 48.8 KB.
This PR does not edit any ceiling and moves nothing lazily.
## Published typings (Clause-②)
Read on the built `dist/index.d.ts`:
- the entry re-exports `ChatMessage` and `ChatbotEnhancedProps` from
`./ChatbotEnhanced.js`;
- `ChatMessage.buildProgress?` is a `ChatBuildProgress`;
- its `phase` is `ChatBuildPhase` = `'structure' | 'data' | 'verify' |
'done' | 'unknown'`, where it was `'structure' | 'data' | 'done'`, and
it carries the new optional `verify`.
The entry's type graph widens, so `@object-ui/plugin-chatbot` takes a
`minor`, as the claim expected. `@object-ui/i18n` gains four keys, also
`minor`. After this change, `check:spec-floors` has no finding for
`@object-ui/plugin-chatbot`.
## Verification (at 22a59ea; re-run at the merge head 4549bcf as
noted)
- `pnpm --filter @object-ui/plugin-chatbot type-check` and `pnpm
--filter @object-ui/i18n type-check` (each is `tsc --noEmit && tsc -p
tsconfig.test.json`): exit 0. Re-run at 4549bcf: exit 0.
- `pnpm exec vitest run packages/plugin-chatbot/ packages/i18n/
--maxWorkers=2`: "Test Files 140 passed (140)", "Tests 1920 passed | 13
skipped (1933)". Re-run at 4549bcf: the same counts.
- Tests outside these packages that read the touched files:
`column-identity.ratchet`, `check-i18n-call-site-keys`,
`check-i18n-en-drift`, `check-i18n-dead-keys`,
`one-authority-per-exported-name-6273`, `check-eager-closure-budget` and
`ObjectView.viewConfigGate`. Result: "Test Files 7 passed (7)", "Tests
524 passed (524)".
- These gates exited 0: `check:i18n-keys`, `check:i18n-drift` ("No en
value changed in this range."), `check:i18n-dead-keys` (report only;
none of the new keys is listed), `check:i18n-designer-parity`,
`check:control-bytes`, `check:test-path-roots`,
`check:changeset-claims`, `check:pending-changeset-literals` and
`scripts/check-changeset-presence.mjs`.
- `pnpm exec eslint` on the 13 touched source files returned 0 errors.
All 10 warnings are in `ChatbotEnhanced.tsx`, on lines this diff does
not touch, and the base version has the same 10.
- The 13 files were read from `--format json`, and none is ignored by
`eslint.config.js`.
- Narrowing to these files excludes nothing: type-aware linting is off
(`parserOptions.project` and `projectService` are unset for these
files), and no custom rule reads another file. So this diff cannot
change the lint result of a file it does not touch.
- `scripts/check-governed-queue-guard.mjs --test` on the diff answers
NOT GOVERNED.
- **Not measured locally.**
- The type-check of importers (`app-shell`, `console`) is left to CI.
The only importer, app-shell's `AiChatPage`, builds `buildProgress` from
`buildProgressFromDraftReview` and spreads it, so a wider union cannot
break that site.
- `check:spec-floors` cannot judge the 15 packages that are not built in
this worktree (`no-artifact` findings).
## Reverse verification (at 22a59ea, through `ablation-replace`)
Every leg restored with the blob equal to HEAD and `git diff HEAD`
empty.
1. **"Last part wins"** (the tree reader takes every part): 4 failed, 10
passed. Red: "a verify hop never displaces the finished tree", "a verify
part with no tree beside it is not read as a build tree", "shows the
finished tree AND a verify line that advances per hop" and "closes the
verify line on `done`".
2. **An unknown phase coerced to `structure`**: 2 failed, 12 passed.
Red: "a phase outside the vocabulary is `unknown` on either part…" and
"an unknown tree phase is surfaced as a warning, not rendered as
Building".
3. **The `verify` row deleted from the phase table**: 5 failed,
including "reads every phase of the spec vocabulary as itself…". `tsc
--noEmit` also fails: "TS2741: Property 'verify' is missing … required
in type Record over structure, data, verify, done". (An earlier try at
this leg passed an empty `--replacement`, which the tool refused before
running anything. It was redone with `--delete`.)
4. **The published union gains a member the spec lacks**: the source
`tsc` stays green and the test project fails twice with "TS2344: Type
'false' does not satisfy the constraint 'true'". This is the
compile-time pin working in the direction the source cannot see.
## Acceptance notes
- **A `build-verify` part on a message with no build tree draws no
verify line.** This covers an `apply_edit` turn, if cloud verifies
those. The old reader drew "Building your app…" there, and that is gone.
Carrying the line without a tree needs a sibling message key, which
means widening `chatMessageAdapter.ts`'s runtime-only key list, outside
this claim. Carrier: none.
- **A tree frame with no `phase` now reads `unknown`** (a warning),
where it used to read `structure`. The spec declares `phase` required on
every frame.
- **`hop` is rendered as sent ("step N").** The spec leaves the base, 0
or 1, to the emitter, so a 0-based loop would read "step 0" first. That
is for the cloud seat to know.
- **The verify line keeps its spinner if the stream ends without a
`done` frame.** The tree behaves the same way today.
- **The spec's own JSDoc on `BUILD_PROGRESS_PHASES` goes stale once this
lands.** It still describes this reader as coercing to `structure`, and
cites it by line address. Carrier: none.
- **This change adds about 0.37 KB to the eager closure.** It lands
within the margin objectui#11982 re-pinned (see "First-load bytes").
---
_Generated by [Claude
Code](https://claude.ai/code/session_01CGZy1BGCjdN5cXqL9cnvB8)_
---------
Co-authored-by: Claude <noreply@anthropic.com>1 parent 70f1b27 commit 6d5eb34
14 files changed
Lines changed: 340 additions & 11 deletions
File tree
- .changeset
- packages
- i18n/src/locales
- plugin-chatbot/src
- __tests__
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
3584 | 3584 | | |
3585 | 3585 | | |
3586 | 3586 | | |
| 3587 | + | |
| 3588 | + | |
| 3589 | + | |
| 3590 | + | |
3587 | 3591 | | |
3588 | 3592 | | |
3589 | 3593 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
3317 | 3317 | | |
3318 | 3318 | | |
3319 | 3319 | | |
| 3320 | + | |
| 3321 | + | |
| 3322 | + | |
| 3323 | + | |
3320 | 3324 | | |
3321 | 3325 | | |
3322 | 3326 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
3847 | 3847 | | |
3848 | 3848 | | |
3849 | 3849 | | |
| 3850 | + | |
| 3851 | + | |
| 3852 | + | |
3850 | 3853 | | |
3851 | 3854 | | |
3852 | 3855 | | |
| |||
3935 | 3938 | | |
3936 | 3939 | | |
3937 | 3940 | | |
| 3941 | + | |
| 3942 | + | |
| 3943 | + | |
| 3944 | + | |
3938 | 3945 | | |
3939 | 3946 | | |
3940 | 3947 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
3382 | 3382 | | |
3383 | 3383 | | |
3384 | 3384 | | |
| 3385 | + | |
| 3386 | + | |
| 3387 | + | |
| 3388 | + | |
3385 | 3389 | | |
3386 | 3390 | | |
3387 | 3391 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
3379 | 3379 | | |
3380 | 3380 | | |
3381 | 3381 | | |
| 3382 | + | |
| 3383 | + | |
| 3384 | + | |
| 3385 | + | |
3382 | 3386 | | |
3383 | 3387 | | |
3384 | 3388 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
3319 | 3319 | | |
3320 | 3320 | | |
3321 | 3321 | | |
| 3322 | + | |
| 3323 | + | |
| 3324 | + | |
| 3325 | + | |
3322 | 3326 | | |
3323 | 3327 | | |
3324 | 3328 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
3316 | 3316 | | |
3317 | 3317 | | |
3318 | 3318 | | |
| 3319 | + | |
| 3320 | + | |
| 3321 | + | |
| 3322 | + | |
3319 | 3323 | | |
3320 | 3324 | | |
3321 | 3325 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
3377 | 3377 | | |
3378 | 3378 | | |
3379 | 3379 | | |
| 3380 | + | |
| 3381 | + | |
| 3382 | + | |
| 3383 | + | |
3380 | 3384 | | |
3381 | 3385 | | |
3382 | 3386 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
3463 | 3463 | | |
3464 | 3464 | | |
3465 | 3465 | | |
| 3466 | + | |
| 3467 | + | |
| 3468 | + | |
| 3469 | + | |
3466 | 3470 | | |
3467 | 3471 | | |
3468 | 3472 | | |
| |||
0 commit comments