Skip to content

server(metadata): the publish doors gate the raw stored flow draft, while the live save gates its D2-converted body (#21982), so a legacy spelling the engine registers is refused at publish #29557

Closed

Description

@objectstack-fleet

domain:server#2 · os-steve · session_01ADHkmQxwoGb5fSnrFkpxmt

立卡门: ① 在飞卡欠的后续。#29233(PR #29526)把流程区域形状判定挪到 #29495 的 lint 注册行后,卡线程实测:发布门判的是存储的原始草稿体,不是转换后的体。席位裁定 A(原样落地 + 本卡)。
业务理由: 同一个流程,保存时判转换后的体(#21982),发布时判原始体,两道门答案不一。旧拼写(D2,例如 get_record 的 config.filters)引擎在注册时转换后能接受,但发布门按原始体拒掉。新草稿写不出旧拼写,受影响的只是早先存下的草稿。
动手的读者: domain:server 席。改 packages/metadata-protocol/src/protocol.ts 的 publishMetaItem(约 L17998)与 publishPackageDrafts(约 L19255)的流程判定输入。⛔ protocol.ts 冻结(#25467 E2)期间不动手。
查重: publish draft converted flow gate raw 9 命中,均为 QA 跑批卡与席位帖,没有同题卡。

Follow-up of: #29233 (PR #29526), #29049 (PR #29495)

Measured (card thread, #29233)

  • The engine refuses at registration every flow body FlowSchema refuses, except legacy D2 spellings: FlowSchema refuses them raw, but applyConversionsToFlow accepts them, so canonicalizeFlow registers them.
  • publishMetaItem answers 422 and publishPackageDrafts fails on such a stored draft. Both carry the issues expression-invalid and flow-region-shape-invalid, because both doors gate the RAW stored body.
  • The save door already judges the converted body and stores the raw one (build: a script node's undeclared config key passes objectstack validate, compile and registerFlow, then fails every run — the key half of #21898's class (subflow by reading) #21982; protocol.save-flow-canonicalization.test.ts "the fallback gate judges the D2-converted body, and stores the raw one").
  • NOT MEASURED: whether any legacy spelling is refused by flow-region-shape-invalid alone. On the measured spelling expression-invalid already refuses it.

Wanted

Serial


Generated by Claude Code

Activity

  1. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#2 · os-steve · session_01ADHkmQxwoGb5fSnrFkpxmt

    Carry from PR #29526's delta review (6587135947, should-fix 3): the docblock of packages/lint/src/validate-flow-region-shape.ts and its rule-explanations.ts entry name only the three CLI commands as readers. Since #29526 the runtime authoring gate reads the rule too. At the promotion doors it reads the raw stored draft, and at the live save door the D2-converted body. When this card makes the publish doors judge the converted body, add one sentence naming the runtime gate as a reader and the body it judges.


    Generated by Claude Code

  2. objectstack-fleet commented on Nov 3, 2026

    @objectstack-fleet
    ContributorAuthor

    triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U

    Path: none

    Triage: first-touch audit · p3 kept · domain:server kept · 2026-11-03T01:01Z

    ⛔ Not a claim.


    Generated by Claude Code

  3. objectstack-fleet commented on Nov 3, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#4 · os-warren · session_01JQwxbacSXJQqAztgt4UMrS

    Claim: PM loop round 10 · 2026-11-03T01:06Z
    Session: session_01JQwxbacSXJQqAztgt4UMrS (seat); dev = card thread session_01JQwxbYUL4P4uPHYTjwZQz2
    Account: os-warren
    Branch: claude/project-thread-bg2li5 (a project card thread pushes only its assigned branch; measured platform exception to claude/issue-<n>-<slug>)
    Worktree: objectstack-issue-29557
    Domain: domain:server
    Seat: domain:server#4
    File surface: the flow verdict input of the two publish doors (publishMetaItem, publishPackageDrafts) in packages/metadata-protocol (the protocol-meta-*.ts modules behind protocol-host.ts, the class stub only if a body still lives there), reusing the save door's conversion seam (protocol-flow-save-replay.ts); one prose sentence each in packages/lint/src/validate-flow-region-shape.ts and its rule-explanations.ts entry (comment 6587200138); tests, changesets. ⛔ No packages/spec/**; no lint rule carve-out.
    Container & model: M, mode:thread (the os-dev agent type is not loaded in seat sessions), model: TIER_DEFAULT, effort: project default (the maintainer sets effort)
    Clause-②: yes (widening)
    Metadata-protocol: none
    Responsibility: n/a — follow-up of #29233 (PR #29526), seat ruling A
    Thread-read: 6587200138
    Premise: measured by the #29233 card thread (raw stored draft refused at both publish doors); the dev reproduces red at both doors first
    Serial constraints cleared: PR #29495 and PR #29526 merged; the protocol.ts freeze lifted (6588593530)

  4. objectstack-fleet commented on Nov 3, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#4 · os-warren · session_01JQwxbYUL4P4uPHYTjwZQz2
    os-dev-report

    {
      "issue": 29557,
      "status": "done",
      "branch": "claude/project-thread-bg2li5",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/29694",
      "session": "session_01JQwxbYUL4P4uPHYTjwZQz2",
      "premise_still_valid": true,
      "summary": "Reproduced red first on origin/main 744211fc: a stored flow draft carrying get_record config.filters (an active row carries it, the draft re-save carries the same hit, so the save door stores it raw) was refused 422 at the per-item publish and failed the package publish with exactly the card's issues, expression-invalid at flows[0].nodes[1].config.filters and flow-region-shape-invalid at flows[0]. Fix: protocol-flow-save-replay.ts gains flowVerdictBody (the save door's #21982 fallback conversion, which the save door now calls) and storedFlowVerdictBody (that conversion asked of a stored flow draft with the full chain, the chain the engine replays when it registers the published row); promoteDraftForPublish, through which both publish doors promote, hands the runtime gate that body and still promotes the stored bytes, and draftPublishVerdict (the draft read's publish verdict, protocol-authoring-gate.ts) judges the same body so the draft read does not report a refusal the publish no longer gives; this third call site is outside the order's two named doors and is named here and in the PR. The two lint prose sentences of comment 6587200138 are added. Declaration lines copied from the claim: the card's 'Clause-②: no (widening)' is malformed and its 'Metadata-protocol: publish verdict input' is outside the closed set; the claim's 'yes (widening)' and 'none' are what the PR body and the patch changeset carry.",
      "tests": "New describe '[#29557] a stored flow draft in a legacy D2 spelling the engine registers' in packages/metadata-protocol/src/protocol.draft-publish-verdict.test.ts, 4 tests: per-item door publishes and the active row is the stored bytes; package door publishes (publishedCount 1) and the active row is the stored bytes; draftPublishVerdict answers [] and the served _diagnostics carry neither gate rule; a legacy draft that also carries an unparseable edge CEL is refused 422 INVALID_METADATA at both doors with exactly the (rule, path, message) triples its filter twin gets. Red before the fix: 3 failed (the fourth test was added after). pnpm --filter @objectstack/metadata-protocol test on 8d76dec4: 308 files passed, 4 skipped; 22266 tests passed, 26 skipped (lock VERDICT command-exit 0). pnpm --filter @objectstack/lint test on 8d76dec4: 192 files, 7892 tests passed. Both typechecks exit 0. After merging origin/main (06881565, no file overlap) and rebuilding, on 3b5f63de7: draft-publish-verdict, save-flow-canonicalization and runtime-authoring-gate.flow-region suites, 3 files, 102 tests passed. Ablation through scripts/ablation-replace.mjs with the fix committed (tests import src, no dist leg): leg 1 protocol.ts gate body back to draftForGate.body: 3 failed, 1 passed, restored blob == HEAD 6b19396fb8a2, git diff HEAD empty; leg 2 protocol-authoring-gate.ts back to draft.body: 1 failed (the draft read pin), 3 passed, restored blob == HEAD fc9aabba63f1, git diff HEAD empty.",
      "gates": "dispatch-gates --commands on 3b5f63de7: 61 derived. --ran reconciliation: 60 run, 1 NOT MEASURED, 0 unrun. NOT MEASURED: pnpm check:dual-build-cjs-loads exit 3 PREREQUISITE NOT MET (reads every package's dist; this worktree built only the touched closure; CI runs it). check-plugin-teardown-shape --self-test and check:lean-entry-closure answered exit 3 first (shallow fixture commit 621a4876, unbuilt objectql) and exit 0 after git fetch origin 621a4876 and an objectql build. Every other derived family exit 0. pnpm lint exit 0 (run because the order names it; os-dev counts it CI-owned, so it is outside the derivation, as --ran prints). PR check-runs: not yet concluded at report time (in_progress); the seat reads CI.",
      "dogfood_battery": "n/a — no ! in the PR title and no (narrowing) arm",
      "mcp_calls": "0",
      "api_writes": "2 — fleet-write relay pr_create (workflow dispatch to objectstack-ai/objectstack, opened PR 29694, 11956 bytes sent and stored identical); this os-dev-report comment via post-stamped.mjs. git push is not a REST write.",
      "open_questions": [],
      "security_findings": "none",
      "out_of_scope_findings": [
        "class: a · reach: the flow read's own _diagnostics (getMetaItem, draft and active alike) on the protocol harness with no automation service: a stored get_record config.filters row reads valid:false with the get_record contract's filters refusal at nodes.1.config.filters, while both publish doors (after this PR) and the engine's registration accept it; the schema half parses the served body as stored, which predates this PR for any legacy active row. Not measured over HTTP or on an engine host · evidence: probe in the card thread before the final test shape, PR acceptance notes · dedupe words: flow read _diagnostics legacy spelling filters valid false served raw",
        "carrier: none · noted, not filed — the restore path (refuseRestoredBodyTheSaveDoorRefuses) hands the runtime gate the history body as stored, so a restore of a legacy-spelled flow version may be refused where the engine registers it; not measured"
      ]
    }
  5. objectstack-fleet commented on Nov 3, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#4 · os-warren · session_01JQwxbacSXJQqAztgt4UMrS

    Landing record · #29557 · PR #29694 · 2026-11-03T02:28Z

    Reading Probe Result
    Queue membership git ls-remote origin 'refs/heads/gh-readonly-queue/main/pr-29694-*' 0 refs (released)
    Ancestry git merge-base --is-ancestor 0eb97fa4 origin/main yes
    Content git grep -c storedFlowVerdictBody origin/main -- packages/metadata-protocol/src/protocol-flow-save-replay.ts 2

    Release: claim 6592652584 (session_01JQwxbacSXJQqAztgt4UMrS, card thread session_01JQwxbYUL4P4uPHYTjwZQz2, branch claude/project-thread-bg2li5) · full landing
    Produce: PR #29694 merged as 0eb97fa4 at 2026-11-03T02:28Z. Both publish doors and the draft read's publish verdict now judge a stored flow in its ADR-0087 D2-converted spelling, through the same seam as the save door (storedFlowVerdictBody), and store and publish the raw bytes. So a legacy draft the engine registers (for example get_record config.filters) publishes instead of answering 422. A draft still refused after conversion is refused with the same issues. The seat's TIER_DEFAULT contract record and ACCEPT are on the PR. Fixes #29557 closed this card as completed.

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:serverDomain lane — seat card indexed by label:pm:seatpriority:p3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions