Skip to content

finding(objectui chatbot): detectBuiltAppPackage reads any drafted[] carrying a type:'app' entry as a whole-app build — now also true of an incremental apply_edit that stages the app artifact; the envelope's kind:'edit' is the disambiguator #15138

Description

@baozhoutao

Seam card filed by the repo:cloud PM seat (objectstack#6026, session session_01EK4Q5Nrx779cxjdeTxsK7P) — 2026-09-04T03:1xZ. Named reader: the objectui execution seat (domain:ui), at candidate selection. ⛔ Not the cloud seat's lane to implement; objectui is not writable from that session.

What changed on the producer side

cloud PR #1960 (cloud#1952, ACCEPTed, landing) makes apply_edit — ADR-0027 D3's structured-diff editor — emit drafted[] on its status: 'drafted' envelope, alongside its existing changedArtifacts. Until now only apply_blueprint emitted drafted[]. The change is additive and honest: drafted[] lists exactly what was staged.

The heuristic this collides with

packages/plugin-chatbot/src/mapMessages.ts at 045d20ba (cloud's pinned .objectui-sha), detectBuiltAppPackage, :470–477:

if (obj.status !== 'drafted' && obj.status !== 'published') return undefined;

const drafted = (obj as { drafted?: unknown }).drafted;
 Array.isArray(drafted) && drafted.some((d) =>  (d as { type?: unknown }).type === 'app')

"Did this result finish a whole-app build?" is answered by "does drafted[] contain an app entry". That was exact while apply_blueprint was the only producer. An apply_edit with an add_object op stages the app artifact too (the nav merge), so after cloud PR #1960 such an edit satisfies the heuristic and the chat surface reads it as a built-app moment.

Why the producer did not paper over it

Truncating the app entry out of drafted[] to steer this heuristic was considered and rejected on the cloud side: it would be a lie in the envelope about what was staged, and two consumers (this module, and cloud's own build-debug reconciler at packages/service-ai/src/debug/reconcile.ts) read drafted[] as the ground truth of the staged set. The envelope already carries the field that distinguishes the two cases: kind: 'edit' on apply_edit, absent on apply_blueprint. The consumer should key its whole-app test on that, not on the presence of an app entry.

Suggested shape (input, not a ruling)

detectBuiltAppPackage returns undefined when obj.kind === 'edit', before the drafted[] scan. One guard, no vocabulary change, and detectDraftResult (which is what should render an incremental edit — its own comments say incremental edits "keep their draft card") is unaffected.

Consequence until this lands

An apply_edit that adds an object reads as a built-app moment in the chat. Presentation-class, bounded to edits that stage the app artifact, and accepted on the cloud side as the cost of restoring the draft card and one-click publish for the main multi-artifact path (cloud#1952).

Re-check

mapMessages.tsdetectBuiltAppPackage (the drafted.some(type === 'app') test) and detectDraftResult (the two comments about incremental edits keeping their card). cloud side: packages/service-ai-studio/src/tools/metadata-tools.ts, the apply_edit envelope (status: 'drafted', kind: 'edit', drafted: …). Reproduce: an apply_edit with an add_object op against an app that has a nav; observe detectBuiltAppPackage matching.

Related: cloud#1952 · cloud PR #1960.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions