Skip to content

@objectstack/scenarios ships .ts-only exports, so a consumer's built entry cannot load ./score (ERR_MODULE_NOT_FOUND) or must inline it; give it a minimal unpublished build step and a narrow scorer entry #30915

Closed

Description

@objectstack-fleet

repo:cloud#3 · hotlong · session_01Q4EjjRhUZjdy8VXs6Kkur2

Filing gate: (a) a measured defect with a named consumer, found by the cloud#3604 dev (report 6682453462 on objectstack-ai/cloud#3604). Ruling D on #30291 (verbatim 「同意 D」) moved the deterministic scorer into the private @objectstack/scenarios (entry @objectstack/scenarios/score). Cloud consumes it through its link: to the pinned framework tree. Carrier: objectstack (maintainer, 2026-11-06: 「平台的问题应该在平台处理」, #30765).

维护者速读

评估打分器已经按你的裁决搬进平台的私有包 @objectstack/scenarios,但这个包只有 .ts 源码、没有构建产物。cloud 引用它时,测试和类型检查都能过,但 cloud 打包后的运行时加载不到它(会报 ERR_MODULE_NOT_FOUND);换成内联打包,就等于把源码复制进 cloud(产物从 2.87 MB 涨到 3.95 MB),违反裁决。平台这边只需要给这个包加一个不对外发布的最小构建步骤,最好再给打分器单独一个窄入口。cloud#3604 的引用那一半在等这张卡。

Measured (by the cloud#3604 dev, objectstack c50e0dfa)

  • vitest and tsc in cloud resolve @objectstack/scenarios/score through link:.
  • Linked as a dependency: tsup leaves it external, and Node cannot load cloud's dist/index.js. The .ts source imports with .js specifiers, so the load fails with ERR_MODULE_NOT_FOUND (ESM and CJS). objectos and objectos-ee load that dist at boot, and graph-snapshot.mjs reads scoreGraphShape from it.
  • Linked as a devDependency: tsup inlines the scenarios source plus @objectstack/plugin-sharing into cloud's dist (2.87 MB → 3.95 MB). That is a build-time vendored copy, which the ruling forbids.

Expected

  1. @objectstack/scenarios gains a minimal build step: dist ESM + CJS + .d.ts, with exports["./score"] pointing at the built files. The package stays private and unpublished. The framework's pin-tree and Dockerfile builds pick the step up, so cloud needs no change for that.
  2. A narrow scorer entry, so a consumer of ./score (scoreGraphShape, the run grader) does not pull scenario-tags' plugin-sharing / objectql imports.

Acceptance

  • A built-consumer test: a package that depends on @objectstack/scenarios and builds with tsup can import('@objectstack/scenarios/score') from its dist under plain Node.
  • The ./score entry's import graph excludes plugin-sharing and objectql.

Unblocks: objectstack-ai/cloud#3604's import half. Its pin-move half is PR objectstack-ai/cloud#3663.

Suggested-grade: p2.

Activity

  1. added
    bugSomething isn't working
    pm:queueReady for the PM dispatch loop
    repo:cloudCard routed whole to the cloud PM: needs cloud code, a producer or a fact (cloud owns it to closure)
    domain:devxDomain lane — seat card indexed by label:pm:seat
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    and removed
    pm:queueReady for the PM dispatch loop
    on Nov 6, 2026
  2. objectstack-fleet commented on Nov 6, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:devx#1 · os-elon-musk · session_016WV4cymvo9YoyLwKCXXBNw

    Claim: PM loop round 7
    Session: session_016WV4cymvo9YoyLwKCXXBNw
    Account: os-elon-musk
    Branch: claude/project-thread-cin84b (the card thread's platform-assigned branch; a measured platform exception to claude/issue-<n>-<slug>) · card thread session session_016WV4cwgUKpQgCE3UWsA74d
    Worktree: objectstack-issue-30915
    Domain: domain:devx
    Seat: domain:devx#1
    File surface: packages/qa/scenarios/package.json (a build step, ESM + CJS + .d.ts, exports["./score"] on the built files, still private), a tsup config, a narrow scorer entry under src/score/, a built-consumer test, and the turbo/pin-tree wiring only if a build graph needs it.
    Container & model: M, mode:thread, model: default tier, effort: high (p2)
    Clause-②: no. The package stays private and unpublished. The scorer's behaviour does not change, only how it is built and entered.
    Metadata-protocol: none
    Responsibility: n/a. This is a measured defect with a named consumer (cloud#3604), following ruling D on #30291 (「同意 D」).
    Thread-read: none
    Premise: holds. packages/qa/scenarios ships .ts-only exports on main, and ./score reaches scenario-tags' plugin-sharing / objectql imports.
    Serial constraints: #30883 (claimed beside this card) edits src/score/** behaviour. This card owns only the entry, build and package wiring. Whichever lands second merges main first, and the narrow entry re-exports rather than moves the scorer, so the two do not collide. No other open PR touches packages/qa/scenarios/package.json (checked 2026-11-06T12:00Z).

  3. objectstack-fleet commented on Nov 6, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:devx#1 · os-elon-musk · session_016WV4cwgUKpQgCE3UWsA74d
    os-dev-report

    {
     "issue": 30915,
     "status": "done",
     "branch": "claude/project-thread-cin84b",
     "pr": "https://github.com/objectstack-ai/objectstack/pull/30938",
     "head": "e748dfb0a0",
     "session": "session_016WV4cwgUKpQgCE3UWsA74d",
     "premise_still_valid": true,
     "summary": "Premise held on origin/main 0e882086: exports named src/*.ts, and ./score (src/score/index.ts) reached objectql and plugin-sharing through scenario-tags.ts. The package (still private) now builds with tsup to dist/ (ESM .js, CJS .cjs, .d.ts/.d.cts) and every exports subpath points there; ./score is a new narrow entry src/score/narrow.ts (re-exports of scenario-graph, -naming, -operation-grade, -run-grade, -score; reads core + spec only) and the previous whole entry src/score/index.ts (code unchanged) is ./score/full. turbo runs the package's own build before its test. No score module moved (#30883 serial constraint).",
     "tests": "At e748dfb0a0 (origin/main 26c965cb8f merged, #30846 included): pnpm --filter @objectstack/scenarios build exit 0 (check-dts-emitted 8/8); test: Test Files 20 passed (20), Tests 256 passed (256); typecheck exit 0. New: test/build/built-consumer.test.ts (tsup-built fixture package loaded by plain node, ESM and CJS, with a module.registerHooks resolve recorder: scorer from dist, nothing from src, nothing matching objectql|plugin-sharing, core seen as control) and test/build/narrow-score-graph.test.ts (source graph walk from narrow.ts, control from index.ts finds both). Ablation 1 (package.json ./score import default back to ./src/score/index.ts via ablation-replace, anchor 1->0): both plain-Node legs red with ERR_MODULE_NOT_FOUND on src/schema.js, restored blob == HEAD. Ablation 2 (narrow.ts also re-exports scenario-tags, rebuilt, ablation-dist-preflight marker live): 3 failed | 2 passed, restored blob == HEAD, rebuilt, grep plugin-sharing|objectql on dist/score.{js,cjs,d.ts} = 0, test/build 5/5.",
     "gates": "dispatch-gates --commands --repo objectstack-ai/objectstack exit 0, 65 derived; all 65 exit 0 at e748dfb0a0 (check:dual-build-cjs-loads first exit 3 PREREQUISITE NOT MET, exit 0 after whole-tree turbo build 119/119). --ran exit 0: 65 run, 0 NOT-MEASURED. Record: /mnt/project-files/pm-devx-seat1/30915/gates-ran-e748dfb0.txt and the PR body. CI check-runs: in_progress at report time (not waited on).",
     "line_budget": "335 + / 15 - across 10 files (tests 186, tsup config + build tsconfig 57, package.json 48, narrow entry 24, READMEs/header 33, turbo 2). No skills/** touched.",
     "files_changed": [
      "packages/qa/scenarios/package.json",
      "packages/qa/scenarios/tsup.config.ts",
      "packages/qa/scenarios/tsconfig.build.json",
      "packages/qa/scenarios/src/score/narrow.ts",
      "packages/qa/scenarios/src/score/index.ts (header comment only)",
      "packages/qa/scenarios/test/build/built-consumer.test.ts",
      "packages/qa/scenarios/test/build/narrow-score-graph.test.ts",
      "packages/qa/scenarios/README.md",
      "docs/qa/scenarios/README.md",
      "turbo.json"
     ],
     "deviations": [
      "No private package under packages/ has a tsup build (measured: every private package with a build script runs `objectstack build`); wiring cited from packages/lint (type: module, multi-entry tsup, esm+cjs, check-dts-emitted).",
      "./score no longer exports scoreCardArtifact, the scenario-tags exports, gradeCardOperation or gradeCardAnswer: they moved to the new ./score/full subpath. Card-level graders live in index.ts beside scoreCardArtifact, so keeping them in ./score would have required moving code out of index.ts, which the #30883 serial constraint forbids. cloud#3604 reads scoreGraphShape and the run grader, both in ./score.",
      "Changeset: skip-changeset per order. Measured: Check Changeset (pr-automation.yml) exempts on the label alone, no private-package branch. Note: earlier scenarios PRs carried '@objectstack/scenarios': patch changesets, and .changeset/config.json has privatePackages.version true.",
      "Dockerfile: docker/Dockerfile installs published packages and builds no workspace package, so nothing to wire; pin-tree builds go through turbo run build, which now includes the package."
     ],
     "dogfood_battery": "n/a — no ! in the PR title and Clause-②: no",
     "mcp_calls": "4 — mcp__github__issue_read x2 (card + comments), mcp__github__pull_request_read x1 (PR read-back); zero MCP writes",
     "api_writes": "2 relay writes — pr_create (#30938, run 42220364185, 12249 bytes identical, label skip-changeset, assignee os-elon-musk) and this comment; plus one git push",
     "open_questions": [],
     "security_findings": "none",
     "out_of_scope_findings": []
    }

    Generated by Claude Code

  4. objectstack-fleet commented on Nov 6, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:devx#1 · os-elon-musk · session_016WV4cymvo9YoyLwKCXXBNw

    Landed · PR #30938 merged as 6910797f10 · 2026-11-06T15:34Z

    @objectstack/scenarios now builds with tsup (ESM, CJS and d.ts). ./score is the narrow entry and ./score/full the full one. The card closed via Fixes, and pm:dispatched is cleared. #30972 (card #30883) is in the queue on top of it.

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

Metadata

Metadata

Assignees

Labels

bugSomething isn't workingdomain:devxDomain lane — seat card indexed by label:pm:seatpriority:p2Medium: important, M3repo:cloudCard routed whole to the cloud PM: needs cloud code, a producer or a fact (cloud owns it to closure)

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions