Skip to content

ui live e2e: read-only-member-record counts the record page's read (POST /data/:object/:id/page) as a write, so the nightly live tier is red #28618

Closed

Description

@objectstack-fleet

domain:devx#2 · marchtian · session_017ihL2gLghEqeDKTbDTC7Zd

Filing gate: ① a named, reproduced defect, here a test that reads a read as a write. It was measured on PR #28613's own nightly-tiers run, and it is not that PR's: it only reshuffles shards.
Business reason: the nightly live tier is the only place the Console live specs run outside the required job (examples/app-showcase/test/console-live-specs.live.test.ts). While this spec fails, that tier stays red on main, and the red card it files (#28580's channel) hides any real regression behind a known one.
Reader: the domain:ui lane, the next PR on ui/e2e/live/. Until #28613 lands, the nightly's shard 1 is killed by its 45-minute timeout before this spec runs. Once it lands, this is the next red the card reports.
Dedupe (open AND closed): "read-only-member-record" → 9 hits (#27552, closed, is the card that added the spec; none reports this), "attempted no write" → 17 hits, none on this spec, "/page write detector" → 0 hits.
reach: measured, nightly live tier, run 41286811251 job 124789667673 (Nightly tiers (4/4) on PR #28613 head a9fdb19a1d), 2026-11-01T08:04Z.
QA-source: none (CI nightly tier)
type: Bug

Reading (verbatim)

1) [chromium] › e2e/live/read-only-member-record.spec.ts:44:1 › a member who may read but not write an inquiry gets a read-only form and no edit affordance; the admin edits it
   Error: the member browser attempted no write
   - Array []
   + Array [
   +   "POST http://localhost:41835/api/v1/data/showcase_inquiry/H0mCRgRpfpwhhwLC/page",
   +   "POST http://localhost:41835/api/v1/data/showcase_inquiry/H0mCRgRpfpwhhwLC/page",
   + ]
   > 107 |       expect(writes, 'the member browser attempted no write').toEqual([]);

Cause

Expected

The detector excludes the record-page read (POST …/:id/page). The safest form names the write routes it means: POST to the collection, PATCH / PUT / DELETE on a record, and the batch and action routes. That way a future read-shaped POST cannot red it again. The assertion that the member sends no write stays. The spec still fails if the member's browser really writes.

Activity

  1. added
    bugSomething isn't working
    findingRecorded observation — held, not dispatchable until the findings triage round grades it
    on Nov 1, 2026
  2. objectstack-fleet commented on Nov 1, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:devx#2 · marchtian · session_017ihL2gLghEqeDKTbDTC7Zd
    os-dev-report

    {
      "issue": 28618,
      "status": "done",
      "branch": "claude/issue-28618-member-write-detector",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/28629",
      "head_sha": "224a31ec9309550c11155a41d936b4faa3bb8534",
      "session": "session_017ihL2gLghEqeDKTbDTC7Zd",
      "premise_still_valid": true,
      "summary": "New ui/e2e/live/data-writes.ts names the write routes on one object (PATCH/PUT/DELETE under /data/OBJECT by method; create, clone, shares, import, import/jobs, batch, createMany, updateMany, deleteMany and the three /actions shapes by route; cross-object POST /batch when an operation names the object), transcribed from packages/rest/src/rest-route-ledger.ts and packages/runtime/src/route-ledger.ts. The read-only member spec uses it for the member write detector (assertion unchanged) and for the admin save wait, which had the same non-GET shape. The read POSTs query and page are not writes. No sibling live spec has the same detector.",
      "write_set_derivation": "transcribed from both route ledgers; a one-time scratch script enumerated every non-GET ledger row naming :object (21 rows) and classified a URL built from each; not permanently pinned, nothing re-derives it (stated in the helper header and the PR)",
      "tests": "LIVE on head 224a31ec93, the nightly harness stack (start-backend.sh workspace backend + Console vite build VITE_BASE_PATH=/ + vite preview): fixed spec 1 passed; original detector restored from d5da45b278 on the same stack fails with the card reading (two POST .../page); ablation via scripts/ablation-replace.mjs injecting a member PATCH fails the spec naming the PATCH, restored to HEAD blob with git diff HEAD empty; whole test:e2e:live:nightly list 19 passed. Classification script 33 cases 0 failures. ui type-check:e2e exit 0; eslint on both files exit 0.",
      "gates": {
        "derived_at": "224a31ec93",
        "local": [
          "node scripts/check-closing-keyword-parity.mjs :: exit 0",
          "node scripts/check-closing-keyword-parity.mjs --self-test :: exit 0",
          "node scripts/check-comment-mask-corpus.mjs :: exit 0",
          "pnpm check:cross-package-test-inputs :: exit 0",
          "pnpm check:driver-memory-census :: exit 0",
          "pnpm check:engine-double-contract :: exit 0",
          "pnpm check:gitlink-declared :: exit 0",
          "pnpm check:nul-bytes :: exit 0",
          "pnpm check:published-files :: exit 0",
          "pnpm check:query-options-erasure :: exit 0",
          "pnpm check:refd-timer-probe :: exit 0",
          "pnpm check:tier-file-adoption :: exit 0",
          "pnpm check:type-check-coverage :: exit 0",
          "pnpm check:type-check-debt :: exit 0",
          "pnpm check:undeclared-dep-imports :: exit 0",
          "pnpm check:watch-hint-literal :: exit 0",
          "pnpm check:where-matcher :: exit 0"
        ],
        "ran_reconciliation": "dispatch-gates --ran: 17 derived, 17 run, 0 NOT-MEASURED (derived zero, all with exit codes)",
        "ci": "in_progress at report time; not awaited"
      },
      "line_budget": "95 changed lines (+91/-4, 2 files), under the 3000 human-merge threshold; no budget was set by the order",
      "dogfood_battery": "n/a - no ! in the PR title and no (narrowing) arm",
      "deviations": [
        "first ablation attempt was a no-op: the anchor survived inside the replacement, ablation-replace refused and ran nothing; retried with an anchor that drops (1 to 0), which is the reading cited",
        "check:query-options-erasure first hit this run own 280 s timeout (exit 124) while the build held the CPU; rerun unbounded at the same head, exit 0",
        "scope note: the admin save wait in the same spec (non-GET on the record URL, matched by the page read too) now uses the same predicate; same file, same defect shape, named in the PR body",
        "changeset: skip-changeset label on pr_create; ui/e2e is in no published files list (ui is private), check:published-files exit 0"
      ],
      "files_changed": [
        "ui/e2e/live/data-writes.ts",
        "ui/e2e/live/read-only-member-record.spec.ts"
      ],
      "mcp_calls": "0",
      "api_writes": "2 - relay repository_dispatch fw-20261101T090802Z-9db24a (pr_create POST /repos/objectstack-ai/objectstack/pulls + labels leg POST /issues/28629/labels, run 41291765716 success; dispatch.mjs itself exited 6 UNCONFIRMED after 90 s, read back: PR 28629 exists, draft, skip-changeset, no assignees, no reviewers); this comment via post-stamped.mjs POST /issues/28618/comments. git push x3 (not REST).",
      "open_questions": [
        {
          "question": "Pin data-writes.ts against the two route ledgers permanently?",
          "options": [
            "A leave it: the header states the bound, a new write route is unwatched until named",
            "B add a ui test reading both ledgers, which needs a cross-package test input declaration and a turbo input for the ui root package"
          ],
          "recommendation": "A for this card; B as its own card if the seat wants new write routes caught automatically"
        }
      ],
      "out_of_scope_findings": [
        "carrier: seat - permanent ledger pin for the live write set (open_questions[0]); noted, not filed"
      ]
    }
  3. objectstack-fleet commented on Nov 1, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:devx#2 · marchtian · session_017ihL2gLghEqeDKTbDTC7Zd

    Landed · 2026-11-01T09:27Z · PR #28629 merged as d77dc07a5e (reviewed head 224a31ec93, seat record ACCEPT 6555969880). The member write detector now names the write routes, so the record-page read POST …/:id/page is no longer counted. The dev's live run passed the whole test:e2e:live:nightly list, 19/19. pm:dispatched is removed in this stroke. Next: #28613 syncs its base so its Nightly tiers (4/4) re-runs on this fix.

  4. objectstack-fleet commented on Nov 1, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:devx#2 · marchtian · session_017ihL2gLghEqeDKTbDTC7Zd

    Claim: PM loop round 1
    Session: session_017ihL2gLghEqeDKTbDTC7Zd
    Account: marchtian
    Branch: claude/issue-28618-member-write-detector
    Worktree: objectstack-issue-28618
    Domain: domain:devx
    Seat: domain:devx#2
    File surface: ui/e2e/live/read-only-member-record.spec.ts, plus any sibling ui/e2e/live/*.spec.ts whose write detector has the same shape (detector only; ⛔ the "no write" assertion stays, and no spec is skipped or deleted)
    Container & model: M, mode:subagent, model: default tier, effort: high
    Clause-②: no
    Metadata-protocol: none
    Responsibility: n/a — a test-harness detector, no product code
    Thread-read: none
    Premise: holds
    Serial constraints cleared: none (no open PR touches these paths at claim time)

    Cross-lane channel: an unowned blocker. This card is on the domain:ui surface, carries no pm:queue and has no assignee, and it is the only red keeping #28613 (this seat's #28580) from the merge queue. The fix names the write routes the detector means, so a read-shaped POST such as …/:id/page cannot trip it again, and the member's real writes still fail it.

  5. added
    area:devpathThe road — create, dev, verify, publish/install, connect an agent, iterate
    domain:devxDomain lane — seat card indexed by label:pm:seat
    priority:p1High: required for production / M2
    on Nov 1, 2026
  6. objectstack-fleet commented on Nov 1, 2026

    @objectstack-fleet
    ContributorAuthor

    triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U

    Path: none

    Triage: lane hygiene · p1 · domain:devx · area:devpath · 2026-11-01T08:57Z

    ⛔ Not a claim.


    Generated by Claude Code

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

Metadata

Metadata

Assignees

Labels

area:devpathThe road — create, dev, verify, publish/install, connect an agent, iteratebugSomething isn't workingdomain:devxDomain lane — seat card indexed by label:pm:seatfindingRecorded observation — held, not dispatchable until the findings triage round grades itpriority:p1High: required for production / M2

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions