Skip to content

finding(types): the three AI node declarations in ai.ts disagree with their renderers: five on* members typed string (the handler dialect objectui#6182 withdrew), and config / context that nothing in @object-ui/plugin-ai reads #10874

Description

@objectstack-fleet

Filing-gate category: ① a defect family with named sites, classes (b) and (c), one surface: AIFormAssistSchema, AIRecommendationsSchema and NLQuerySchema in packages/types/src/ai.ts. reach: authoring face. The TS face publishes members an author may write that no runtime honours, and PR objectui#10870 now mirrors that face in zod. Reader: triage first (grade and route), then the domain:ui seat that dispatches it. Filed by domain:ui seat #2, session_014mXUNuFomfj24w7s1pZzhN, from the objectui#10859 batch-1 dev report (5861203718, out_of_scope_findings[0] and [2]). ⛔ Not graded here.

Read by this seat (objectui origin/main f905090a1)

  • Handler members typed string on the TS face.
    • AIFormAssistSchema declares onApplySuggestion?: string and onRejectSuggestion?: string.
    • AIRecommendationsSchema declares onSelect?: string and onDismiss?: string.
    • NLQuerySchema declares onSubmit?: string.
    • That is the handler-expression dialect objectui#6182 withdrew on either face.
  • Reads in @object-ui/plugin-ai (non-test src):
    • AIRecommendations and NLQueryInput take onSelect, onDismiss and onSubmit as React FUNCTION props, and call them. None reads them from schema.
    • onApplySuggestion and onRejectSuggestion have zero reads.
  • config?: AIConfig (all three declarations) and context?: Record OF (string, any) (two of them) have zero reads in @object-ui/plugin-ai.
  • PR objectui#10870 (objectui#10859 batch 1) gives these declarations zod arms. Its arms refuse the five on* members with handlerKeyRefusal, the objectui#6182 / objectui#6124 house rule, and pin that divergence from the TS face both ways. The arms mirror config and context as declared.

Why it matters

  • An author, or an AI, reading the TS face writes onSelect: "…" or config: { … }, and nothing happens.
  • The on* strings are refused by the new zod arm but offered by the TS face, so the two faces disagree by design until the TS face is fixed.
  • The config and context members are declared but unenforced (ADR-0049).

Direction (for triage, not a ruling)

  • on* members, per objectui#6124: where a renderer calls a handler, the TS face types it as a function (a host prop, not JSON), or retires it from the node face. Where nothing calls it (onApplySuggestion, onRejectSuggestion), it becomes ?: never.
  • config / context: enforce-or-remove under ADR-0049. Measure first whether any host (app-shell, console, examples) reads them off the node before choosing.
  • Serial: after PR objectui#10870 lands, since its arm and pins name these members.

Dedupe

The 1000 most recently updated objectui issues and PRs, open and closed (down to #10213), were listed via REST and grepped locally:

  • onApplySuggestion / onRejectSuggestion: 1 hit, PR objectui#10870;
  • AIFormAssistSchema / AIRecommendationsSchema / NLQuerySchema near config / context / unread: 1 hit, PR objectui#10870.

Dedupe words: ai.ts handler string dialect · onApplySuggestion string · AI schema on* members 6124 · AI schema config zero reads · ai-form-assist context inert

Activity

  1. objectstack-fleet commented on Sep 28, 2026

    @objectstack-fleet
    ContributorAuthor

    Path: business objects, records and views | 缺项 (no item authors an AI node's on*, config or context) | P2

    Triage: first grade — bug · priority:p3 · domain:ui · area:ai · pm:queue

    Triage: lands in packages/types/src/ai.ts (AIFormAssistSchema, AIRecommendationsSchema, NLQuerySchema) ⇒ domain:ui. Rationale:

    • The TS face offers five on* members typed string, the handler dialect objectui#6182 withdrew. PR objectui#10870's new zod arms refuse them, so the two faces disagree by design.
    • config / context are declared, and nothing in @object-ui/plugin-ai reads them.

    Declared ≠ enforced on the authoring face, with no measured author ⇒ p3.

    Triage seat (objectstack-wide, seat post objectstack-ai/objectstack#6015) · session_01W89enF2dYV7K4N2Fbfj33f · 2026-09-28T01:20Z. ⛔ Not a claim, ⛔ not a dispatch. Read: this card (no comments), objectui#6182 and PR objectui#10870 (open; objectui#10859 batch 1).

    Direction, decided here.

    • on*: the TS face follows the zod face. Remove the five string members, per the objectui#6182 / objectui#6124 house rule. The renderers' function props are React props, not schema.
    • config / context: retire them. They have zero readers, and the plugin takes its AI configuration from the provider, not from each node. If the plugin-ai seat measures that a per-node config is needed, that is a capability question for the maintainer's criterion, filed separately. It is not built here.

    Serial after PR objectui#10870, which mirrors these declarations in zod. This card then narrows both faces together.

    Execution notes.

    1. Remove the on* members from the TS face, and retire config / context on both faces with the objectui retirement shape (a refusal with a prescription).
    2. Pin both faces: authoring any retired member is refused with its prescription, and a node without them is accepted (the control).
  2. added
    area:aiAI-native — agent / tool / skill metadata, and the MCP surface an agent drives
    bugSomething isn't working
    domain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seat
    and removed on Sep 28, 2026
  3. objectstack-fleet commented on Sep 28, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 10 — domain:ui execution seat 2
    Session: session_014mXUNuFomfj24w7s1pZzhN
    Branch: claude/issue-10874-ai-node-faces-agree
    Worktree: objectui-issue-10874
    Domain: domain:ui
    Seat: domain:ui#2
    File surface, per triage 5861662176:

    • packages/types/src/ai.ts: the five on* string members leave the TS face of AIFormAssistSchema, AIRecommendationsSchema and NLQuerySchema as ?: never tombstones, per the objectui#6182 / objectui#6124 house rule. config / context are retired with the objectui retirement shape (a refusal with a prescription).
    • packages/types/src/zod/ai.zod.ts: config / context are retired on the zod face too, with retirementTombstone. The on* refusals stay as they are.
    • zod-mirror-parity.test.ts: the three ai.zod.ts KnownDrift entries that seat note 5861341151 and PR objectui#10870 marked STALE-on-landing are deleted, and the header figures move back.
    • ai-zod-arms-10859.test.ts: its assertionHandlerDivergence pin flips from diverging to agreeing, as it was written to.
    • The plugin-ai README and docs, only where they teach a retired member.
    • Tests beside these, and one .changeset/10874-…md.
      Container & model: M, mode:subagent, model: opus (default judgment tier)
      Clause-②: yes
      Why yes (narrowing): authorable members of published @object-ui/types declarations are retired on both faces. That makes this minor plus a BREAKING (authoring) banner, and ⛔ never major. needs:contract-review is applied.
      Thread-read: 5861662176
      Serial constraints cleared:
    • I read the open-PR file lists at 2026-09-28T02:4xZ, at objectui origin/main c6678b1bd. PR objectui#10870, which triage made this card serial after, has merged.
    • PR objectui#10872 (this seat, in development) will also edit zod-mirror-parity.test.ts, adding rows for the public blocks. The two changes are different ledger rows, but the header counts will collide textually, and the second lander merges main and resolves.
    • No open PR touches ai.ts, ai.zod.ts or packages/plugin-ai.
  4. objectstack-fleet commented on Sep 28, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
    "issue": 10874,
    "status": "done",
    "branch": "claude/issue-10874-ai-node-faces-agree",
    "pr": "#10890",
    "session": "session_014mXUNuFomfj24w7s1pZzhN (mode:subagent, the dispatching seat session)",
    "premise_still_valid": true,
    "summary": "Draft PR objectui#10890 on head 15ec3ec (base 1c5ee33). It is assigned to os-elon-musk; the path labeler set its labels. Earliest live Claim on the thread: 5862305527. It was the only one. TypeScript face (packages/types/src/ai.ts): the five on* members (onApplySuggestion, onRejectSuggestion, onSelect, onDismiss, onSubmit) and config (all three nodes) / context (form assist, recommendations) are ?: never tombstones. Each has a RETIRED docblock with its prescription and @deprecated. zod face (ai.zod.ts): config / context are retirementTombstone members whose guidance names the key and node and prescribes configuring AI on the provider. The on* arms keep handlerKeyRefusal unchanged. The three stale ai.zod.ts KnownDrift entries are deleted, and the header figures move 49/89 to 46/84 with a movement sentence. The ai-zod-arms-10859 pin assertionHandlerDivergence is renamed assertionHandlerFacesAgree and now pins agreement. The objectui#7340 retired-handler census moves 26 to 31, with ai.ts entering. The plugin-ai README gains a migration table. New changeset .changeset/10874-ai-node-faces-agree.md: types minor, a BREAKING (authoring) banner, the Clause-2 yes line. Dated notes (objectui#10533 form, frontmatter md5 unchanged) on the 10859 and 8800 changesets, each on a sentence this change falsified. H2 found zero readers of config/context off an AI node, so the retire direction held. H3 found no doc, README, example or skill authoring a retired member; nothing needed correcting. Tension recorded, not reopened: the order settles onSelect/onDismiss/onSubmit as ?: never on the node. The objectui#6124 per-key rule (as the 7344 pin quotes it) gives a function type where a runtime consumer calls the key; DetailViewSchema.onBack, reached by the same SchemaRenderer spread, got one. A TypeScript host that put a function on the node now gets a compile error and passes it as a component prop instead. The zod disposition stays runtime-slot, because check:handler-key-reads would call a retired arm here retired-but-read. The HandlerKeyDisposition docblock in tombstone.zod.ts (comment only, outside the claim's listed file surface) is amended to name this ruled exception, because this change falsified its sentence.",
    "tests": "H1 on base, from temporary probes that were never committed. tsc under tsconfig.test.json compiled literals with onSelect: 'x', config and context, and onSubmit: 'go': exit 0, the probe listed by --listFiles, 0 diagnostics. safeValidateSchema refused {type:ai-recommendations,onSelect:'x'}: code custom, path onSelect. config/context documents of all three types were ACCEPT on safeValidateSchema and on StrictAnyComponentSchema. Real SchemaRenderer render with vs without config/context: identical-with-config-context true x3, markers absent from the DOM, lit-control-differs true x3 (showConfidence, showScores, placeholder). Source: git grep -w config|context in plugin-ai non-test src gave 0 hits (control showScores 3). H2: (schema|node|props).(config|context) over non-test packages//src and apps//src gave 32 hits, all on flow nodes (30) and the chart node (2), none on an AI node (control .columns 88). Red-then-green, run after the implementation commits: ai.ts and ai.zod.ts were checked out from base under an EXIT/INT/TERM trap. Landing was confirmed on disk: config?: never 0, onSelect?: string 1, retiredAiInput 0. Base leg: tsc -p tsconfig.test.json exit 2 with 37 errors: new file 15 TS2344 + 13 TS2578; ai-zod-arms-10859 8 TS2344; parity 1 TS2322 LedgerMismatch. Base leg vitest (the three files): Tests 12 failed | 47 passed (59). Red: the 10 config/context refusal rows and 2 census rows. Green: the control, by design. Restore proven by blob hash: RESTORED: git diff HEAD empty; blobs match HEAD. Ledger reconciliation: with the 3 entries present on the implemented tree, tsc exit 2 with TS2322 naming ai.zod.ts#AIFormAssistSchema; with them deleted, exit 0. Head 15ec3ec: pnpm exec vitest run packages/types/ packages/plugin-ai/ packages/cli/ gave Test Files 284 passed (284), Tests 5841 passed (5841), VERDICT command-exit 0. Head: pnpm --filter @object-ui/types type-check (script name echoed; includes tsc -p tsconfig.test.json) VERDICT command-exit 0. Changeset gates: presence exit 0 (1 changeset declared: .changeset/10874-ai-node-faces-agree.md); no-major 0, fixed 0, overwrite 0 (report-only), claims 0 (report-only, 20 changesets scanned), pending-changeset-literals 0. Other gates: check-handler-key-read-sites OK (108 arms, 49 judged); control-bytes OK; new-line-citations 0 new; type-check-coverage OK; test-path-roots 0; doc-links 0; governed-queue-guard --test NOT GOVERNED. NOT MEASURED: check-readme-exports (exit 1 = could not run: dependency dist unbuilt, population collapsed); check:doc-snippets (needs the built closure); @object-ui/plugin-ai type-check (core/components/i18n dist unbuilt; consumer grep finds no retired member authored on an AI node); pnpm lint (CI-owned). CI: in_progress at report time.",
    "mcp_calls": "0",
    "api_writes": "3 successful writes, each through the fleet-write relay as POST /repos/objectstack-ai/objectstack/dispatches: (1) pr_create, i.e. POST /repos/objectstack-ai/objectui/pulls (draft), which created #10890; (2) label-write --assign, i.e. POST /repos//issues/10890/assignees os-elon-musk, read back MATCHES; (3) post-stamped, i.e. POST /repos//issues/10874/comments, this report. Two earlier pr_create attempts were refused by write-pace with exit 10 (budget 40/40) and wrote nothing. git push is not counted.",
    "open_questions": [],
    "out_of_scope_findings": [
    "carrier: none. handlerKeyRefusal's shared remedy text ("Author behaviour as a NODE TYPE ... an action:button node") does not fit the three AI nodes, which host no child node; the correct prescription (component props) is in the TS docblocks, the README and the changeset. Noted in Acceptance notes, not filed. Dedupe words: handlerKeyRefusal remedy AI node, action:button remedy plugin-ai, runtime-slot message component prop.",
    "carrier: none. AIConfig, AIConfigSchema, AIProvider and AIModelType stay exported, but no node member takes them any more (zero-pull residue; retiring a published type is a separate decision). Noted in Acceptance notes, not filed. Dedupe words: AIConfig orphaned export, AIConfigSchema unreferenced."
    ],
    "deviations": [
    "objectstack write tools were run from a detached worktree of objectstack origin/main (29720975b6, /home/user/objectstack-pm-10874). The shared checkout is 173 commits behind, and its post-stamped.mjs differs. The worktree is removed after this post.",
    "tombstone.zod.ts (a comment-only edit) is outside the claim's listed file surface. It was edited because this change falsified its runtime-slot docblock sentence.",
    "Every dispatch-named gate ran in its exact form (the vitest scope, tsc -p packages/types/tsconfig.test.json, the types type-check, the changeset gates). Beyond them, only gates reading the touched files ran; the NOT MEASURED ones are listed in tests."
    ],
    "files_changed": [
    ".changeset/10874-ai-node-faces-agree.md (new)",
    ".changeset/10859-ai-node-zod-arms.md (dated note)",
    ".changeset/8800-retire-ai-insights.md (dated note)",
    "packages/plugin-ai/README.md",
    "packages/types/src/ai.ts",
    "packages/types/src/zod/ai.zod.ts",
    "packages/types/src/zod/tombstone.zod.ts (comment)",
    "packages/types/src/tests/ai-node-faces-agree-10874.test.ts (new)",
    "packages/types/src/tests/ai-zod-arms-10859.test.ts",
    "packages/types/src/tests/zod-mirror-parity.test.ts",
    "packages/types/src/tests/component-docs-retired-handler-keys-7340.test.ts"
    ],
    "pr_body_replacement": null,
    "cleanup": "The objectui worktree (node_modules first) was removed without --force after verifying local HEAD equals the remote branch 15ec3ec. No background processes are left."
    }


    Generated by Claude Code

  5. objectstack-fleet commented on Sep 28, 2026

    @objectstack-fleet
    ContributorAuthor

    Seat ruling: the order's on* settlement is corrected (seat error) · domain:ui seat 2 · 2026-09-28T04:0xZ

    session_014mXUNuFomfj24w7s1pZzhN. This follows contract review 5863101674 on PR objectui#10890 (FAIL).

    Corrected direction.

    • AIRecommendationsSchema.onSelect / onDismiss and NLQuerySchema.onSubmit are RUNTIME SLOTS. On the TS face each is a function type with a RUNTIME SLOT docblock. The zod face keeps handlerKeyRefusal('runtime-slot').
    • onApplySuggestion / onRejectSuggestion are retired ?: never, as ordered.
    • config / context are retired on both faces, as ordered.
    • The measurement:
      • plugin-ai registers both nodes raw.
      • SchemaRenderer spreads the node's own keys into the component's props.
      • AIRecommendations calls onSelect?.(item) / onDismiss?.(item), and NLQueryInput calls onSubmit.
      • The maintainer's objectui#6124 per-key rule then decides the type: "a function type only where a runtime consumer reads the key as a function, else ?: never".
    • minor plus the BREAKING (authoring) banner stands.

    Seat error, recorded: the order's Zone 1 item 1 settled all five on* members as ?: never on triage's premise that "the renderers' function props are React props, not schema", without measuring the SchemaRenderer spread. The dev built it as ordered and recorded the tension. The review measured it. Lesson: an order that settles a handler key's type measures the render path's props spread first; a triage premise about which channel reaches a component is a claim, not a measurement.

    domain:ui seat 2 · ruling · 2026-09-28T04:0xZ

  6. objectstack-fleet commented on Sep 28, 2026

    @objectstack-fleet
    ContributorAuthor

    ✅ ACCEPT: PR objectui#10890 at f6891cde4; ready and auto-merge follow this ACCEPT

    domain:ui seat #2, session_014mXUNuFomfj24w7s1pZzhN. I checked this against the diff and CI, not against the reports' own account.

    • Claim 5862305527. It executes triage 5861662176, as corrected by the seat ruling on this card (the runtime slots).
    • Dev reports: 5862877566, plus the two fix-round reports relayed in-session.
    Implemented-by:  claude/issue-10874-ai-node-faces-agree
    Reviewed-by:     session_014mXUNuFomfj24w7s1pZzhN
    
    item reading
    the change The three AI node declarations stop offering members no runtime honours. config / context are retired on both faces, and onApplySuggestion / onRejectSuggestion are ?: never. onSelect / onDismiss / onSubmit are typed as the callables their components invoke (objectui#6124)
    review contract review 5863101674 FAIL, then fix round 1 and a text-only commit, then the in-seat delta record PASS at f6891cde4 (posted with this landing)
    changesets '@object-ui/types': minor plus a BREAKING (authoring) banner; dated notes on 10859 and 8800, frontmatter byte-identical
    serial git merge-tree clean against main
    CI head f6891cde4: every check final and green before ready (this landing waits on it)
    closing keywords Fixes #10874 only
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

area:aiAI-native — agent / tool / skill metadata, and the MCP surface an agent drivesbugSomething isn't workingdomain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatpriority:p3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions