Skip to content

plugin-approvals: the request and action list views show an Object column with the target object's API name (object_name, such as showcase_announcement), the type half of the record pointer pair, drawn as plain text #24501

Closed

Description

@objectstack-fleet

Filing gate ①, class (a): a user-visible machine name with a named producer on a served surface. This is the list-view position of the family #24264, #24281 and #24375 closed on the approval request page. Found by #24375's dev (report on #24375, out-of-scope finding 1; PR #24500). Filed by domain:services seat 2 (seat post #21118) · os-warren · session_01LR1cD9JqgkeqY7k9rrZH8s. ⛔ Not a claim. Grade, lane and area:* are triage's.

Dedupe

Dedupe words: approval request list Object column API name; object_name list view column showcase_announcement; sys_approval_action recent all_actions object_name column; referenceVia type half plain text grid.


Generated by Claude Code

Activity

  1. objectstack-fleet commented on Oct 19, 2026

    @objectstack-fleet
    ContributorAuthor

    Triage: p2 · domain:services · area:workflow · pm:queue · triage seat · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-19T08:55Z

    Triage seat (objectstack-wide, seat post #6015). ⛔ Not a claim, ⛔ not a dispatch.


    Generated by Claude Code

  2. objectstack-fleet commented on Oct 19, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 2 · 2026-10-19T09:29Z
    Session: session_01LR1cD9JqgkeqY7k9rrZH8s
    Account: os-warren (the seat's linked user as GET /user answers it; always the card's assignee)
    Branch: claude/issue-24501-approval-list-object-column
    Worktree: objectstack-issue-24501
    Domain: domain:services
    Seat: domain:services#2 (seat post #21118)
    File surface: packages/plugins/plugin-approvals/src/sys-approval-request.object.ts (the four list views' columns) and sys-approval-action.object.ts (the recent and all_actions views' columns), with the pins beside them; on the label route only, the served label column and its writer and backfill in the same two object files plus approval-service.ts's row builders, declared before any edit; a changeset; ⛔ not approval-node.ts, and ⛔ not approval-service.ts on the drop route; ⛔ not objectstack-ai/objectui, ⛔ not packages/spec/** (stop on breach; explain in the report)
    Container & model: M, mode:subagent, model: opus (the default tier; dispatch-gates --tier printed no path-derived mandate for this surface)
    Clause-②: no
    Responsibility: plugin-approvals' list views, which declare object_name as a column beside the record_id pointer (this lane) | none: the pointer cell draws the record, and the separate column draws the stored API name | every user of the approval request and Action History lists in the console; live today
    Thread-read: 6263481224
    Serial constraints cleared: PR #24500 (#24375), which edited sys-approval-request.object.ts, landed as 666283aeae, the order triage set (6263481224). No open PR among the 11 touches plugin-approvals (file scan at this claim). Of the 14 pm:dispatched claims, only #24497's (domain:engine) names plugin-approvals, and only as a fallback on the producers (approval-service.ts, approval-node.ts), which this claim keeps out of the drop route. #24321 (seat 1's next, pm:queue) may reach approval-service.ts's decision path, not the object files.


    Generated by Claude Code

  3. objectstack-fleet commented on Oct 19, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 24501,
      "status": "needs_decision",
      "branch": "claude/issue-24501-approval-list-object-column",
      "pr": null,
      "session": "session_01LR1cD9JqgkeqY7k9rrZH8s (subagent: the dispatching seat's session)",
      "premise_still_valid": true,
      "summary": "Not built: the drop route that triage and the dispatch name would break the cell it relies on. The console's list rows carry only the view's `$select`, and objectui builds that from the view's `columns` plus fixed harvests, never from the `referenceVia` sibling. So dropping `object_name` from `columns` leaves `record_id` half-addressed, and the Record column draws the raw record id (objectui's own control case), losing the target's icon and name. Any route that removes the machine-name column (drop or label) needs the type half projected some other way, which is wider than this card's surface. The options and the recommendation (objectui harvests the sibling, then this card drops the column) are in `open_questions`; no PR, no file changed.",
      "readings": {
        "tree": "objectstack `origin/main` `6b42b6bc8` (`666283aea` plus `820fd5aef` and `6b42b6bc8`, which touch only plugin-approvals' CHANGELOG.md and package.json); objectui `.objectui-sha` = `4016370af3c9`, read with `git show PIN:path`; objectui `main` `6f877f1df4` (09:17Z) re-read for the two projection builders. These are static readings, not a screen reading: this container has no console build (`packages/console/dist` is absent).",
        "A1_holds": "`sys-approval-request.object.ts` lists `object_name` beside `record_id` in `all_requests` :100, `my_pending` :109, `submitted_by_me` :123 and `completed` :133. `sys-approval-action.object.ts` does the same in `recent` :57 and `all_actions` :77; `by_actor` :67 does not.",
        "A2_what_the_cell_draws": "`RecordPointerCell.tsx` (header :22-:31, render :277, :309): in the readable state it draws the target object's icon and the record's name, linked, with the raw id as the tooltip. No object label text is drawn. In the unreadable state it draws 'LABEL · record unavailable'. All six showcase approval targets declare an icon (project, invoice, expense_report, task, field_zoo, announcement). So the cell itself tells a reader which kind of record a row is about, through the icon, and the Flow column (`process_label`) mostly names the subject too: 'Project Budget Approval', 'Expense Report Sign-off', 'Announcement Dynamic Approval'.",
        "A2_what_the_cell_needs": "`resolveRecordPointer` (`fields/src/index.tsx` :3306-:3308) reads the type half from the ROW (`row[via]`) and returns null when it is absent or blank. The grid then draws the stored text, which is the raw id; objectui pins this as 'a half-addressed row keeps the stored text (control)', `ObjectGrid.recordPointerCell-12608.test.tsx` :141. The row carries only the projection. `ListView.tsx` `selectFields` (:2920-:3265) is `id` + authored `columns` (FLS-filtered) + `$expand` roots + harvests for view bindings, grouping, row colour, deadlines, predicates and the concurrency token. It has no `referenceVia` arm. `ObjectGrid.tsx` `getSelectFields` (:2620-:2875, `extraFields` :2842) has the same harvests and no `referenceVia` arm either; objectui `main` `6f877f1df4` is unchanged in both. The adapter forwards `$select` (`data-objectstack/src/index.ts` :4934), and objectstack's data door projects it. `packages/objectql/src/declared-fields.ts` :30-:34 records list rows as the view's `$select` projection, 'sparse, permanently', by decision. Setup's request and action lists read through that door: `routeApprovalRecordReads` routes only a `findOne` of a request and one request's timeline, per the `approvalRequestsDataSource.ts` header. The inbox page (`ApprovalsInboxPage.tsx`) is bespoke, draws `object_label || object_name`, and does not use these views.",
        "A2_verdict": "Dropping `object_name` from `columns` takes it out of `$select`. Every Setup list row then reaches the cell without its type half, and the Record column changes from 'icon + record name' to the raw record id. That loses what a user reads, and loses it in the record column, not the object column. Triage's premise 'where the `record_id` pointer cell already names the record' holds only while the type half is projected.",
        "A3": "No declared rule or pin binds list `columns` to `highlightFields`; `sys-approval-request.page.ts` and its pin read `highlightFields` and the page's own timeline columns only. One pin binds the action lists to the pair: `approval-list-display-labels.integration.test.ts` :291 asserts `recent` and `all_actions` contain `object_name`, `record_id` and `acted_as_label` (#23889's case (f)). Any drop route rewrites that line. No lint rule or `scripts/` gate reads `referenceVia` against list columns.",
        "hiddenFields_probe": "`ListView` subtracts `hiddenFields` only from the drawn set (`effectiveFields` :3780). Its own `$select` reads `schema.columns` before that subtraction, so `hiddenFields: ['object_name']` would keep the type half fetched on that path. But `ListView` hands the grid `fields: effectiveFields` (:3943), and a grid that owns its grouped fetch (`gridOwnsGroupedFetch` :2590) builds `$select` from those fields (`ObjectGrid.tsx` :2872). On that path the type half is not fetched and the cell draws the raw id. Two fetch paths give two answers for one declaration."
      },
      "tests": "None run: no file changed, so there is no behaviour to test and no ablation. Every claim above is a static reading at the named trees, with file:line.",
      "gates": "`node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` at `6b42b6bc8`: exit 2, 'this branch changes nothing against origin/main (merge base 6b42b6bc8) — nothing to derive'. 0 derived, 0 run, so there is nothing to reconcile with `--ran`. No PR, so no check-runs to cite.",
      "line_budget": 0,
      "files_changed": [],
      "deviations": [
        "No PR and no changeset: the route was falsified before the first edit (rule 6). The branch is pushed empty at `origin/main` `6b42b6bc8`, as the write-route probe and the claim's landing marker.",
        "The verdict rests on static readings, with objectui's own pinned control case. The browser screen reading is NOT MEASURED, reason: there is no console build in this container, and one at the pin needs objectui's console build plus the showcase closure.",
        "Card, thread, #24375 and PR #24500 were read with single-resource `gh api` REST reads. objectui `main`'s head and two files were read through the commits and contents APIs. That is 7 reads in all, and none was an MCP call."
      ],
      "mcp_calls": "0",
      "api_writes": "1 — POST /repos/objectstack-ai/objectstack/issues/24501/comments (this report, through `scripts/pm/post-stamped.mjs` on the fleet relay). `git push` of the empty branch is not a REST write.",
      "open_questions": [
        {
          "question": "Which route takes the target object's API name out of the six approval list views (request `all_requests`, `my_pending`, `submitted_by_me`, `completed`; action `recent`, `all_actions`)? Measured: the `record_id` pointer cell resolves only while `object_name` is in the list's `$select`, and objectui projects only shown columns plus fixed harvests.",
          "options": [
            "A: objectui harvests the `referenceVia` sibling of every projected pointer column into `$select`, in both `ListView.selectFields` and `ObjectGrid.getSelectFields`, behind the declared-field and FLS-readable gates its grouping, row-colour and deadline harvests use. It is pinned beside objectui#12608's cases: a list whose columns omit the type half still draws the record. The console pin then moves (with the SDUI manifest regenerated), and #24501 drops `object_name` from the six `columns` and rewrites pin (f) line 291. #24501 is Blocked-by the objectui card, because landing the drop before the pin moves turns every Setup list's Record column into raw ids. Effort: one small objectui PR (two projection builders and one test), one pin bump (it can ride a scheduled one), then a diff here of about ten lines plus the changeset. Cost: three landings in order.",
            "B: keep `object_name` in `columns` and add `hiddenFields: ['object_name']` to the six views. This is objectstack only, inside this card's surface, about six lines. Measured cost: it holds only on ListView's own fetch. A grid that owns its grouped fetch projects the effective (post-hiddenFields) fields and draws raw ids. Any objectui change that stops fetching hidden columns reverts every row silently, with no gate to see it. The declaration says 'hide' and means 'fetch for another column's renderer'.",
            "C: the label route. Declare an `object_label` column on both objects, written in `openNodeRequest` and `actionRow`, filled by a boot backfill, carried in four bundles, and shown in place of `object_name`. Removing `object_name` from `columns` breaks the pointer exactly as above, so C needs A or B as well. It also inherits PR #24500's objections: a stored snapshot beside the approvals get's live `object_label`, which goes stale when the object is relabelled. Widest effort.",
            "D: no change now. Park #24501 until A lands. The machine name stays visible in the six lists meanwhile."
          ],
          "recommendation": "A. By the four axes. Real need: the readers are admins on Setup's Approvals Requests (4 views) and Action History (2 views). A keeps the Record cell (icon + name, or 'LABEL · record unavailable') and removes only the machine-name column. Three sibling objects draw the same machine-name Object column for the same pointer reason (`sys_audit_log` 5 views, `sys_record_share` 6, `sys_share_link` 4), and A unblocks their drops with no further console change. Long-term: A is contract-first, because the renderer fetches what a declared `referenceVia` needs, in the harvest shape the list already uses four times. B holds on one fetch path of two. C adds a second answer for one fact. Making AI mistakes harder: after A, an author who lists an id half without its type half still gets the record, so the trap is gone structurally. Under B, removing the 'unused' hidden column, or grouping the list, silently reverts to raw ids. Startup focus: A adds no column, writer, backfill or gate. B is the cheapest, but it is a staged workaround that 过渡也从紧 rules out. C is the widest. Excluded rather than offered: the console drawing the `object_name` column by its object's label. That is the console-side mapping #24375's carried constraint forbids, since the served list would still declare a machine-name column."
        }
      ],
      "out_of_scope_findings": [
        "carrier: #24501 (this decision) · objectui's list projection never asks for a `referenceVia` pointer's type half, so a list view that shows the id half without its sibling draws the raw id (`ListView.tsx` :2920-:3265, `ObjectGrid.tsx` :2620-:2875 at pin `4016370af3c9`, unchanged on objectui `main` `6f877f1df4`). Dormant today: every pointer-pair list view in this repository lists both halves. It goes live the moment option A's drop, or option C, lands without the harvest. Under option A the seat files it in objectui with a back-link, and #24501 carries `Blocked-by:`. Dedupe words: referenceVia sibling select projection list; record pointer half-addressed raw id list; ListView selectFields harvest pointer type half; ObjectGrid getSelectFields referenceVia.",
        "class: a · reach: named producer: `packages/plugins/plugin-audit/src/objects/sys-audit-log.object.ts` :53, :63, :108, :124, :140; `packages/plugins/plugin-sharing/src/objects/sys-record-share.object.ts` :58, :67, :80, :92, :102, :112; `packages/plugins/plugin-sharing/src/objects/sys-share-link.object.ts` :60, :70, :80, :90 · evidence: each view lists `object_name` (a `Field.text` labelled 'Object' that holds the target's API name) as a column, and the console draws it as the stored string. This is the same family and the same pointer constraint as #24501, so it is not a single-point card: fold it into whichever card carries this decision for the family. Dedupe words: audit log list Object column API name; record share list object_name column; share link list object_name machine name; pointer pair type half list column."
      ]
    }

    Generated by Claude Code

  4. objectstack-fleet commented on Oct 19, 2026

    @objectstack-fleet
    ContributorAuthor

    Seat answer and Release · domain:services seat 2 · os-warren · session_01LR1cD9JqgkeqY7k9rrZH8s · 2026-10-19T09:46Z
    Release: session_01LR1cD9JqgkeqY7k9rrZH8s releases claim 6264078420 · reason: the route's premise is falsified (dev report 6264306454) · destination: pm:blocked behind objectstack-ai/objectui#13036 · the branch claude/issue-24501-approval-list-object-column sits empty at origin/main 6b42b6bc8, so the next claim may reuse it or cut fresh (Resume-from: none).

    The dev's needs_decision, answered by the seat: route A. This is a lane call, not a maintainer question. It restores a declared invariant, that a referenceVia pointer resolves, and orders the technical tasks. No option differs in product semantics or in a public contract's shape. The maintainer can veto in the round report.

    • What the dev measured, re-read by the seat at objectui pin 4016370af3c9:

      • ListView.tsx and ObjectGrid.tsx have no referenceVia arm in their $select builders.
      • resolveRecordPointer reads row[via] (packages/fields/src/index.tsx about :3306).
      • The pinned control "a half-addressed row keeps the stored text" sits at ObjectGrid.recordPointerCell-12608.test.tsx:141.

      So triage's drop route (6263481224, "where the record_id pointer cell already names the record") holds only while the type half is projected. Dropping object_name alone would turn the Record column into raw ids.

    • Why A, by the four axes:

      • Real need: admins read Setup's Approvals Requests and Action History lists. A keeps the Record cell (icon and name, or "LABEL · record unavailable") and removes only the machine-name column.
      • Long term: the renderer fetches what a declared referenceVia needs, in the harvest shape its lists already use. That is contract-first.
      • Harder to get wrong: an author who lists an id half without its sibling still gets the record.
      • Startup scope: no new column, writer, backfill or gate.
    • Why not the others:

    • Order: plugin-list / plugin-grid: a list's $select never asks for a referenceVia pointer's type half, so a list view that shows the id half without its sibling column draws the raw record id objectui#13036 adds the harvest in both projection builders, with pins. objectstack's .objectui-sha then moves past it; the pin moving is the install. Then this card drops object_name from the list views' columns. Landing the drop before the pin moves breaks every one of these lists. The body carries Blocked-by: objectstack-ai/objectui#13036. The unlock also reads .objectui-sha past that fix, not only the closure.

    This card now collects the family (the dev's out-of-scope finding 2; one card for the family, not a card per object). The positions, read at origin/main 6b42b6bc8 by the dev, each listing object_name (a Field.text labelled "Object" holding the API name) as a list column:

    • plugin-approvals/src/sys-approval-request.object.ts: all_requests :100, my_pending :109, submitted_by_me :123, completed :133.
    • plugin-approvals/src/sys-approval-action.object.ts: recent :57, all_actions :77.
    • plugin-audit/src/objects/sys-audit-log.object.ts: :53, :63, :108, :124, :140.
    • plugin-sharing/src/objects/sys-record-share.object.ts: :58, :67, :80, :92, :102, :112.
    • plugin-sharing/src/objects/sys-share-link.object.ts: :60, :70, :80, :90.

    At re-dispatch:

    • The claim re-reads those lines.
    • It checks whether each view has a referenceVia id half to keep.
    • It checks the C2/C3 cutover epic's declared territory ([epic] ADR-0131 — total organization ownership: no NULL organization_id (v18 line) #15194) for the two plugin-sharing object files.
    • An enumerating pin holds the result across all five objects: no list view lists a pointer pair's type half as a column. The approvals pin approval-list-display-labels.integration.test.ts:291, which asserts the pair in recent / all_actions, is rewritten.

    Generated by Claude Code

  5. objectstack-fleet commented on Oct 19, 2026

    @objectstack-fleet
    ContributorAuthor

    State change · pm:blocked → pm:on-hold · domain:services seat 2 · os-warren · session_01LR1cD9JqgkeqY7k9rrZH8s · 2026-10-19T13:45Z
    Restart-when: objectstack origin/main's .objectui-sha has objectui fe11eb12e578fe38cff8ba454de6507bd99daa2a (PR objectstack-ai/objectui#13042, the fix for objectstack-ai/objectui#13036) as an ancestor
    Restart-touch: .objectui-sha


    Generated by Claude Code

  6. objectstack-fleet commented on Oct 19, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 4 · 2026-10-19T14:27Z
    Session: session_01LR1cD9JqgkeqY7k9rrZH8s
    Account: os-warren (the seat's linked user as GET /user answers it; always the card's assignee)
    Branch: claude/issue-24501-approval-list-object-column
    Worktree: objectstack-issue-24501
    Domain: domain:services
    Seat: domain:services#2 (seat post #21118)
    File surface: the list views' columns in packages/plugins/plugin-approvals/src/sys-approval-request.object.ts, sys-approval-action.object.ts, packages/plugins/plugin-audit/src/objects/sys-audit-log.object.ts, packages/plugins/plugin-sharing/src/objects/sys-record-share.object.ts and sys-share-link.object.ts, the pins beside them (including approval-list-display-labels.integration.test.ts's pair line), and a changeset; ⛔ not approval-service.ts / approval-node.ts (#24321 and #24519 hold them), ⛔ not objectstack-ai/objectui, ⛔ not .objectui-sha (stop on breach; explain in the report)
    Container & model: M, mode:subagent, model: opus (the default tier; dispatch-gates --tier printed no path-derived mandate for this surface)
    Clause-②: no
    Responsibility: the five objects' list views, which declare a pointer pair's type half (object_name, an API name) as a shown column (this lane) | objectstack-ai/objectui#13036 (closed): objectui PR #13042 (fe11eb12e5) now fetches the type half without the column | every Setup user of these lists; live today
    Thread-read: 6268722760
    Serial constraints cleared: no open PR touches any of the five object files (file scan of all 11 open PRs at this claim). No pm:dispatched claim names them: #24421 (plugin-sharing) holds sharing-rule-service.ts, and the C2/C3 epic territory (#15194) names sharing-rule-service.ts, the bootstrap seeder and sharing-plugin.ts's boot region, not these object files. Landing waits on the pin: the PR stays draft until objectstack's .objectui-sha has objectui fe11eb12e5 as an ancestor, because a drop before then draws raw ids in these lists. That condition replaces the hold's Restart-when: line, which leaves the body in this act.

    State change, recorded here: pm:on-hold → pm:dispatched. The maintainer asked why dispatch had stopped ("为什么不继续派发"). The pin wait now governs landing only, and the work is written now.


    Generated by Claude Code

  7. objectstack-fleet commented on Oct 19, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 24501,
      "status": "done",
      "branch": "claude/issue-24501-approval-list-object-column",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/24600",
      "session": "session_01LR1cD9JqgkeqY7k9rrZH8s (subagent: the dispatching seat's session)",
      "premise_still_valid": true,
      "summary": "Route A's second half is done: `object_name` (the target object's API name) leaves `columns` in the 20 list views where it sat beside its `record_id` pointer id half. They are request 4, action 2, audit log 4, record share 6 and share link 4. `sys_audit_log.config_changes` lists `object_name` without an id half, so it is not this pattern and is left as is. Each package gains an enumerating pin: no list view shows a `referenceVia` sibling beside its id half, and the family's views still show the id half. Pin (f) is rewritten to the new contract. Draft PR #24600 is parked, because objectstack's `.objectui-sha` (`4016370af3c9`) does not yet have objectui `fe11eb12e5` as an ancestor (exit 1; the control leg `4016370af3c9~30` gave exit 0).",
      "readings": {
        "A1": "Confirmed on `origin/main` `de4352460`. All 20 views list `object_name` immediately before `record_id`, and `record_id` declares `referenceVia: 'object_name'` on each object: request :263, action :154, audit log :321, record share :172, share link :168. `sys_approval_action.by_actor` never listed it. `sys_audit_log.config_changes` (:124) lists `object_name` with no `record_id`. Its rows are `config_change` (`sys_setting` or `sys_platform_setting`, `record_id: null`) and `import` (`sys_user`, no `record_id`). That view is reported and left as is.",
        "A2": "Holds, read from objectui `fe11eb12e5` with `git show` (read only). `ListView.tsx` `selectFields` loops over the FLS-surviving `cols` and adds `objectDef.fields[c].referenceVia` through `addSpeculative`. That covers ListView's own fetch. `ObjectGrid.tsx` `getSelectFields` adds a `referenceViaFields` harvest (shown columns, `passesProjectionGate`, `isProjectableField`) into `extraFields`. That covers the grid-owned grouped fetch and a standalone `object-grid`. `fe11eb12e5` is an ancestor of objectui `origin/main` `8aa8e3e1e5` (exit 0), and both arms are present there.",
        "A3": "Done. Case (f) now asserts `arrayContaining(['record_id', 'acted_as_label'])` and `not.toContain('object_name')` for `recent` and `all_actions`.",
        "pin_state": "`.objectui-sha` is `4016370af3c9`, committed at 03:42Z; the fix was committed at 11:29Z. In the shallow objectui clone, `git merge-base --is-ancestor fe11eb12e5 4016370af3c9` gave exit 1. On the same clone, the control `4016370af3c9~30` (`b5153f44ea`) gave exit 0."
      },
      "tests": "All runs are at `c62273124` and went through `os-verify-lock.sh`. (1) Builds: the three packages' dependency closure gave VERDICT command-exit 0, and the three packages themselves gave VERDICT command-exit 0. (2) `pnpm --filter @objectstack/plugin-approvals exec vitest run --maxWorkers=2`: Test Files 81 passed (81), Tests 1114 passed (1114), exit 0. (3) plugin-audit had 56 files and 899 tests pass; plugin-sharing had 49 files and 1163 tests pass. Both exited 0 (VERDICT command-exit 0). (4) Typecheck: `pnpm --workspace-concurrency=1 --filter` over the three packages, `run typecheck`, gave VERDICT command-exit 0. check:test-typecheck was OK for approvals (324 errors over 8 files, unchanged), audit (0) and sharing (3 errors over 2 files, unchanged). (5) Ablation ran through `scripts/ablation-replace.mjs` in wrap mode at the committed HEAD, one leg per package. Each leg put `object_name` back: sharing `all_shares`, audit `record_views`, approvals `all_requests`. Each mutation landed (anchor x1 to x0, blob changed). Each turned exactly one test red, `no list view shows a referenceVia sibling beside its id half` (`expected [ Array(1) ] to deeply equal []`), with vitest exit 1, 1 and 1. Each file was restored to blob == HEAD with an empty `git diff HEAD`. The tests import the objects by relative src path, so no rebuild was needed.",
      "gates": "Local: `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` ran at `c62273124` with no paths (merge base `de4352460`) and derived 67 commands. A runner recorded each exit code before any pipe. On the first pass 65 exited 0. `pnpm check:i18n` and `pnpm check:dual-build-cjs-loads` exited 3 (PREREQUISITE NOT MET). After a full `turbo run build --filter='!@objectstack/docs'` under the lock (VERDICT command-exit 0), both re-ran with exit 0. `--ran ran-final.list` exited 0: '67 derived, 67 run, 0 NOT-MEASURED, 0 UNRUN'. CI: all 31 check-runs on PR head `c62273124` were `queued` at report time (in_progress). They include the Lint & Repo Gates lanes, the Type Check lanes, Test Core 1-6/6, Build Core, Check Changeset and Governed Surface Queue Guard. None had concluded.",
      "line_budget": 253,
      "files_changed": [
        ".changeset/24501-list-object-column.md",
        "packages/plugins/plugin-approvals/src/approval-list-display-labels.integration.test.ts",
        "packages/plugins/plugin-approvals/src/sys-approval-action.object.ts",
        "packages/plugins/plugin-approvals/src/sys-approval-request-pointer-pair.test.ts",
        "packages/plugins/plugin-approvals/src/sys-approval-request.object.ts",
        "packages/plugins/plugin-audit/src/objects/sys-audit-log.object.ts",
        "packages/plugins/plugin-audit/src/sys-audit-log-pointer-pair.test.ts",
        "packages/plugins/plugin-sharing/src/objects/sys-record-share.object.ts",
        "packages/plugins/plugin-sharing/src/objects/sys-share-link.object.ts",
        "packages/plugins/plugin-sharing/src/sharing-pointer-pairs.test.ts"
      ],
      "deviations": [
        "pr_create through the relay exited 6 (UNCONFIRMED): run 39280081714 still read `queued` after 300 s. No second dispatch was sent. A read of the target confirms PR #24600: created by objectstack-fleet[bot] at 15:43:23Z, draft, assignee os-warren, head `c62273124`. The read-back body matches the sent body byte for byte, apart from the reader's trailing newline.",
        "The enumerating pin is three per-package pins, not one file. The five objects live in three packages, and a single file would need cross-package imports outside the claimed surface. Each pin enumerates its whole package: approvals reads the `ApprovalsServicePlugin` manifest, and audit and sharing read `objects/index.ts`. So a list view added later is judged too.",
        "Worktree: the local branch already existed at `6b42b6bc8`, left by the first dev and equal to the remote. The worktree was added on it and fast-forwarded to `origin/main` `de4352460` instead of being created with `worktree add -b`. No force-push.",
        "`test:repo` was not run locally: the derivation does not name it, so it is declared to CI (Test Core). The dogfood battery was not run, because it is not a PR check (it runs in main's push battery).",
        "Browser reading NOT MEASURED. The bundled console at the pin predates the fix, and a reading against objectui `main` needs an objectui worktree build. That reading belongs to the unlock.",
        "Attribution follows AGENTS.md: the commit carries the model-free `Claude-Session` / `Co-authored-by` pair, and the PR body ends with the session-URL footer form. The harness reminder's model-named trailer and other footer form were not used; AGENTS.md outranks the reminder, as the reminder itself states.",
        "A shell slip, contained. The first attempt to compose this report used an unquoted heredoc, so bash ran the backtick spans in the text as commands, from `/home/user` (not a git repository). None of them reached a write: the relative `scripts/pm/*` paths did not resolve, `git` refused outside a repository, `POST` was not found, and pnpm rejected the typecheck spelling. One `pnpm --filter @objectstack/plugin-approvals exec vitest run` was started from `/home/user` outside the lock. No vitest results were written in any checkout after it (the newest `results.json` is this worktree's, from 15:02), and no process of it remains. `/home/user` and the shared checkout's `git status` are unchanged. The report was then written from a file."
      ],
      "mcp_calls": "0",
      "api_writes": "2 relay dispatches, each a `POST /repos/objectstack-ai/objectstack/dispatches`, sent through `scripts/pm/with-fleet.sh --via dispatch` and `scripts/pm/post-stamped.mjs`. They executed: (1) `POST /repos/objectstack-ai/objectstack/pulls` (draft, opened #24600) and `POST /repos/objectstack-ai/objectstack/issues/24600/assignees` (os-warren); (2) `POST /repos/objectstack-ai/objectstack/issues/24501/comments` (this report). The branch was also pushed twice with `git push`, which is not a REST write.",
      "open_questions": [],
      "out_of_scope_findings": [
        "class: a · reach: named producer (static reading, not a screen reading) · evidence: same family as #24375 and this card. These served surfaces still name a pointer's target by its API name, outside the list `columns` this card covers. `sys-record-share.object.ts`: :45 `titleFormat: '{object_name}/{record_id} → {recipient_id} ({access_level})'`, with no `nameField`, so it is the record title; :46 `highlightFields` lists `object_name`; the `by_object` view groups and sorts on `object_name`, so its group header reads the API name. `sys-share-link.object.ts`: :51 `titleFormat: '{object_name}/{record_id} ({permission})'`, with no `nameField`; :52 `highlightFields`. `sys-audit-log.object.ts`: :44 `titleFormat: '{action} · {object_name}'` (its `nameField` is `action`); :45 `highlightFields`; `config_changes` lists `object_name` with no id half. Line numbers are after this PR. This is a family finding, not a single-point card: fold it into whichever card carries the family's record-page and grouping positions. The record-page half follows #24375's route, where the Details tab's pointer card names the object by its label. The `config_changes` and `by_object` positions need a decision, because no label column exists to show or to group by. Dedupe words: record share title format object_name record_id; share link highlightFields object_name; record shares by object grouping API name; audit log config changes Object column sys_setting."
      ]
    }

    Generated by Claude Code

  8. objectstack-fleet commented on Oct 19, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed · domain:services seat 2 · os-warren · session_01LR1cD9JqgkeqY7k9rrZH8s · 2026-10-19T23:20Z

    Reading Value
    .objectui-sha on main 12dc7b47c340 (PR #24660, #24644), which carries objectui fe11eb12e5 (git merge-base --is-ancestor, exit 0): the list projection fetches a referenceVia pointer's type half
    PR #24600 merged through the merge queue, tested there on that pin: auto_merge_enabled 2026-10-19T22:56Z → added_to_merge_queue 2026-10-19T22:59Z → merged 2026-10-19T23:20Z
    origin/main merge commit 92ce3af404 is an ancestor (git merge-base --is-ancestor, exit 0)
    This card closed completed by the PR's Fixes #24501; this act clears pm:dispatched and the assignee

    ACCEPT 6271464866 is on the PR. The record-page and grouping half of this family is #24611.


    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

No one assigned

    Labels

    area:workflowApprovals and automation — the work that runs without a person driving itdomain:servicespriority:p2Medium: important, M3

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions