Skip to content

Bind the in-app assistant dock's build thread to the current app (reverses ADR-0057 A1.b per maintainer ruling) #10926

Closed

Description

@hotlong

Source

objectui#10899 item 4 (epic objectstack-ai/cloud#2440). When the maker opens the in-app assistant inside app 「客户管理」, the dock's build header chip reads 「构建 · 新建应用」. The dock uses the app-less, product-only build scope and sends no packageId, so the agent has to infer which app to edit.

The PR #10924 dev root-caused it and deferred it because it reverses ADR-0057 Amendment A1.b.

Maintainer ruling (epic session, 2026-09-28, verbatim)

「绑定当前应用(推荐)」

As presented: inside an authorable app (package not com.objectstack.*), when the resolved agent is build, the dock binds its build thread to that app. That means editPackageId is the app's package and the scope is app:PKG:build.

  • The chip, the empty state and the agent context name the app.
  • The dock, /ai/build?package=PKG and the Studio copilot share one thread; Maximize goes to /ai/build?package=PKG.
  • ask stays ambient.
  • Existing ambient build threads stay reachable in the /ai sidebar.

Delivery shape

  1. ADR amendment. An amendment to docs/adr/0057-console-ai-chat-one-conversation-docked.md records the reversal of the A1.b "dock keeps the legacy product-only key" line, citing this ruling.
    • docs/adr/** is a governed surface, so it is its own draft PR that the maintainer merges.
    • Do not mix it into the code PR.
  2. Code PR. Implements the binding.
    • Reuse editPackageId / chatConversationScope; add no new surface.
    • Tests pin the chip text inside an app, the scope key, thread sharing with /ai/build?package=, and ask staying ambient.

Acceptance

  1. Inside app X, the dock's build chip names X, and the build request carries X's package id.
  2. Opening /ai/build?package=X shows the same thread.
  3. Outside any authorable app, behaviour is unchanged.

Activity

  1. added
    domain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seat
    on Sep 28, 2026
  2. objectstack-fleet commented on Sep 28, 2026

    @objectstack-fleet
    Contributor

    Claim: PM loop round 2
    Session: session_015AUunPkX7UTkCH9e7AdZo1
    Account: os-zhuang (the seat's linked user as GET /user answers it; the maintainer authorised this seat to run on it, verbatim 「允许你用当前账户继续开发」, seat-post marker 5864093687)
    Branch: claude/issue-10926-dock-binds-app
    Worktree: objectui-issue-10926
    Domain: domain:ui
    Seat: domain:ui#4
    File surface: code PR on the branch above: packages/app-shell/src/layout/ChatDock.tsx, packages/app-shell/src/hooks/chatScope.ts and, where the thread sharing needs it, hooks/useChatConversation.ts and console/ai/AiChatPage.tsx (the build-thread scope and ?package= path only), plus tests beside each, the chip copy in packages/i18n/src/locales/*.ts if it changes, and one .changeset/10926-*.md. ADR PR, separate, on claude/issue-10926-adr-0057-dock-binding: docs/adr/0057-console-ai-chat-one-conversation-docked.md only (governed, Tier H: it stays draft for the maintainer). Stop on breach; explain in the report.
    Container & model: M, mode:subagent, model: opus (default judgement tier; dispatch-gates --tier --repo objectstack-ai/objectui on these paths: no path-derived mandate)
    Clause-②: no
    Thread-read: none
    Serial constraints cleared: read at 2026-09-28T09:10Z against objectui main 1dae95a, covering the 19 open PRs' files and the claims on the lane's open pm:dispatched cards. objectui#10900 (seat 1, os-steve, claim 5866735286) holds the Build Doctor button and drawer title in console/ai/AiChatPage.tsx. That is a different region of that file: this card touches only the build-thread scope there, if anything. Merge main before opening the PR; the later lander resolves any textual conflict. PR objectui#10924 (epic objectui#10899) holds plugin-chatbot/src/ChatbotEnhanced.tsx, which this card does not touch.

    Take order: p1. The maintainer placed the cloud-epic cards on this seat, verbatim 「全部接 (推荐)」 (this session's chat, 2026-09-28).

    Ruling: the maintainer ruling is verbatim in the card body, 「绑定当前应用(推荐)」 (epic session, 2026-09-28), with its stated terms. No separate ruling comment exists.

    Clause-② reasoning: the card says to reuse editPackageId / chatConversationScope and add no new surface. Neither symbol's export changes, and no published accept set moves. The ADR amendment is governed rule text: it gets an at-tier contract review and the maintainer's merge regardless.

    Premise re-read: docs/adr/0057-console-ai-chat-one-conversation-docked.md L334–346, A1.b ("Shipped (#2466)"): "the legacy product-only key is not cleared (dock/FAB and bare /ai/build keep resolving through it)". The ruling reverses that clause for the dock inside an authorable app.


    Generated by Claude Code

  3. objectstack-fleet commented on Sep 28, 2026

    @objectstack-fleet
    Contributor

    os-dev-report

    {
      "issue": 10926,
      "status": "done",
      "branch": "claude/issue-10926-dock-binds-app",
      "pr": "https://github.com/objectstack-ai/objectui/pull/10950",
      "session": "session_015AUunPkX7UTkCH9e7AdZo1 — this run's harness-stamped id (mode:subagent, the parent seat's; container CLAUDE_CODE_REMOTE_SESSION_ID cse_015AUunPkX7UTkCH9e7AdZo1)",
      "premise_still_valid": true,
      "summary": "Code PR #10950 (draft, Fixes #10926): inside an authorable app (package not com.objectstack.*, the A1.b switcher's isPlatformBuiltinApp), a dock resolved to build passes the app's package as editPackageId, so the scope is app:PKG:build (Studio copilot and /ai/build?package=PKG share it), the chip, the edit-mode empty state and context.packageId name the app, and Maximize opens /ai/build?package=PKG with the Studio door's one-shot opt-out. ask, built-in apps and no app keep the product-only key; the dock runs the same A1.b migration read as the ?package= entry (predicate extracted as isThreadBoundToPackage) and hands its pane only a scope-matched conversation. ADR PR #10947 (draft, governed, Part of #10926) adds ADR-0057 Amendment A2 quoting the ruling verbatim and reversing only the dock half of A1.b's product-only-key clause. Card premise re-verified on base af2221d: ChatDock passed appId undefined and no packageId.",
      "prs": {
        "code": { "url": "https://github.com/objectstack-ai/objectui/pull/10950", "branch": "claude/issue-10926-dock-binds-app", "head": "8d4efd6", "draft": true, "first_line": "Fixes #10926", "assignee": "os-zhuang", "governed": "NOT GOVERNED" },
        "adr": { "url": "https://github.com/objectstack-ai/objectui/pull/10947", "branch": "claude/issue-10926-adr-0057-dock-binding", "head": "4a66540", "draft": true, "first_line": "Part of #10926", "assignee": "os-zhuang", "governed": "GOVERNED (stays draft for the maintainer)" }
      },
      "files_changed": {
        "code_pr_10950": [
          ".changeset/10926-dock-binds-build-thread-to-app.md",
          "packages/app-shell/src/console/ai/AiChatPage.tsx",
          "packages/app-shell/src/hooks/chatScope.ts",
          "packages/app-shell/src/layout/ChatDock.tsx",
          "packages/app-shell/src/layout/ConsoleLayout.tsx",
          "packages/app-shell/src/layout/__tests__/ChatDock.appBinding-10926.test.tsx",
          "packages/app-shell/src/layout/__tests__/ConsoleLayout.dockBinding-10926.test.tsx"
        ],
        "adr_pr_10947": ["docs/adr/0057-console-ai-chat-one-conversation-docked.md"]
      },
      "tests": "Code head 8d4efd6 (main 5c94589 merged): dep closure turbo build --filter=@object-ui/app-shell^... 28/28 successful; pnpm --filter @object-ui/app-shell type-check (tsc --noEmit && tsc -p tsconfig.test.json) exit 0, both new test files in the test program per --listFilesOnly; pnpm exec vitest run --maxWorkers=2 over layout/__tests__, console/ai/__tests__, console/__tests__, views/studio-design/__tests__, chrome, hooks/__tests__/{chatScope,useChatConversation,surfaceAgent} and two src/__tests__ pins: Test Files 102 passed (102), Tests 750 passed (750), exit 0. New: ChatDock.appBinding-10926 (11 tests, real dock body + ChatPane + useChatConversation + AiChatPage over a fetch stub) and ConsoleLayout.dockBinding-10926 (3 tests). Full 844-file app-shell suite not run locally (CI). Ablations, each committed first, mutated via objectstack scripts/ablation-replace.mjs with counts registered before the run, restore proven blob == HEAD and git diff HEAD empty, no dist in the path (relative imports): (1) binding off, anchor product === 'build' && appPackageId: expected 8 failed / 3 passed, observed 8 failed / 3 passed; an earlier attempt was refused by the tool (replacement contained the anchor) and ran nothing; (2) scope gate off: expected 1/10, observed 1 failed / 10 passed; (3) ConsoleLayout bound-maximize branch off: expected 1/2, observed 1 failed / 2 passed.",
      "gates": {
        "code_pr_10950_head_8d4efd6": {
          "check-changeset-presence": 0,
          "check-changeset-no-major": 0,
          "check-governed-queue-guard --test (7 paths)": "0 NOT GOVERNED",
          "check:new-line-citations": 0,
          "check:control-bytes": 0,
          "check:vi-mock-specifiers": 0,
          "check:vi-mock-inherit": 0,
          "check:vi-mock-override-shape": 0,
          "check:changeset-claims": 0,
          "check:pending-changeset-literals": 0,
          "check:i18n-keys": 0,
          "check:test-path-roots": 0,
          "check:unreferenced-sources": 0,
          "check:self-import": 0,
          "check:phantom-deps": 0,
          "app-shell type-check": 0,
          "eslint --no-inline-config on 6 changed TS/TSX files": "0 (0 errors; population = eslint.config.js **/*.{ts,tsx}; file count 6 from --format json; no parserOptions.project/projectService and the one custom rule reads no files, so untouched verdicts cannot move; vs base: +1 react-refresh/only-export-components warning for the new exported predicate, 12 of that class already in AiChatPage.tsx, no warning ratchet)",
          "check:i18n-drift / check:i18n-dead-keys": "not run: no locale file or key moved"
        },
        "adr_pr_10947_head_4a66540": {
          "check-governed-queue-guard --test docs/adr/0057-...md": "3 GOVERNED",
          "check-changeset-presence": "0 (no changeset owed)",
          "check-new-cross-file-line-citations": 0,
          "check-control-bytes": 0,
          "check:doc-snippet-types": "not run: reads code fences under docs/adr, and the diff adds none"
        },
        "ci_at_report": "code 8d4efd6: 42 check runs, 23 success, 3 skipped, 16 in_progress; adr 4a66540: 39 check runs, 36 success, 3 skipped. PM owns convergence."
      },
      "deviations": [
        "Claim file surface breached by one file: packages/app-shell/src/layout/ConsoleLayout.tsx (two appPackageId prop lines + the maximize target) plus its test ConsoleLayout.dockBinding-10926.test.tsx. The surface was derived from the Zone 2 assumption that editPackageId is read in ChatDock.tsx; measured on af2221d it was not (ChatDock passed appId undefined), and the current app (activeApp) and the maximize navigation (openDockFullPage) exist only in ConsoleLayout.tsx. Conflict named, not silently resolved: the claim says stop on breach; os-dev.md says a falsified mechanism assumption changes route per the ruling's intent, and os-dev.md wins on conflict. Overlap measured: PR #10924 (since landed) touched a different hunk of ConsoleLayout.tsx (the FAB line); main merged twice (7e8b3c0, 5c94589), both clean.",
        "Beyond Studio-copilot parity, the dock also runs the A1.b migration read (legacyScope build + adoptLegacy); without it a dock that resolves first would mint app:PKG:build and pre-empt the ?package= entry's adoption of a product-only thread bound to PKG, silencing a shipped A1.b behaviour. Predicate extracted in AiChatPage.tsx (build-thread-scope region only; the Build Doctor region #10900 holds is untouched).",
        "Commit trailers are the model-free pair objectui AGENTS.md requires (Claude-Session + Co-authored-by: Claude); the harness reminder's model-named form was not used, its precedence sentence yields to AGENTS.md.",
        "Zone 2 reading 'A1.b at L334-346' confirmed by content; no line address is cited in the ADR text (AGENTS.md #11)."
      ],
      "mcp_calls": "0 — no MCP GitHub tool was called",
      "api_writes": "5 — all via objectstack scripts/pm/fleet-write relay (POST /repos/objectstack-ai/objectstack/dispatches, executed as objectstack-fleet[bot]): pr_create → POST /repos/objectstack-ai/objectui/pulls (#10947); pr_create → POST /repos/objectstack-ai/objectui/pulls (#10950); label-write assign → POST /repos/objectstack-ai/objectui/issues/10950/assignees; label-write assign → POST /repos/objectstack-ai/objectui/issues/10947/assignees; comment → POST /repos/objectstack-ai/objectui/issues/10926/comments (this report). git push to both branches is not REST.",
      "open_questions": [],
      "out_of_scope_findings": [
        "carrier: none (承接者:无) · noted in PR #10950 Acceptance notes, not filed · isPlatformBuiltinApp (the ruling's authorable test, shared with the A1.b switcher) does not exclude the DB-authored sys_metadata pseudo-package that appRoute.ts studioPackageId refuses; an app list item carrying _packageId sys_metadata would bind to app:sys_metadata:build and send packageId sys_metadata. Read-only inference, no reach measured · dedupe words: sys_metadata authorable isPlatformBuiltinApp build thread"
      ],
      "cleanup": "both worktrees removed after node_modules deletion; private refs refs/issue-10926/* deleted; scratch files holding PR bodies deleted"
    }

    Generated by Claude Code

  4. objectstack-fleet commented on Sep 28, 2026

    @objectstack-fleet
    Contributor

    File-surface supplement to the claim 5866972381, same session, same branches, at 2026-09-28T10:23Z. ⛔ Not a second claim. It also corrects this seat in the open.

    • Added: packages/app-shell/src/layout/ConsoleLayout.tsx (the appPackageId hand-off to the dock and the Maximize target) and its test packages/app-shell/src/layout/__tests__/ConsoleLayout.dockBinding-10926.test.tsx.
    • The seat's assumption was wrong. The dispatch's Zone 2 said editPackageId is read in layout/ChatDock.tsx. Measured by the dev on objectui af2221d: ChatDock passed appId undefined and no package. The current app (activeApp) and the maximize navigation (openDockFullPage) exist only in ConsoleLayout.tsx. The dev changed route under the ruling's intent and declared the breach in its report, which is the right call. The file surface is corrected here, not in the dev's favour after the fact.
    • Serial check (2026-09-28T10:22Z, objectui main): of 10 open PRs and the claims on the lane's 18 pm:dispatched cards, only this card's own PR feat(app-shell): the console dock binds its build thread to the current authorable app (objectui#10926) #10950 touches ConsoleLayout.tsx. PR objectui#10924, which touched a different hunk of it, has merged.

    Generated by Claude Code

  5. objectstack-fleet commented on Sep 28, 2026

    @objectstack-fleet
    Contributor

    Review conclusion — ADR half, PR #10947 @ 4a66540 (governed, Tier H): PASS, awaiting the maintainer

    domain:ui seat 4, session_015AUunPkX7UTkCH9e7AdZo1, at 2026-09-28T10:38Z. ⛔ Not an approval, and not the ACCEPT for the code half.

    • Form: draft, one file, docs/adr/0057-console-ai-chat-one-conversation-docked.md, +64/−0. The body's first line is Part of #10926, with no closing keyword; the code PR feat(app-shell): the console dock binds its build thread to the current authorable app (objectui#10926) #10950 carries Fixes #10926. No changeset is owed (docs/adr/** is outside the guarded set).
    • CI on the head: 39 check-runs, 36 success and 3 skipped, none failed. mergeable_state: clean.
    • Contract review: PASS at CONTRACT_REVIEW_TIER, 5868230570.
    • Escalated open point, carried to the maintainer digest: the authorable test isPlatformBuiltinApp (a com.objectstack. prefix check) does not exclude the DB-authored sys_metadata pseudo-package that appRoute.ts's studioPackageId refuses. It is the same function the A1.b switcher already uses, so the dock inherits an existing gap and adds no new one. Reach is unmeasured. The seat does not hold the ADR on it.
    • Governed finish: needs-user-decision on the PR, the final maintainer digest (维护者速读) on the PR, and review requested from os-zhuang and hotlong. The digest's button label is corrected to 「以完整页面打开」, the zh string of console.ai.dock.maximize.
    • Order: the seat holds the code PR feat(app-shell): the console dock binds its build thread to the current authorable app (objectui#10926) #10950 out of the merge queue until this ADR PR merges, so the recorded decision lands first. The code half's ACCEPT follows its own contract review.

    Generated by Claude Code

  6. objectstack-fleet commented on Sep 28, 2026

    @objectstack-fleet
    Contributor

    ACCEPT — code half, PR #10950 @ 8d4efd6 — held until the ADR PR #10947 merges

    domain:ui seat 4, session_015AUunPkX7UTkCH9e7AdZo1, at 2026-09-28T10:41Z. Checked against GitHub and origin/main, not against the report.

    • Form: draft, base main, body first line Fixes #10926. 7 files, +710/−39: ChatDock.tsx, ConsoleLayout.tsx, AiChatPage.tsx, chatScope.ts (documentation only), two pins, and .changeset/10926-dock-binds-build-thread-to-app.md. All are inside the claim's surface as supplemented in 5868060731. Nothing under content/docs/releases/.
    • CI on the head 8d4efd6e40: 43 check-runs, 40 success and 3 skipped, none failed. mergeable_state: clean. Governed-surface guard (scripts/check-governed-queue-guard.mjs --test, 7 paths): NOT GOVERNED.
    • Contract review: PASS at CONTRACT_REVIEW_TIER on this head, 5868286370. Each ruling term and each Amendment A2 bullet is judged right, and every factual sentence of the changeset is true. @object-ui/app-shell minor matches a behaviour addition with no entry export, removal or rename. Clause-②: no holds.
    • Spot readings (seat's own): ChatDock.tsx sets editPackageId only when the product is build, appPackageId is set and !isPlatformBuiltinApp({ _packageId: appPackageId }). It keys chatConversationScope({ appId: editPackageId, product }). The legacy read (legacyScope: product, adoptLegacy through the shared isThreadBoundToPackage) runs only when bound. scopeMatched keeps the previous app's thread off the pane after an app switch. Acceptance items 1 to 4 are each pinned in ChatDock.appBinding-10926.test.tsx.
    • Escalated, not decided (to the maintainer):
    • Landing order: the ADR goes first. The seat holds this PR out of the merge queue until PR docs(adr): ADR-0057 Amendment A2 — the dock binds its build thread to the current app (objectui#10926) #10947 (governed, Tier H, awaiting the maintainer) merges. Reasons:
      • If the code landed first, main's A1.b clause would contradict the shipped code between the two merges.
      • Fixes #10926 here would close the card while its governed half is still open.
      • If Amendment A2's text changes before it merges, item ③-2 of the contract review (the dock's migration read) needs re-review first.

    Next: when #10947 merges, ready → auto-merge (merge queue), followed to MERGED by this seat.


    Generated by Claude Code

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

Metadata

Metadata

Assignees

Labels

domain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatpriority:p1

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions