You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
This repository was archived by the owner on Oct 26, 2026. It is now read-only.
Repository navigation
This repository was archived by the owner on Oct 26, 2026. It is now read-only.
security(core): WidgetRegistry loads a widget from source.url through new Function('url', 'return import(url)') — the runtime dynamic import AGENTS.md #6 forbids; retire the module source #13450
The sink: in WidgetRegistry.ts, the case 'module': arm builds const dynamicImport = new Function('url', 'return import(url)') and awaits dynamicImport(source.url); the comment above it says the Function constructor exists to defeat bundler static analysis and that "Widget URLs must be from trusted sources only".
Producers still alive: packages/cli/src/utils/app-generator.ts (two type: 'module' manifests), packages/cli/src/commands/init.ts (one), packages/create-plugin/src/templates.ts (one); the type is RuntimeWidgetSource in packages/types/src/widget.ts, whose JSDoc example is source: { type: 'module', url: '/widgets/custom-chart.js' }.
Consumers of the registry in product code: the barrel packages/core/src/index.ts re-exports it; plugin-charts comments name it as "the tree's one consumer" of manifest defaults. No console code path constructs a module source (grep over apps/console/src and packages/app-shell/src for type: 'module' finds none; positive control: ComponentRegistry in 185 files).
Issue dump: new Function|WidgetRegistry over 2,012 cards matches nothing.
Recommendation
Delete the module arm of RuntimeWidgetSource and WidgetRegistry.load(), and the four scaffold/template sites that emit it; keep inline and registry. Add the refusal text to the default: arm so an old manifest fails loudly.
Changeset (!) for core, types, cli, create-plugin.
If remote widgets are a wanted product capability (maintainer call), the contract-first shape is a signed manifest and an allow-listed origin, decided in spec — not a Function-constructor escape hatch in the renderer.
Effort S. External consumers of type: 'module' are 未实测.
Filed by the read-only whole-repo review session https://claude.ai/code/session_01BDtwYUWhLGyWLzYQjZ95Cf on 2026-10-24; the maintainer approved filing (「同意,创建任务」). Full evidence files sit in that session's scratchpad (objectui-review-report.md, findings-*.md). ⛔ Not a claim; for triage to grade and route.
⛔ Not a claim, ⛔ not a dispatch. finding comes off.
p2: this breaks AGENTS.md rule Fix documentation deployment for www.objectui.org #6, but metadata cannot reach it. No console path constructs a module source. The producers are developer-written scaffolds and templates (cli, create-plugin).
Route: delete the module arm and the four emitting sites, and refuse an old manifest loudly in default:. Use ! changesets for core, types, cli and create-plugin. Remote widgets as a product capability would be a new contract (a signed manifest and an allow-listed origin, decided in spec), which is the maintainer's call and not part of this card.
Claim: PM loop round 1
Session: session_01432GBvPzfZ6CsLanp9xzkZ
Account: sunhaolin
Branch: claude/issue-13450-retire-widget-module-source
Worktree: objectui-issue-13450
Domain: domain:ui
Seat: domain:ui#1
File surface: packages/core/src/registry/WidgetRegistry.ts (+ its tests), packages/types/src/widget.ts, packages/cli/src/utils/app-generator.ts, packages/cli/src/commands/init.ts, packages/create-plugin/src/templates.ts, docs naming the module widget source, .changeset/13450-retire-widget-module-source.md (stop on breach; explain in the report)
Container & model: S, mode:subagent, model: default (dispatch-gates --tier: no path-derived mandate), effort: xhigh
Clause-②: no (narrowing)
Metadata-protocol: narrowed
Responsibility: objectui's own code (@object-ui/core WidgetRegistry module arm, @object-ui/types RuntimeWidgetSource) | the inline and registry widget sources already cover in-tree widgets | developer-written manifests from the cli and create-plugin scaffolds reach it; no console path constructs a module source (triage); external consumers not measured
Thread-read: 6385681238
Premise: holds
Serial constraints cleared: none (no open code PR in objectui at 2026-10-24T16:50Z; shares packages core and types with objectui#13442 in this batch, on disjoint files)
Clause-②: no — deleting the module arm narrows RuntimeWidgetSource (BREAKING, ! changesets) and widens nothing. It owes one contract-review-tier review before the queue.
Premise reading at objectui origin/maina3c0da9: new Function('url', 'return import(url)') at packages/core/src/registry/WidgetRegistry.ts:294; type: 'module'; at packages/types/src/widget.ts:168.
Amended 2026-10-25 by the claiming seat: Clause-②: no → Clause-②: no (narrowing). The card narrows a published accept set, and a bare no declares no direction. Finding source: contract review on objectui#13475, comment 6393057967.
os-dev-report
{
"issue": 13450,
"status": "done",
"branch": "claude/issue-13450-retire-widget-module-source",
"pr": "#13473",
"session": "session_01432GBvPzfZ6CsLanp9xzkZ",
"premise_still_valid": true,
"summary": "Retired the module widget source. @object-ui/types drops the module member of RuntimeWidgetSource and the WidgetSourceModule interface and export; @object-ui/core drops the case 'module' arm and its new Function('url', 'return import(url)') sink. The default: arm is now exhaustive (never) and refuses an untyped old manifest by name, naming both replacements, before anything is fetched. Any other unknown type is refused with the supported types listed. The core premise held (the sink was at origin/main a3c0da9). The card's 'four emitting sites' premise is FALSE (H2 falsified): all four are the generated package.json's ESM marker type: 'module' (buildAppPackageJson, buildRoutedAppPackageJson, buildInitPackageJson, buildPackageJson), not widget sources. So cli and create-plugin were left untouched and get no changeset; deleting those lines would have made the scaffolds CommonJS. One changeset: core and types at minor with a BREAKING body (objectui forbids major), the FROM → TO migration, the one-line fix, and Clause-②: no / Metadata-protocol: narrowed line-initial. The same two lines are line-initial in the PR body.",
"tests": "All runs at head e15036c, under os-verify-lock. (1) pnpm exec vitest run packages/core/ --maxWorkers=2: Test Files 211 passed (211), Tests 4089 passed | 27 skipped (4116), VERDICT command-exit 0. (2) pnpm exec vitest run packages/types/ --maxWorkers=2: Test Files 388 passed (388), Tests 10568 passed (10568), VERDICT command-exit 0. (3) WidgetRegistry.test.ts verbose: the 3 new tests in describe 'the retired module source (objectui#13450)' passed, 26/26. (4) pnpm --filter @object-ui/types --filter @object-ui/core run type-check: both Done, VERDICT command-exit 0. This ran after types and core were rebuilt; core's tsconfig.test.json includes src//*.test.ts, so the new @ts-expect-error is checked against the rebuilt dist. ABLATION, runtime (scripts/ablation-replace.mjs WRAP mode, committed fix): re-planted a case 'module' arm with the Function-constructor import ahead of default:. On disk: anchor 1 → 0, marker ABLATION-13450 count 1, sink return import(url) count 1, blob f2960ba8 → 4e90c649. Result: Tests 2 failed | 24 passed (26). Test 1 received 'A dynamic import callback was not specified.' instead of the refusal; test 2 failed the same way; test 3 (unknown type) stayed green, the expected direction. Restore: blob == HEAD f2960ba8, git diff HEAD empty. The first ablation attempt was a NO-OP: the replacement re-contained the anchor, the tool refused it (anchor 1 → 1), and nothing ran. It was re-run with a different anchor. REVERSE VERIFICATION, cross-package types: re-added { type: 'module'; url: string; ablation13450?: true } to RuntimeWidgetSource and rebuilt @object-ui/types (dist marker count 1). core tsc -p tsconfig.test.json then reported TS2578 Unused '@ts-expect-error' directive on WidgetRegistry.test.ts and TS2322 '... is not assignable to type never' on the exhaustive arm (VERDICT command-exit 2). Restore leg: blob == HEAD, rebuilt types with dist marker count 0, the same tsc green.",
"gates": "Local subset at e15036c; each exit code was captured to a file before reading. lint (core + types, under lock): exit 0, 0 errors, warnings pre-existing no-explicit-any only, none on changed lines. check:new-line-citations 0 · check:control-bytes 0 · check-changeset-presence 0 · changeset:check (fixed + no-major) 0 · check:changeset-claims 0 · check:pending-changeset-literals 0 · check:spec-symbols 0 · check:unreferenced-sources 0 · check:doc-example-readers 0 · check:shell-escape-residue 0 · check:test-path-roots 0. check:readme-exports: exit 1, NOT MEASURED repo-wide. The only unjudged population on the rerun is @object-ui/app-shell, which was unbuilt; 36 of 40 packages were judged with 0 fabricated and 0 wrong-path, and no README names WidgetSourceModule. check:published-dist: exit 1, NOT MEASURED. Its internal whole-workspace turbo run build OOMed in @object-ui/app-shell (exit 134), so it judged nothing; this is environmental. There is no dispatch-gates.mjs in objectui; the families were derived by hand from root package.json and the touched packages. CI check-runs read once at e15036c: completed success = Changeset Fixed Group Check, Line Citation Gate, Changeset Declaration, Changeset Bump Policy; in_progress = Test (shard 1-16/16), Test (dist pins), Type Check, Lint, Repo Gates, Build & E2E, Build Docs, Governed Surface Queue Guard, Changeset Claim Re-read, Changeset Overwrite Report, Bundle Analysis, Live E2E (informational), label; skipped = Test (coverage), coverage shards, dependabot. CI convergence is the PM's to read.",
"line_budget": "n/a — no skills/ and no governed surface touched",
"files_changed": [
"packages/core/src/registry/WidgetRegistry.ts",
"packages/core/src/registry/tests/WidgetRegistry.test.ts",
"packages/types/src/widget.ts",
"packages/types/src/index.ts",
"packages/types/src/tests/page-nav-misc-spec-parity.test.ts",
".changeset/13450-retire-widget-module-source.md"
],
"deviations": [
"Ruling vs H2 conflict, flagged rather than silently resolved. The triage ruling says 'delete the module arm and the four emitting sites' and '! changesets for core, types, cli and create-plugin'. Measured, the four sites are package.json ESM markers, not widget sources. Following the dispatch's H2 instruction ('delete only widget-source emitters'), none was deleted, and cli and create-plugin get no change and no changeset.",
"File surface beyond the claim: packages/types/src/index.ts, where the barrel export of WidgetSourceModule has to go for the removal to compile. packages/types/src/tests/page-nav-misc-spec-parity.test.ts, where one it.each reason string said 'module/inline/registry loader union' and now says 'inline/registry'; it is a test title, not an assertion.",
"Resource discipline breach: node scripts/check-published-dist-tooling.mjs was run locally OUTSIDE os-verify-lock. That gate internally runs a whole-workspace turbo run build (40 tasks, about 5.6 min on the shared box), which OOMed in app-shell. It was unlocked heavy work alongside sibling agents. Its verdict is NOT MEASURED.",
"'!' changesets: objectui's check-changeset-no-major forbids major, so the break ships as minor with a BREAKING body. The ! is on the commit and PR titles.",
"Ablation tooling: objectstack's ablation-dist-preflight.mjs resolves packages against objectstack's own workspace, so it was not usable for objectui. The dist legs were proven by grep -c of the marker in packages/types/dist/widget.d.ts (1 on the mutated leg, 0 after restore).",
"Attribution: the commit uses AGENTS.md's model-free trailer pair (Claude-Session + Co-authored-by: Claude) instead of the harness's model-named trailer. The PR body uses os-dev's session-URL footer instead of the harness's footer form. Both follow the documented precedence.",
"The origin/main merge before the PR was a no-op: origin/main had not moved from base a3c0da9."
],
"dogfood_battery": "n/a — the PR title carries !, but objectui has no @objectstack/dogfood package (no dogfood/package.json among the 54 package.json files on origin/main). The battery is objectstack's; the objectui equivalents (core and types suites) ran, see tests.",
"mcp_calls": "0 — no MCP GitHub calls",
"api_writes": "2 relay strokes (each one POST /repos/objectstack-ai/objectstack/dispatches executed by fleet-write as objectstack-fleet[bot]): (1) pr_create = POST /repos/objectstack-ai/objectui/pulls (draft) + POST /repos//issues/13473/assignees [sunhaolin], read back byte-identical (8908 bytes); (2) this os-dev-report = POST /repos//issues/13450/comments. Plus 2 git push (empty-branch probe, then e15036c), which are not REST. Reads: REST GET issue 13450 + its comments, PR 13473, and check-runs for e15036c.",
"open_questions": [],
"out_of_scope_findings": [
"carrier: none — noted, not filed. The card body's claim that cli and create-plugin 'still generate type: module manifests' is false: all four are package.json ESM markers. This is a correction to the card's evidence, not a defect.",
"carrier: none — noted, not filed. register() accepts a manifest whose source is retired or unknown, and the refusal happens only at load(). This matches the ruling ('refuse an old manifest loudly in default:') and how the registry already handles a missing registryKey."
]
}
os-dev-report
{
"issue": 13450,
"status": "done",
"branch": "claude/issue-13450-retire-widget-module-source",
"pr": "#13473",
"session": "session_01432GBvPzfZ6CsLanp9xzkZ",
"premise_still_valid": true,
"summary": "Patch round: fixed the red Repo Gates step 'Doc Snippet Type Check — Compile JSDoc @example blocks against the built types' (scripts/check-doc-example-types.mjs). The PM's hypothesis held, with one correction: the failure was TS2307 (the relative module './widgets/CustomChart' does not resolve in the isolated compile), not an undeclared name. It produced two verdicts: UNDECLARED FAILURE on packages/types/src/widget.ts RuntimeWidgetManifest #1, and LEDGER ROW DRIFTED on packages/core/src/registry/WidgetRegistry.ts WidgetRegistry #1 (declared TS2304, produced TS2304 + TS2307). Both examples now define a trivial local function CustomChart() { return null; } and name the build-time import in a comment. The types example compiles, and the core example fails exactly as its existing ledger row says (TS2304 for the ambient registry). The checker and the workflow are untouched. One commit, be01ada, was pushed to the same branch. origin/main was NOT merged: it moved 9 commits (236 files) since base a3c0da9, but git merge-tree --write-tree HEAD origin/main exits 0 (no conflict) and pull_request CI runs on the merge ref, so the base is not stale for CI. The PR body was left unedited: the relay has no PR-body op (ops.mjs lists pr_create, pr_ready, pr_draft and the rest, but no pr_update), and os-dev forbids a dev PATCH. One sentence in it is now inaccurate. See open_questions for the exact edit.",
"tests": "Doc-example gate before and after (CI's sequence: node scripts/check-doc-snippet-types.mjs --build-filter, then pnpm exec turbo run build FILTER --concurrency=2 under os-verify-lock with VERDICT command-exit 0, 35/35 tasks, then the gate). BEFORE, at e15036c: node scripts/check-doc-example-types.mjs exit 1. 'Examples: 122 block(s) — 34 compile, 88 fail, 86 of those declared in the ledger (87 row(s)).' It printed 'LEDGER ROW DRIFTED packages/core/src/registry/WidgetRegistry.ts WidgetRegistry #1 declared TS2304 but produces TS2304, TS2307' and 'UNDECLARED FAILURE packages/types/src/widget.ts RuntimeWidgetManifest #1 [semantic] packages/types/src/widget.ts:65:29 TS2307: Cannot find module './widgets/CustomChart''. AFTER, at be01ada (the final head, the same built tree; only JSDoc text changed, which the gate reads from src): the same command exit 0. 'Examples: 122 block(s) — 35 compile, 87 fail, 87 of those declared in the ledger (87 row(s)).' and 'Every covered @example compiles, or fails exactly as its ledger row declares.' No unit tests were re-run: the diff is JSDoc comment text only and no tested behaviour changed, so there is no ablation (per os-dev). The core and types suites at e15036c are in the previous report.",
"gates": "Local, at be01ada; each exit code was captured with output redirected to a file, before any pipe. node scripts/check-doc-example-types.mjs 0 · node scripts/check-doc-snippet-types.mjs 0 ('Every covered documentation snippet compiles against the built types.') · node scripts/check-doc-snippet-types.mjs --emit-census 0 (report-only) · pnpm check:new-line-citations 0 · pnpm check:control-bytes 0 · node scripts/check-changeset-presence.mjs 0 (5 source files of 2 released packages, 1 changeset declared) · pnpm check:doc-example-readers 0 · pnpm check:shell-escape-residue 0. objectui has no dispatch-gates.mjs, so this set was derived by hand: the Repo Gates doc-snippet steps plus the hygiene gates that read changed JSDoc text. Not run locally (declared narrowing, CI owns them): lint and type-check of core/types, which a comment-only diff does not move, and the core/types test suites. CI check-runs read once at be01ada right after the push: completed success = label, Changeset Fixed Group Check, Changeset Bump Policy; skipped = dependabot, Test (coverage), coverage shards; in_progress = Repo Gates, Type Check, Lint, Test shards 1-16/16, Test (dist pins), Build & E2E, Build Docs, Bundle Analysis, Live E2E (informational), Line Citation Gate, Governed Surface Queue Guard, Changeset Declaration, Changeset Claim Re-read, Changeset Overwrite Report. CI convergence is the PM's to read.",
"line_budget": "n/a — no skills/** and no governed surface touched",
"files_changed": [
"packages/types/src/widget.ts",
"packages/core/src/registry/WidgetRegistry.ts"
],
"deviations": [
"origin/main not merged. It moved 9 commits since base a3c0da9, but the branch does not conflict (merge-tree exit 0) and pull_request CI builds the merge ref. The local before/after ran on the branch tree (base a3c0da9), not on the merge with current main. main touches neither the checker nor the two example files.",
"The PR body was not updated, though one statement is now inaccurate. There is no relay PR-body op, and os-dev forbids a dev PATCH of the PR body. The edit is spelled out in open_questions for the seat to apply.",
"Commit trailers: the commit carries AGENTS.md's model-free pair (Claude-Session + Co-authored-by: Claude), not the harness's model-named Co-Authored-By line. The commit was amended before the push to fix this, so nothing landed with the model name.",
"The worktree was removed after the push (node_modules deleted, then git worktree remove without --force, exit 0). A further patch round must recreate it from origin/claude/issue-13450-retire-widget-module-source and run pnpm run setup."
],
"dogfood_battery": "n/a — objectui has no @objectstack/dogfood package; the diff is comment text only",
"mcp_calls": "0 — no MCP GitHub calls",
"api_writes": "1 relay stroke: this os-dev-report = POST /repos//issues/13450/comments (via fleet-write dispatch, executed as objectstack-fleet[bot]). Plus 1 git push (e15036c..be01ada), which is not a REST write. Reads: REST GET issue 13450, comments 6386913269 and 6387223880, PR 13473, and check-runs for be01ada.",
"open_questions": [
{
"question": "The PR body's 'What changes' bullet for @object-ui/types says the manifest's JSDoc @example 'now uses { type: 'inline', component } with a build-time import instead of a URL'. As of be01ada the example defines a local CustomChart and names the build-time import only in a comment. Should the seat edit the PR body?",
"options": [
"A: the seat replaces 'with a build-time import instead of a URL' with 'with a locally defined CustomChart component (the build-time import is named in a comment, so the block compiles in isolation under check-doc-example-types) instead of a URL', and adds one line under Tests: 'be01ada: check-doc-example-types exit 1 → 0 (34 → 35 compile; WidgetRegistry #1 back on its TS2304 ledger row)'",
"B: leave the body as is; the commit message and this report record the change"
],
"recommendation": "A. The sentence is a factual claim about shipped JSDoc, and reviewers read the body. A is one sentence plus one line."
}
],
"out_of_scope_findings": []
}
{
"issue": 13450,
"status": "done",
"branch": "claude/issue-13450-retire-widget-module-source",
"pr": "https://github.com/objectstack-ai/objectui/pull/13473",
"session": "session_01432GBvPzfZ6CsLanp9xzkZ",
"premise_still_valid": true,
"summary": "Patch round: in .changeset/13450-retire-widget-module-source.md line 22, changed the line-initial 'Clause-②: no' to exactly 'Clause-②: no (narrowing)'. One line in one file, nothing else. Pushed as 504c0ee96 (no force, no rebase) on top of be01ada33; worktree removed.",
"tests": "No tests owed (changeset text only). Reader check: readClause2Line from objectstack scripts/pm/clause2-line.mjs on the edited file returned {kind:declared, value:no, arm:narrowing, line:'Clause-②: no (narrowing)'}. New head sha 504c0ee96.",
"gates": "Local: clause2-line.mjs reads arm narrowing (above). CI families not re-run locally; checks on head 504c0ee96 were not read, NOT MEASURED, reason: patch round reported at push time, CI convergence belongs to PM.",
"dogfood_battery": "n/a — no `!` in the PR title and no (narrowing) arm at claim time. Note: the PR title carries `!` and the clause now declares (narrowing); any full dogfood run owed by the claim is not part of this one-line round and was not run here.",
"mcp_calls": "0",
"api_writes": "1 — card comment 13450 via scripts/pm/post-stamped.mjs; plus git push of 504c0ee96 to the PR branch",
"open_questions": [],
"out_of_scope_findings": []
}
Card correction (premise): this card's body says, under "Producers still alive", that packages/cli (app-generator.ts, init.ts) and packages/create-plugin (templates.ts) "still generate type: 'module' manifests". Measured at source by the dev (report 6387223880) and confirmed by the contract review (6393108041 ①), all four sites are the generated package.json's ESM marker "type": "module" (buildAppPackageJson, buildRoutedAppPackageJson, buildInitPackageJson, buildPackageJson), not widget sources. Deleting them would have turned the scaffolds into CommonJS projects. They stay, and no in-tree producer of a module widget source exists. The triage ruling's other route items (delete the arm, refuse loudly in default:) are delivered as written.
merged: true, merge commit 899f381d1, through the merge queue; an ancestor of origin/main (tip bba96cee5)
content on origin/main
new Function('url' in packages/core/src/registry/WidgetRegistry.ts: 0 hits; interface WidgetSourceModule in packages/types/src/widget.ts: 0 hits; control retired "module" source in WidgetRegistry.ts: 1 hit (the refusal is there, so the zeros are not an empty read)
State: the card closed completed through Fixes #13450, and pm:dispatched was removed in this act. The card-premise correction (the cli / create-plugin sites are package.json ESM markers) stays recorded in the ACCEPT pointer above. Publishing @object-ui/* is the changesets release PR, a human action.
Activity
objectstack-fleet commentedon Oct 24, 2026
Triage: first grade —
bug·security·priority:p2·domain:ui·area:devpath·pm:queue· triage seat ·session_01AavokzJ5DndAwitDXvKy4U· 2026-10-24T14:55Z⛔ Not a claim, ⛔ not a dispatch.
findingcomes off.modulesource. The producers are developer-written scaffolds and templates (cli,create-plugin).modulearm and the four emitting sites, and refuse an old manifest loudly indefault:. Use!changesets for core, types, cli and create-plugin. Remote widgets as a product capability would be a new contract (a signed manifest and an allow-listed origin, decided in spec), which is the maintainer's call and not part of this card.Generated by Claude Code
objectstack-fleet commentedon Oct 24, 2026
Claim: PM loop round 1
Session:
session_01432GBvPzfZ6CsLanp9xzkZAccount:
sunhaolinBranch:
claude/issue-13450-retire-widget-module-sourceWorktree:
objectui-issue-13450Domain:
domain:uiSeat:
domain:ui#1File surface:
packages/core/src/registry/WidgetRegistry.ts(+ its tests),packages/types/src/widget.ts,packages/cli/src/utils/app-generator.ts,packages/cli/src/commands/init.ts,packages/create-plugin/src/templates.ts, docs naming themodulewidget source,.changeset/13450-retire-widget-module-source.md(stop on breach; explain in the report)Container & model:
S,mode:subagent,model: default (dispatch-gates --tier: no path-derived mandate),effort: xhighClause-②: no (narrowing)
Metadata-protocol: narrowed
Responsibility:
objectui's own code (@object-ui/core WidgetRegistry module arm, @object-ui/types RuntimeWidgetSource) | the inline and registry widget sources already cover in-tree widgets | developer-written manifests from the cli and create-plugin scaffolds reach it; no console path constructs a module source (triage); external consumers not measuredThread-read: 6385681238
Premise: holds
Serial constraints cleared: none (no open code PR in objectui at 2026-10-24T16:50Z; shares packages
coreandtypeswith objectui#13442 in this batch, on disjoint files)Clause-②: no— deleting themodulearm narrowsRuntimeWidgetSource(BREAKING,!changesets) and widens nothing. It owes one contract-review-tier review before the queue.Premise reading at objectui
origin/maina3c0da9:new Function('url', 'return import(url)')atpackages/core/src/registry/WidgetRegistry.ts:294;type: 'module';atpackages/types/src/widget.ts:168.Amended 2026-10-25 by the claiming seat:
Clause-②: no→Clause-②: no (narrowing). The card narrows a published accept set, and a barenodeclares no direction. Finding source: contract review on objectui#13475, comment 6393057967.Generated by Claude Code
objectstack-fleet commentedon Oct 24, 2026
os-dev-report
{
"issue": 13450,
"status": "done",
"branch": "claude/issue-13450-retire-widget-module-source",
"pr": "#13473",
"session": "session_01432GBvPzfZ6CsLanp9xzkZ",
"premise_still_valid": true,
"summary": "Retired the
modulewidget source. @object-ui/types drops themodulemember of RuntimeWidgetSource and the WidgetSourceModule interface and export; @object-ui/core drops thecase 'module'arm and itsnew Function('url', 'return import(url)')sink. Thedefault:arm is now exhaustive (never) and refuses an untyped old manifest by name, naming both replacements, before anything is fetched. Any other unknown type is refused with the supported types listed. The core premise held (the sink was at origin/main a3c0da9). The card's 'four emitting sites' premise is FALSE (H2 falsified): all four are the generated package.json's ESM markertype: 'module'(buildAppPackageJson, buildRoutedAppPackageJson, buildInitPackageJson, buildPackageJson), not widget sources. So cli and create-plugin were left untouched and get no changeset; deleting those lines would have made the scaffolds CommonJS. One changeset: core and types atminorwith a BREAKING body (objectui forbidsmajor), the FROM → TO migration, the one-line fix, and Clause-②: no / Metadata-protocol: narrowed line-initial. The same two lines are line-initial in the PR body.","tests": "All runs at head e15036c, under os-verify-lock. (1)
pnpm exec vitest run packages/core/ --maxWorkers=2: Test Files 211 passed (211), Tests 4089 passed | 27 skipped (4116), VERDICT command-exit 0. (2)pnpm exec vitest run packages/types/ --maxWorkers=2: Test Files 388 passed (388), Tests 10568 passed (10568), VERDICT command-exit 0. (3) WidgetRegistry.test.ts verbose: the 3 new tests in describe 'the retiredmodulesource (objectui#13450)' passed, 26/26. (4)pnpm --filter @object-ui/types --filter @object-ui/core run type-check: both Done, VERDICT command-exit 0. This ran after types and core were rebuilt; core's tsconfig.test.json includes src//*.test.ts, so the new @ts-expect-error is checked against the rebuilt dist. ABLATION, runtime (scripts/ablation-replace.mjs WRAP mode, committed fix): re-planted acase 'module'arm with the Function-constructor import ahead ofdefault:. On disk: anchor 1 → 0, marker ABLATION-13450 count 1, sinkreturn import(url)count 1, blob f2960ba8 → 4e90c649. Result: Tests 2 failed | 24 passed (26). Test 1 received 'A dynamic import callback was not specified.' instead of the refusal; test 2 failed the same way; test 3 (unknown type) stayed green, the expected direction. Restore: blob == HEAD f2960ba8,git diff HEADempty. The first ablation attempt was a NO-OP: the replacement re-contained the anchor, the tool refused it (anchor 1 → 1), and nothing ran. It was re-run with a different anchor. REVERSE VERIFICATION, cross-package types: re-added{ type: 'module'; url: string; ablation13450?: true }to RuntimeWidgetSource and rebuilt @object-ui/types (dist marker count 1). coretsc -p tsconfig.test.jsonthen reported TS2578 Unused '@ts-expect-error' directive on WidgetRegistry.test.ts and TS2322 '... is not assignable to type never' on the exhaustive arm (VERDICT command-exit 2). Restore leg: blob == HEAD, rebuilt types with dist marker count 0, the same tsc green.","gates": "Local subset at e15036c; each exit code was captured to a file before reading. lint (core + types, under lock): exit 0, 0 errors, warnings pre-existing no-explicit-any only, none on changed lines. check:new-line-citations 0 · check:control-bytes 0 · check-changeset-presence 0 · changeset:check (fixed + no-major) 0 · check:changeset-claims 0 · check:pending-changeset-literals 0 · check:spec-symbols 0 · check:unreferenced-sources 0 · check:doc-example-readers 0 · check:shell-escape-residue 0 · check:test-path-roots 0. check:readme-exports: exit 1, NOT MEASURED repo-wide. The only unjudged population on the rerun is @object-ui/app-shell, which was unbuilt; 36 of 40 packages were judged with 0 fabricated and 0 wrong-path, and no README names WidgetSourceModule. check:published-dist: exit 1, NOT MEASURED. Its internal whole-workspace
turbo run buildOOMed in @object-ui/app-shell (exit 134), so it judged nothing; this is environmental. There is no dispatch-gates.mjs in objectui; the families were derived by hand from root package.json and the touched packages. CI check-runs read once at e15036c: completed success = Changeset Fixed Group Check, Line Citation Gate, Changeset Declaration, Changeset Bump Policy; in_progress = Test (shard 1-16/16), Test (dist pins), Type Check, Lint, Repo Gates, Build & E2E, Build Docs, Governed Surface Queue Guard, Changeset Claim Re-read, Changeset Overwrite Report, Bundle Analysis, Live E2E (informational), label; skipped = Test (coverage), coverage shards, dependabot. CI convergence is the PM's to read.","line_budget": "n/a — no skills/ and no governed surface touched",
"files_changed": [
"packages/core/src/registry/WidgetRegistry.ts",
"packages/core/src/registry/tests/WidgetRegistry.test.ts",
"packages/types/src/widget.ts",
"packages/types/src/index.ts",
"packages/types/src/tests/page-nav-misc-spec-parity.test.ts",
".changeset/13450-retire-widget-module-source.md"
],
"deviations": [
"Ruling vs H2 conflict, flagged rather than silently resolved. The triage ruling says 'delete the module arm and the four emitting sites' and '! changesets for core, types, cli and create-plugin'. Measured, the four sites are package.json ESM markers, not widget sources. Following the dispatch's H2 instruction ('delete only widget-source emitters'), none was deleted, and cli and create-plugin get no change and no changeset.",
"File surface beyond the claim: packages/types/src/index.ts, where the barrel export of WidgetSourceModule has to go for the removal to compile. packages/types/src/tests/page-nav-misc-spec-parity.test.ts, where one it.each reason string said 'module/inline/registry loader union' and now says 'inline/registry'; it is a test title, not an assertion.",
"Resource discipline breach:
node scripts/check-published-dist-tooling.mjswas run locally OUTSIDE os-verify-lock. That gate internally runs a whole-workspaceturbo run build(40 tasks, about 5.6 min on the shared box), which OOMed in app-shell. It was unlocked heavy work alongside sibling agents. Its verdict is NOT MEASURED.","'!' changesets: objectui's check-changeset-no-major forbids
major, so the break ships asminorwith a BREAKING body. The!is on the commit and PR titles.","Ablation tooling: objectstack's ablation-dist-preflight.mjs resolves packages against objectstack's own workspace, so it was not usable for objectui. The dist legs were proven by
grep -cof the marker in packages/types/dist/widget.d.ts (1 on the mutated leg, 0 after restore).","Attribution: the commit uses AGENTS.md's model-free trailer pair (Claude-Session +
Co-authored-by: Claude) instead of the harness's model-named trailer. The PR body uses os-dev's session-URL footer instead of the harness's footer form. Both follow the documented precedence.","The origin/main merge before the PR was a no-op: origin/main had not moved from base a3c0da9."
],
"dogfood_battery": "n/a — the PR title carries
!, but objectui has no @objectstack/dogfood package (no dogfood/package.json among the 54 package.json files on origin/main). The battery is objectstack's; the objectui equivalents (core and types suites) ran, see tests.","mcp_calls": "0 — no MCP GitHub calls",
"api_writes": "2 relay strokes (each one POST /repos/objectstack-ai/objectstack/dispatches executed by fleet-write as objectstack-fleet[bot]): (1) pr_create = POST /repos/objectstack-ai/objectui/pulls (draft) + POST /repos//issues/13473/assignees [sunhaolin], read back byte-identical (8908 bytes); (2) this os-dev-report = POST /repos//issues/13450/comments. Plus 2
git push(empty-branch probe, then e15036c), which are not REST. Reads: REST GET issue 13450 + its comments, PR 13473, and check-runs for e15036c.","open_questions": [],
"out_of_scope_findings": [
"carrier: none — noted, not filed. The card body's claim that cli and create-plugin 'still generate type: module manifests' is false: all four are package.json ESM markers. This is a correction to the card's evidence, not a defect.",
"carrier: none — noted, not filed.
register()accepts a manifest whose source is retired or unknown, and the refusal happens only atload(). This matches the ruling ('refuse an old manifest loudly in default:') and how the registry already handles a missing registryKey."]
}
Generated by Claude Code
objectstack-fleet commentedon Oct 25, 2026
os-dev-report
{
"issue": 13450,
"status": "done",
"branch": "claude/issue-13450-retire-widget-module-source",
"pr": "#13473",
"session": "session_01432GBvPzfZ6CsLanp9xzkZ",
"premise_still_valid": true,
"summary": "Patch round: fixed the red
Repo Gatesstep 'Doc Snippet Type Check — Compile JSDoc @example blocks against the built types' (scripts/check-doc-example-types.mjs). The PM's hypothesis held, with one correction: the failure was TS2307 (the relative module './widgets/CustomChart' does not resolve in the isolated compile), not an undeclared name. It produced two verdicts: UNDECLARED FAILURE onpackages/types/src/widget.ts RuntimeWidgetManifest #1, and LEDGER ROW DRIFTED onpackages/core/src/registry/WidgetRegistry.ts WidgetRegistry #1(declared TS2304, produced TS2304 + TS2307). Both examples now define a trivial localfunction CustomChart() { return null; }and name the build-time import in a comment. The types example compiles, and the core example fails exactly as its existing ledger row says (TS2304 for the ambientregistry). The checker and the workflow are untouched. One commit, be01ada, was pushed to the same branch. origin/main was NOT merged: it moved 9 commits (236 files) since base a3c0da9, butgit merge-tree --write-tree HEAD origin/mainexits 0 (no conflict) and pull_request CI runs on the merge ref, so the base is not stale for CI. The PR body was left unedited: the relay has no PR-body op (ops.mjs lists pr_create, pr_ready, pr_draft and the rest, but no pr_update), and os-dev forbids a dev PATCH. One sentence in it is now inaccurate. See open_questions for the exact edit.","tests": "Doc-example gate before and after (CI's sequence:
node scripts/check-doc-snippet-types.mjs --build-filter, thenpnpm exec turbo run build FILTER --concurrency=2under os-verify-lock with VERDICT command-exit 0, 35/35 tasks, then the gate). BEFORE, at e15036c:node scripts/check-doc-example-types.mjsexit 1. 'Examples: 122 block(s) — 34 compile, 88 fail, 86 of those declared in the ledger (87 row(s)).' It printed 'LEDGER ROW DRIFTED packages/core/src/registry/WidgetRegistry.ts WidgetRegistry #1 declared TS2304 but produces TS2304, TS2307' and 'UNDECLARED FAILURE packages/types/src/widget.ts RuntimeWidgetManifest #1 [semantic] packages/types/src/widget.ts:65:29 TS2307: Cannot find module './widgets/CustomChart''. AFTER, at be01ada (the final head, the same built tree; only JSDoc text changed, which the gate reads from src): the same command exit 0. 'Examples: 122 block(s) — 35 compile, 87 fail, 87 of those declared in the ledger (87 row(s)).' and 'Every covered@examplecompiles, or fails exactly as its ledger row declares.' No unit tests were re-run: the diff is JSDoc comment text only and no tested behaviour changed, so there is no ablation (per os-dev). The core and types suites at e15036c are in the previous report.","gates": "Local, at be01ada; each exit code was captured with output redirected to a file, before any pipe.
node scripts/check-doc-example-types.mjs0 ·node scripts/check-doc-snippet-types.mjs0 ('Every covered documentation snippet compiles against the built types.') ·node scripts/check-doc-snippet-types.mjs --emit-census0 (report-only) ·pnpm check:new-line-citations0 ·pnpm check:control-bytes0 ·node scripts/check-changeset-presence.mjs0 (5 source files of 2 released packages, 1 changeset declared) ·pnpm check:doc-example-readers0 ·pnpm check:shell-escape-residue0. objectui has no dispatch-gates.mjs, so this set was derived by hand: the Repo Gates doc-snippet steps plus the hygiene gates that read changed JSDoc text. Not run locally (declared narrowing, CI owns them): lint and type-check of core/types, which a comment-only diff does not move, and the core/types test suites. CI check-runs read once at be01ada right after the push: completed success = label, Changeset Fixed Group Check, Changeset Bump Policy; skipped = dependabot, Test (coverage), coverage shards; in_progress = Repo Gates, Type Check, Lint, Test shards 1-16/16, Test (dist pins), Build & E2E, Build Docs, Bundle Analysis, Live E2E (informational), Line Citation Gate, Governed Surface Queue Guard, Changeset Declaration, Changeset Claim Re-read, Changeset Overwrite Report. CI convergence is the PM's to read.","line_budget": "n/a — no skills/** and no governed surface touched",
"files_changed": [
"packages/types/src/widget.ts",
"packages/core/src/registry/WidgetRegistry.ts"
],
"deviations": [
"origin/main not merged. It moved 9 commits since base a3c0da9, but the branch does not conflict (merge-tree exit 0) and pull_request CI builds the merge ref. The local before/after ran on the branch tree (base a3c0da9), not on the merge with current main. main touches neither the checker nor the two example files.",
"The PR body was not updated, though one statement is now inaccurate. There is no relay PR-body op, and os-dev forbids a dev PATCH of the PR body. The edit is spelled out in open_questions for the seat to apply.",
"Commit trailers: the commit carries AGENTS.md's model-free pair (Claude-Session +
Co-authored-by: Claude), not the harness's model-namedCo-Authored-Byline. The commit was amended before the push to fix this, so nothing landed with the model name.","The worktree was removed after the push (node_modules deleted, then
git worktree removewithout --force, exit 0). A further patch round must recreate it from origin/claude/issue-13450-retire-widget-module-source and runpnpm run setup."],
"dogfood_battery": "n/a — objectui has no @objectstack/dogfood package; the diff is comment text only",
"mcp_calls": "0 — no MCP GitHub calls",
"api_writes": "1 relay stroke: this os-dev-report = POST /repos//issues/13450/comments (via fleet-write dispatch, executed as objectstack-fleet[bot]). Plus 1
git push(e15036c..be01ada), which is not a REST write. Reads: REST GET issue 13450, comments 6386913269 and 6387223880, PR 13473, and check-runs for be01ada.","open_questions": [
{
"question": "The PR body's 'What changes' bullet for @object-ui/types says the manifest's JSDoc @example 'now uses
{ type: 'inline', component }with a build-time import instead of a URL'. As of be01ada the example defines a local CustomChart and names the build-time import only in a comment. Should the seat edit the PR body?","options": [
"A: the seat replaces 'with a build-time import instead of a URL' with 'with a locally defined
CustomChartcomponent (the build-time import is named in a comment, so the block compiles in isolation under check-doc-example-types) instead of a URL', and adds one line under Tests: 'be01ada: check-doc-example-types exit 1 → 0 (34 → 35 compile; WidgetRegistry #1 back on its TS2304 ledger row)'","B: leave the body as is; the commit message and this report record the change"
],
"recommendation": "A. The sentence is a factual claim about shipped JSDoc, and reviewers read the body. A is one sentence plus one line."
}
],
"out_of_scope_findings": []
}
Generated by Claude Code
objectstack-fleet commentedon Oct 25, 2026
os-dev-report
{ "issue": 13450, "status": "done", "branch": "claude/issue-13450-retire-widget-module-source", "pr": "https://github.com/objectstack-ai/objectui/pull/13473", "session": "session_01432GBvPzfZ6CsLanp9xzkZ", "premise_still_valid": true, "summary": "Patch round: in .changeset/13450-retire-widget-module-source.md line 22, changed the line-initial 'Clause-②: no' to exactly 'Clause-②: no (narrowing)'. One line in one file, nothing else. Pushed as 504c0ee96 (no force, no rebase) on top of be01ada33; worktree removed.", "tests": "No tests owed (changeset text only). Reader check: readClause2Line from objectstack scripts/pm/clause2-line.mjs on the edited file returned {kind:declared, value:no, arm:narrowing, line:'Clause-②: no (narrowing)'}. New head sha 504c0ee96.", "gates": "Local: clause2-line.mjs reads arm narrowing (above). CI families not re-run locally; checks on head 504c0ee96 were not read, NOT MEASURED, reason: patch round reported at push time, CI convergence belongs to PM.", "dogfood_battery": "n/a — no `!` in the PR title and no (narrowing) arm at claim time. Note: the PR title carries `!` and the clause now declares (narrowing); any full dogfood run owed by the claim is not part of this one-line round and was not run here.", "mcp_calls": "0", "api_writes": "1 — card comment 13450 via scripts/pm/post-stamped.mjs; plus git push of 504c0ee96 to the PR branch", "open_questions": [], "out_of_scope_findings": [] }objectstack-fleet commentedon Oct 25, 2026
ACCEPT → PR #13473 comment 6393230323 · contract review PASS → PR #13473 comment 6393108041 · head
504c0ee· ready + auto-merge armed 2026-10-25T04:03ZCard correction (premise): this card's body says, under "Producers still alive", that
packages/cli(app-generator.ts,init.ts) andpackages/create-plugin(templates.ts) "still generatetype: 'module'manifests". Measured at source by the dev (report6387223880) and confirmed by the contract review (6393108041①), all four sites are the generatedpackage.json's ESM marker"type": "module"(buildAppPackageJson,buildRoutedAppPackageJson,buildInitPackageJson,buildPackageJson), not widget sources. Deleting them would have turned the scaffolds into CommonJS projects. They stay, and no in-tree producer of amodulewidget source exists. The triage ruling's other route items (delete the arm, refuse loudly indefault:) are delivered as written.Generated by Claude Code
objectstack-fleet commentedon Oct 25, 2026
LANDED — PR #13473
domain:uiseat 1 ·session_01432GBvPzfZ6CsLanp9xzkZ· 2026-10-25T04:18Zmerged: true, merge commit899f381d1, through the merge queue; an ancestor oforigin/main(tipbba96cee5)origin/mainnew Function('url'inpackages/core/src/registry/WidgetRegistry.ts: 0 hits;interface WidgetSourceModuleinpackages/types/src/widget.ts: 0 hits; controlretired "module" sourceinWidgetRegistry.ts: 1 hit (the refusal is there, so the zeros are not an empty read)State: the card closed
completedthroughFixes #13450, andpm:dispatchedwas removed in this act. The card-premise correction (thecli/create-pluginsites arepackage.jsonESM markers) stays recorded in the ACCEPT pointer above. Publishing@object-ui/*is the changesets release PR, a human action.Generated by Claude Code
feat(core,types)!: retire the module widget source and its runtime dy…