Skip to content

lint: the object_extension publish door runs no field-formula judgment, so a computed field os build refuses still publishes through PUT /meta/object_extension #33072

Closed

Description

@objectstack-fleet

domain:spec#2 · os-tesla · session_01L9qibvfX5bawZKtfa6u7j9

Filing gate: ③ a follow-up a dev report surfaced (#32875, os-dev-report 6847088184, class a, measured at PR #33070 head 7b18b05f). Not reproduced over HTTP by the dev or the filer.
Reader: the lane that owns the runtime authoring-rule roster (runtimeTypes of validateStackExpressions in packages/lint/src/validate-expressions.ts, read by runtimeAuthoringRulesFor).

维护者速读

PR #33070(#32875)之后,os build / os validate 会检查对象扩展加的存储型计算字段的公式;但运行时保存对象扩展(PUT /api/v1/meta/object_extension/TARGET,Studio 在 .custom 对上加字段)只跑 validateSecurityRoleWord,不跑公式检查。于是 build 会拒的计算字段,经运行时保存仍能发布。两道门对同一个字段判法不一致。

What happens

Expected

The object_extension publish door asks the same field-formula judgment the build asks of an extension field (against the extended object as served), so the two doors agree; a refusal at the door carries the same rule id and location the build prints.

Dedupe

repo:objectstack-ai/objectstack is:issue is:open object_extension validateSecurityRoleWord → #32875 only (the build half). Related: #32875, PR #33070, #32529.

⛔ Not a claim. Grading and lane are triage's.

Activity

  1. objectstack-fleet commented on Nov 13, 2026

    @objectstack-fleet
    ContributorAuthor

    triage#1 · hotlong · session_01Q4EjjMnyLqJdzuktEmRPXH

    Path: none

    Triage: first touch → domain:spec · p2 · pm:queue · 2026-11-13T07:45Z

    ⛔ Not a claim. The runtime object_extension publish door skips the field-formula judgment that os build/os validate now run (#32875 / PR #33070), so a Studio or API author gets no signal for a stored computed extension field. It is a missing authoring signal with the CLI as a workaround: p2 (#32997). Lane: domain:spec (runtimeTypes in validate-expressions.ts).


    Generated by Claude Code

  2. added
    domain:specDomain lane — seat card indexed by label:pm:seat
    pm:queueReady for the PM dispatch loop
    on Nov 13, 2026
  3. objectstack-fleet commented on Nov 13, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:spec#2 · os-tesla · session_01L9qibvfX5bawZKtfa6u7j9

    Claim: PM loop round 2 · 2026-11-13T14:12Z
    Session: session_01L9qibvfX5bawZKtfa6u7j9 (seat); card thread session_01L9qibwwiSN1TXWjohzCZN9 is the dev
    Account: os-tesla
    Branch: claude/project-thread-1oe8qz (the card thread's designated branch; the platform lets a thread push only that branch, so not claude/issue-33072-*)
    Worktree: objectstack-issue-33072
    Domain: domain:spec
    Seat: domain:spec#2
    File surface: packages/lint/src/validate-expressions.ts; packages/lint/src/runtime-gate.ts / authoring-rules.ts where the runtime roster lives; the runtime object_extension publish door's file if the gate must be handed the served target; their tests; root .changeset/; a semantic-migration entry if the level is narrowed (stop on breach; explain in the report)
    Container & model: M, mode:thread, model: default tier (the seat runs the contract review at landing), effort: high (fleet token rule 2, maintainer 2026-11-12)
    Clause-②: no
    Metadata-protocol: narrowed
    Responsibility: validateStackExpressions declares runtimeTypes without object_extension, so runtimeAuthoringRulesFor('object_extension') answers only validateSecurityRoleWord (packages/lint) (objectstack) | none: PR #33070 judges extension fields at build only | every app author and AI agent adding a computed field through Studio's .custom pair or PUT /api/v1/meta/object_extension/TARGET; the door publishes a field os build refuses
    Thread-read: 6847222554
    Premise: holds at origin/main 64551047: PR #33070 (#32875) merged and judges extension fields at build; the runtime roster for object_extension names only validateSecurityRoleWord (seat-filed finding from os-dev report 6847088184, class a). Level is provisional: the dev measures first-party exposure and confirms or corrects Metadata-protocol in the PR.
    Serial constraints cleared: sibling cards #32836 / #32837 from this seat edit packages/lint/src/*.user-text.ts and finding-user-text.ts, outside this surface; no other open PR from this seat touches validate-expressions.ts.

  4. added
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    and removed
    pm:queueReady for the PM dispatch loop
    on Nov 13, 2026
  5. objectstack-fleet commented on Nov 13, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:spec#2 · os-tesla · session_01L9qibwwiSN1TXWjohzCZN9

    os-dev-report

    {
      "issue": 33072,
      "status": "done",
      "branch": "claude/project-thread-1oe8qz",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/33119",
      "session": "session_01L9qibwwiSN1TXWjohzCZN9",
      "premise_still_valid": true,
      "summary": "Premise held at main 2c98485d: runtimeAuthoringRulesFor('object_extension') answered only validateSecurityRoleWord, and the door published an extension formula sqrt(record.amount) with 0 errors while the build refused it with 1 expression-invalid at object 'fx_ticket' · objectExtensions[0] · field 'score' expression (pins committed first at 5dae65b1, 8 of 10 red). validateStackExpressions now declares object_extension in runtimeTypes; on that write runStackExpressionPasses runs only #32875's extension walk (judgeFieldFormula over objectExtensionsByTarget, indexes over objectsAsServed): the object walk and flows walk read empty lists and the function returns after the walk, so no second field walk or fold exists. The host needed no change (the gate already carries live objects). Metadata-protocol narrowed, confirmed by measurement; first-party exposure 0. Semantic entry object-extension-door-computed-field-expression-judged and changeset 33072-object-extension-door-formula.md (minor lint + spec).",
      "tests": "At c237a74a: pnpm --filter @objectstack/lint test → Test Files 202 passed (202), Tests 8625 passed (8625); typecheck exit 0. @objectstack/metadata-protocol (consumer, the gate host) vitest run → Test Files 337 passed | 7 skipped (344), Tests 22799 passed | 36 skipped. @objectstack/runtime src/domains/meta-object-extension-item.test.ts → 26 passed, the 3 new #33072 cases verbose-confirmed. Full @objectstack/runtime suite at 8c1950cb (consumer): lock VERDICT command-exit 0 (20m39s), Test Files 600 passed (600), Tests 11920 passed | 19 skipped (11939). New pins: lint runtime-gate.object-formula-writes.test.ts describe #33072 (10: roster, 3 LIT, PARITY door==build on one shared input, CONTROL valid formula, undeclared target, differential, narrowing, CONTROL object door) and runtime meta-object-extension-item.test.ts [#33072] (3, real saveMetaItem+publishMetaItem: 422 INVALID_METADATA, issue expression-invalid at object 'crm_account' · objectExtensions[0] · field 'score__c' expression, row left draft; misspelt read refused; CONTROL publishes and is served). Ablation 1: object_extension dropped from runtimeTypes via ablation-replace (anchor 1→0), lint rebuilt, ablation-dist-preflight --absent read the double-quoted dist marker gone → lint 8 failed / 41 passed, runtime (dist) 2 LIT failed / CONTROL passed; restore blob == HEAD, rebuild, preflight marker present in 4 files, runtime 3/3. A first attempt was a refused anchor miss (no write), not counted. Ablation 2: object-walk fence removed → 1 failed (the narrowing pin), differential green; restore blob == HEAD.",
      "gates": "dispatch-gates --commands (objectstack-ai/objectstack at c237a74a, 8 paths vs merge base 2c98485d) → 87 families, each run with stdin from /dev/null, exit codes captured before any pipe: 86 exit 0, check:dual-build-cjs-loads exit 3 (PREREQUISITE NOT MET, needs every dist). --ran with exit codes: 87 derived, 86 run, 1 NOT-MEASURED (derived), 0 UNRUN. After a full pnpm build at 8c1950cb (lock VERDICT command-exit 0, 7m36s) check:dual-build-cjs-loads exit 0 (123 entries / 72 packages load). The merge of origin/main 9433d4f3 (2 commits: skills/objectstack-data/** and scripts/pm/check-skill-line-ratchet.mjs) changed no derived path. PR check-runs at 8c1950cb when read: all eleven required contexts success: Lint & Repo Gates, TypeScript Type Check, Test Core, Build Core, Governed Surface Queue Guard, Lint UI (skipped by its path filter), Type Check UI, Test UI, Build & E2E UI, Live E2E UI, Dogfood Regression Gate; also Check Changeset, Check PR Size, Spec property liveness, PR-body guards, Flag docs affected by code changes success; 0 failures among 67 check-runs.",
      "dogfood_battery": "8c1950cb · os-verify-lock: VERDICT command-exit 0 (34m15s) · Test Files 460 passed | 3 skipped (463) · Tests 3874 passed | 42 skipped (3916) · no failures",
      "mcp_calls": "4 — mcp__github__issue_read x2 (get, get_comments; one more get_comments before pr_create), mcp__github__pull_request_read x1 (get_check_runs); 0 write tools",
      "api_writes": "2 — relay pr_create (objectstack-ai/objectstack#33119, run 43449876536, body 12091 bytes read back identical, assignee os-tesla) and this os-dev-report comment via post-stamped; plus git push (not a REST write)",
      "open_questions": [],
      "security_findings": "none",
      "out_of_scope_findings": [
        "carrier: none · noted, not filed · the door does not judge an extension's validations; the build does not judge them as extension items either (#32875 judged fields only), so the two doors agree",
        "carrier: none · noted, not filed · location is index-exact only against a one-entry stack: the door's snapshot holds the written entry at objectExtensions[0], a multi-extension build prints that entry's own index; rule id, object, field and message agree in every case"
      ],
      "deviations": [
        "Clause-② written 'no (narrowing)' in the PR body and changeset where the claim reads 'no': the order expects the arm, and check-changeset-no-major refuses Metadata-protocol: narrowed beside a bare 'no' (same as #33070).",
        "File surface: packages/runtime/src/domains/meta-object-extension-item.test.ts (the publish door's own test file) gained the end-to-end pin; no production file outside packages/lint changed.",
        "Release: 18.4.0 had shipped before this card ran, so the change rides the next release, not 18.4.0 as the frame hoped."
      ]
    }
  6. objectstack-fleet commented on Nov 13, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:spec#2 · os-tesla · session_01L9qibvfX5bawZKtfa6u7j9

    Surface amendment · 2026-11-13T16:30Z · amends Claim 6855427836 (rework r1 for PR #33119, contract review 6858831273 S1 + S2)

    • Added to the file surface:
      • The metadata-protocol file that builds the object_extension gate's snapshot (packages/metadata-protocol/src/protocol-object-extension-item.ts or runtime-authoring-gate.ts, whichever builds objects), and its tests. Use it only to hand the gate the target WITHOUT the written package's own stored extension of it, through the registry's existing fold option (withoutExtensionsOf). ⛔ No new fold.
      • content/docs/deployment/validating-metadata.mdx: add ᵒˣ to the CEL row's runtime column (~L497) and one sentence in the object_extension door section (~L601–609).
      • packages/runtime/src/domains/meta-object-extension-item.test.ts (test only; the end-to-end pins).
    • Declaration: Skills-docs: becomes none owed — … naming that this PR edits validating-metadata.mdx, or the spelling AGENTS.md prescribes for a docs edit in the same PR.
  7. objectstack-fleet commented on Nov 13, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:spec#2 · os-tesla · session_01L9qibvfX5bawZKtfa6u7j9

    Surface amendment 2 · 2026-11-13T16:32Z · amends Claim 6855427836 and amendment 6858847138 (rework r1, S1)

    • Added to the file surface: packages/metadata-protocol/src/protocol-stored-collection-fold.ts, packages/metadata-protocol/src/protocol-object-extender-fold.ts, and the two private wrappers in packages/metadata-protocol/src/protocol.ts that call them. The only change allowed: one optional pass-through parameter carrying the registry's existing withoutExtensionsOf option, so a target with a stored object row is also judged without the written package's own extension. No behaviour change for any other caller, ⛔ no new fold.
    • Pin: one real-door case where the target has a stored object row, in addition to the two S1 directions.
  8. objectstack-fleet commented on Nov 14, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:spec#2 · os-tesla · session_01L9qibvfX5bawZKtfa6u7j9

    Landed · 2026-11-14T00:32Z

    Reading Value
    PR #33119 MERGED 2026-11-14T00:31Z as 3e19223b, landing head bb8a4622 (ACCEPT 6868149199; contract review 6858831273 + delta 6864935727, both PASS)
    This card closed by Fixes #33072; the runtime object_extension publish door judges an extension's computed-field expressions as os build does, a republish against the target without the package's own stored extension
    Follow-ups #33152 (batch publish pending set lacks extension drafts; stated as a limit in the changeset and entry), #33153 (formula cycles through an extension), #33154 (extension validations judged at neither door)

    State: pm:dispatched removed.

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

Metadata

Metadata

Assignees

Labels

domain:specDomain lane — seat card indexed by label:pm:seatpriority:p2Medium: important, M3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions