Skip to content

Commit 6d5eb34

Browse files
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

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
---
2+
'@object-ui/plugin-chatbot': minor
3+
'@object-ui/i18n': minor
4+
---
5+
6+
The chat build panel reads cloud's post-apply verification loop, and an unknown build phase no longer reads as "Building" (objectui#11988, the receiver objectstack-ai/cloud#2172's ruling A orders).
7+
8+
After `apply_blueprint` finishes, cloud's agent loop reports its verification hops on a second `data-build-progress` part with the id `build-verify`, beside the build tree. A hop is `{ phase: 'verify', hop, tool }` and the exit is `{ phase: 'done' }`. The receiver used to take the last `data-build-progress` part whatever its id, and turned every phase other than `data` and `done` into `structure`. So the first verification hop replaced the finished tree with "Building your app…".
9+
10+
- **The tree and the verification part are read apart, by part id.** The `build-verify` part never displaces the tree, whichever order the two parts arrive in. A message that carries only the tree maps and renders exactly as before.
11+
- **The build panel shows a verification line under the tree.** It reads "Checking the change… step N" while a hop runs, with the hop's tool name as its tooltip, and "Checked the change" once the `done` frame arrives. A `build-verify` part on a message that has no build tree is not drawn as a tree.
12+
- **Phases are read against the spec's vocabulary.** The receiver's phase table and frame type are typed by `@objectstack/spec/ai`'s own `BuildProgressPhase` and `BUILD_PROGRESS_FRAME_TYPE`, so a phase the spec adds or drops fails the type check here instead of drifting. The spec's runtime module is not imported, because it would put its whole AI schema module on the console's first load. A phase outside the vocabulary, or a frame without one, is now `unknown` and shows as a warning line ("Unknown build phase") on the tree header or on the verification line. It is no longer coerced to `structure`.
13+
- **Type change.** `ChatBuildProgress.phase`, reached through `ChatMessage['buildProgress']`, widens from `'structure' | 'data' | 'done'` to `'structure' | 'data' | 'verify' | 'done' | 'unknown'`: the spec's phase vocabulary plus `'unknown'`, held equal to the spec's union by a compile-time test. `ChatBuildProgress` also gains an optional `verify` member, `{ phase, hop?, tool? }`. The published typings name no new `@objectstack/spec` symbol, so the package's spec range is unchanged.
14+
- **New language-pack keys, in all ten packs:** `chatbot.build.verifying`, `chatbot.build.verifyStep`, `chatbot.build.verified` and `chatbot.build.unknownPhase`.

‎packages/i18n/src/locales/ar.ts‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3584,6 +3584,10 @@ const ar = {
35843584
seed: "بيانات تجريبية",
35853585
},
35863586
moreArtifacts: "+{{n}} أخرى",
3587+
verifying: "جارٍ التحقق من التغيير…",
3588+
verifyStep: "الخطوة {{n}}",
3589+
verified: "تم التحقق من التغيير",
3590+
unknownPhase: "مرحلة إنشاء غير معروفة",
35873591
},
35883592
},
35893593
chatbotError: {

‎packages/i18n/src/locales/de.ts‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3317,6 +3317,10 @@ const de = {
33173317
seed: "Beispieldaten",
33183318
},
33193319
moreArtifacts: "+{{n}} weitere",
3320+
verifying: "Änderung wird geprüft…",
3321+
verifyStep: "Schritt {{n}}",
3322+
verified: "Änderung geprüft",
3323+
unknownPhase: "Unbekannte Build-Phase",
33203324
},
33213325
},
33223326
chatbotError: {

‎packages/i18n/src/locales/en.ts‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3847,6 +3847,9 @@ const en = {
38473847
// `building`/`built` interpolate `appFallback` when the
38483848
// build has no app label, so each pack must keep BOTH
38493849
// frames in the one case/gender that noun phrase is in.
3850+
// `verifying`/`verifyStep`/`verified` are the post-apply
3851+
// verification line and `unknownPhase` the warning for a
3852+
// phase outside the spec's vocabulary (objectui#11988).
38503853
// `plan.*` — the "N objects · N views · N dashboards" strip. Plural
38513854
// FAMILIES: one slot per CLDR category the pack's language
38523855
// selects (objectui#11432), plus the base key for a call
@@ -3935,6 +3938,10 @@ const en = {
39353938
seed: 'Sample data',
39363939
},
39373940
moreArtifacts: '+{{n}} more',
3941+
verifying: 'Checking the change…',
3942+
verifyStep: 'step {{n}}',
3943+
verified: 'Checked the change',
3944+
unknownPhase: 'Unknown build phase',
39383945
},
39393946
},
39403947
chatbotError: {

‎packages/i18n/src/locales/es.ts‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3382,6 +3382,10 @@ const es = {
33823382
seed: "Datos de ejemplo",
33833383
},
33843384
moreArtifacts: "+{{n}} más",
3385+
verifying: "Comprobando el cambio…",
3386+
verifyStep: "paso {{n}}",
3387+
verified: "Cambio comprobado",
3388+
unknownPhase: "Fase de creación desconocida",
33853389
},
33863390
},
33873391
chatbotError: {

‎packages/i18n/src/locales/fr.ts‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3379,6 +3379,10 @@ const fr = {
33793379
seed: "Données d’exemple",
33803380
},
33813381
moreArtifacts: "+{{n}} autres",
3382+
verifying: "Vérification de la modification…",
3383+
verifyStep: "étape {{n}}",
3384+
verified: "Modification vérifiée",
3385+
unknownPhase: "Phase de création inconnue",
33823386
},
33833387
},
33843388
chatbotError: {

‎packages/i18n/src/locales/ja.ts‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3319,6 +3319,10 @@ const ja = {
33193319
seed: "サンプルデータ",
33203320
},
33213321
moreArtifacts: "他 {{n}} 件",
3322+
verifying: "変更を確認しています…",
3323+
verifyStep: "ステップ {{n}}",
3324+
verified: "変更を確認しました",
3325+
unknownPhase: "不明なビルドフェーズ",
33223326
},
33233327
},
33243328
chatbotError: {

‎packages/i18n/src/locales/ko.ts‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3316,6 +3316,10 @@ const ko = {
33163316
seed: "샘플 데이터",
33173317
},
33183318
moreArtifacts: "외 {{n}}개",
3319+
verifying: "변경 사항 확인 중…",
3320+
verifyStep: "{{n}}단계",
3321+
verified: "변경 사항 확인 완료",
3322+
unknownPhase: "알 수 없는 빌드 단계",
33193323
},
33203324
},
33213325
chatbotError: {

‎packages/i18n/src/locales/pt.ts‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3377,6 +3377,10 @@ const pt = {
33773377
seed: "Dados de exemplo",
33783378
},
33793379
moreArtifacts: "+{{n}} mais",
3380+
verifying: "Verificando a alteração…",
3381+
verifyStep: "etapa {{n}}",
3382+
verified: "Alteração verificada",
3383+
unknownPhase: "Fase de criação desconhecida",
33803384
},
33813385
},
33823386
chatbotError: {

‎packages/i18n/src/locales/ru.ts‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3463,6 +3463,10 @@ const ru = {
34633463
seed: "Демоданные",
34643464
},
34653465
moreArtifacts: "ещё {{n}}",
3466+
verifying: "Проверка изменения…",
3467+
verifyStep: "шаг {{n}}",
3468+
verified: "Изменение проверено",
3469+
unknownPhase: "Неизвестный этап сборки",
34663470
},
34673471
},
34683472
chatbotError: {

0 commit comments

Comments
 (0)