You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
objectstack-ai/gallery: a read-only check workflow on every PR (index schema, complete app directories, no stray files) and a PR-only main, before the scheduled export writes there #31122
Filing gate: ② follow-up of #30349, the second half of the maintainer's write-path ruling D2 (2026-11-06 14:53Z). ⛔ Not a claim. The change lands in objectstack-ai/gallery, a repository the maintainer owns, not in this repo. This card tracks it here because the gallery has no fleet lane.
Business reason. Under D2, a scheduled Claude Code task (#31121) opens one PR on the gallery per stable release, and the maintainer merges it with one click. That click is safe only if the PR has already been checked mechanically. Otherwise a half-written export, a stray .env or node_modules, or an index.json entry that points at nothing would go out on the public gallery. After three clean runs the maintainer may switch the task to pushing main directly (D1). The same check then becomes the only gate.
Wanted (in objectstack-ai/gallery)
A workflow on pull_request with read-only permissions that fails the PR when any of these is true:
index.json does not match the schema the exporter writes (packages/qa/scenarios/src/export/ here);
an index.json entry has no complete apps/<scenario>/ directory (source, run record, screenshots, transcripts), or an app directory is not listed;
any .env*, node_modules/ or absolute local path appears;
framework.version is not a published stable @objectstack/cli version.
The check logic is best kept as an export-gallery --check DIR mode here, so the exporter and the check cannot drift. The workflow then only installs and runs it.
Branch protection on main: PR only, with the check required. The maintainer sets this; it is a setting, not code. Under D1, later, it is relaxed only for the task's identity.
A short note in the gallery README: the content is generated, a PR from the scheduled task is the normal path, and hand edits belong in apps/README.md only.
Depends on
The maintainer adds objectstack-ai/gallery to this project's environment resources. Until then, no session here can read or write it.
export-gallery --check (item 1) can land here before the gallery workflow exists.
Level: QA tooling plus a repository setting. Clause-②: no, Metadata-protocol: none.
Dedupe (open and closed): "gallery check workflow", "gallery index.json schema" and "gallery branch protection" turned up only #30349 itself. New.
The second half of ruling D2: a read-only check workflow on every PR to objectstack-ai/gallery (index schema, complete app directories, no stray files), plus a PR-only main. The change lands in objectstack-ai/gallery, a repository the maintainer owns and outside this board's repos. This card tracks it because the gallery has no fleet lane.
p2, domain:devx, pm:queue kept. Branch protection on the gallery's main is a repository setting that only its owner can apply; the seat prepares the workflow and asks for that setting, and does not assume it.
Claim: PM loop round 10 · 2026-11-09T01:34Z
Session: session_01QsR2jUtaGRLf12LBQ2uTjA (card thread, dev) · seat session_01QsR2jTo666XXx9e1Gm21C6
Account: zhuangjianguo
Branch: claude/project-thread-adxihm
Worktree: objectstack-issue-31122
Domain: domain:devx
Seat: domain:devx#2
File surface: here, packages/qa/scenarios/src/export/** (an export-gallery --check DIR mode), its CLI entry and its tests. In objectstack-ai/gallery (same branch name), one pull_request workflow with contents: read and a README note. ⛔ No .github/** here, no gallery content edits (apps/, index.json), no branch-protection change (that is the maintainer's setting).
Container & model: M, mode:thread, model: default tier (no path-derived mandate), effort: high
Clause-②: no
Metadata-protocol: none
Responsibility: the public gallery's merge safety | no mechanical check runs on gallery PRs, and #31121 will open one per stable release under ruling D2 | the maintainer's one-click merge, and public gallery readers
Thread-read: 6707853036
Premise: holds; the gallery repo was added to the project's repositories 2026-11-09, and the maintainer said 「devx 接手 31122」 (2026-11-09T01:32Z)
Serial constraints cleared: #31729 (this seat) edits packages/qa/scenarios/src/score/** and runner/prompts.ts, which are disjoint from export/**.
Scope: step 1 (repo state, today's tree, the carrying package and version) is posted before code. Then PR 1 here (Refs #31122) and PR 2 in gallery (Refs objectstack-ai/objectstack#31122). Brief: /mnt/project-files/issue-31122/brief.md.
Step 1 · repo state before code · 2026-11-09T01:36Z
Read against objectstack origin/main4013e30 and objectstack-ai/gallery main 09ce9b06.
1. Gallery clone. Yes: objectstack-ai/gallery is cloned in this container, on claude/project-thread-adxihm (same as main, one commit, 09ce9b06). git ls-remote lists one head, main.
2. Today's tree. Six hand-written files and no generated content: README.md, AGENTS.md, CLAUDE.md, LICENSE, .gitignore, apps/README.md. There is no index.json and no app directory under apps/ (0 entries, 0 app dirs). No .github/. The exporter reads an absent index as an empty gallery (readGalleryVersions, exportGallery), so --check will treat it the same: absent index.json plus no app directory passes, and apps/README.md is not an app directory (a file, not a directory). Expected finding count on today's tree: 0. I will report the measured count after the code exists.
3. The package and version that would carry --check.
The exporter lives in @objectstack/scenarios (packages/qa/scenarios, ./export subpath). That package is in the fixed release group in .changeset/config.json, so it is released at the @objectstack/cli version.
It is not published yet: npm view @objectstack/scenarios answers E404. The pending changeset 31172-publish-scenarios-cli.md publishes it at the next release. npm @objectstack/clilatest is 18.3.0 (next 18.2.0).
So --check first exists on npm in the release after PR 1 lands, as @objectstack/scenarios@<that version>. Today there is no version the gallery workflow can pin.
4. Plan for PR 1 (here), and the files it needs.
src/export/check.ts (new): checkGallery(dir, { publishedVersions }) returns one finding per line. It reuses GalleryIndexSchema / parseIndex from manifest.ts and APP_LAYOUT from exporter.ts, not a restated copy.
src/export/cli.ts: --check DIR short-circuits before the card and runs loading (which needs a repo checkout), prints the findings, exits 1 on any, 0 on none.
Version check: framework.version must match STABLE_VERSION (from refresh.ts) and be in @objectstack/cli's published version list. Offline in tests: the list is injected (publishedVersions). Online in the CLI and workflow: npm view @objectstack/cli versions --json, the same npm view channel npmLatestVersion already uses.
Absolute local paths: a fixed set of local roots (/home/, /Users/, /root/, /tmp/, /private/, /var/folders/, a Windows drive path) scanned in every file's contents and names. A bare leading slash is not flagged (URL paths such as /api/v1 are legitimate).
Tests: test/export/check.test.ts, one fixture per failure plus one clean tree, built on the existing test/export/fixture.ts.
Files outside src/export/** that the published path needs (asking before touching):
src/bin.ts plus tsup.config.ts: the published objectstack-scenarios bin offers only run, help and version. For the gallery workflow to run npx @objectstack/scenarios@VERSION export-gallery --check ., the bin needs an export-gallery command that loads the built export CLI lazily (one more tsup entry, as cli is for run). The test/build/ pins (packed-tarball.test.ts, built-consumer.test.ts) may need a row for it.
README.md of the package: one line documenting the command.
A changeset .changeset/31122-scenarios-gallery-check.md (patch), since the source ships in a published package.
Declaration lines. The claim says Clause-②: no. A new bin command on @objectstack/scenarios would be widening, but that package has never been published (E404), so no released surface widens. I will copy the claim's lines verbatim and record this under deviations unless the seat amends the claim.
5. Questions for the seat.
Q1, surface: may PR 1 touch src/bin.ts, tsup.config.ts, the package README.md, the two test/build/ pins and the changeset (above)? Recommend yes: without the bin command the published package cannot run --check at all.
Q2, the gallery workflow until a release carries --check: (A) check out objectstack-ai/objectstack at the pinned PR 1 merge SHA, install and build the scenarios closure, and run pnpm --filter @objectstack/scenarios export-gallery --check "$GITHUB_WORKSPACE"; swap to the npm pin in a later PR once released. (B) Open PR 2 as a draft now and pin npx @objectstack/scenarios@VERSION once a release carries it; no workflow runs until then. Recommend A: gallery-refresh runs from a checkout, not from npm, so the scheduled task can open an export PR before the next release, and B leaves that PR unchecked. A costs a monorepo install per gallery PR (minutes) and a second small PR later.
Q3, screenshots: the exporter allows an app with zero screenshots (--no-screenshots). Recommend the check fails an entry with zero screenshots (a public app with none is a half-written export), and checks that every listed screenshot file exists and that screenshots/ holds no unlisted file.
Claim: PM loop round 10 · amendment · 2026-11-09T01:37Z
Session: session_01QsR2jUtaGRLf12LBQ2uTjA (card thread, dev) · seat session_01QsR2jTo666XXx9e1Gm21C6
Account: zhuangjianguo
Branch: claude/project-thread-adxihm
Worktree: objectstack-issue-31122
Domain: domain:devx
Seat: domain:devx#2
File surface: here, packages/qa/scenarios/src/export/** (an export-gallery --check DIR mode), its CLI entry (src/bin.ts, tsup.config.ts: an export-gallery bin command), the package README, the two test/build pins on the bin list, a patch changeset, and its tests. In objectstack-ai/gallery (same branch name), one pull_request workflow with contents: read and a README note. ⛔ No .github/** here, no gallery content edits (apps/, index.json), no branch-protection change (that is the maintainer's setting).
Container & model: M, mode:thread, model: default tier (no path-derived mandate), effort: high
Clause-②: no
Metadata-protocol: none
Responsibility: the public gallery's merge safety | no mechanical check runs on gallery PRs, and #31121 will open one per stable release under ruling D2 | the maintainer's one-click merge, and public gallery readers
Thread-read: 6707853036
Premise: holds; the gallery repo was added to the project's repositories 2026-11-09, and the maintainer said 「devx 接手 31122」 (2026-11-09T01:32Z); step-1 reading 6730175330 ruled Q1 yes, Q2 A, Q3 yes
Serial constraints cleared: #31729 (this seat) edits packages/qa/scenarios/src/score/** and runner/prompts.ts, which are disjoint from export/**.
Scope: step 1 (repo state, today's tree, the carrying package and version) is posted before code. Then PR 1 here (Refs #31122) and PR 2 in gallery (Refs objectstack-ai/objectstack#31122). Brief: /mnt/project-files/issue-31122/brief.md.
PR 1 of 2 is open: #31748 (draft, head 03dbda01, Refs only). PR 2 (the gallery workflow) waits for its merge, per the seat's Q2 ruling: it pins this PR's merge commit. Reported at 2026-11-09T02:17Z.
{
"issue": 31122,
"status": "done",
"branch": "claude/project-thread-adxihm",
"pr": "https://github.com/objectstack-ai/objectstack/pull/31748",
"head": "03dbda01",
"session": "session_01QsR2jUtaGRLf12LBQ2uTjA",
"premise_still_valid": true,
"summary": "export-gallery --check DIR: a read-only check of a gallery tree on the exporter's own contract (GalleryIndexSchema, APP_LAYOUT, STABLE_VERSION), ten finding codes, exit 1 on any. Reachable from a checkout (pnpm export-gallery --check) and from the published bin (objectstack-scenarios export-gallery --check, lazily loaded from dist/export-check.js). Today's gallery main 09ce9b06 (no index.json, no app dir) reads clean, 0 findings, through both doors. PR 2 in objectstack-ai/gallery is owed after this merges.",
"files_changed": 13,
"line_budget": "+699 / -20 = 719 changed lines vs merge base 4013e308, under the 3000 threshold",
"tests": "head afee5f75: pnpm --filter @objectstack/scenarios typecheck && test under os-verify-lock, VERDICT command-exit 0, 32/32 files, 654/654 tests; after build, packed-tarball + library tests 2 files 17 tests passed; check.test.ts 37/37. Ablation: zero-screenshot rule replaced by if(false) via ablation-replace.mjs, check.test.ts 1 failed / 36 passed, restored blob 71c32a9a == HEAD, git diff HEAD empty. Merge of main (03dbda01) brought 3 commits, none in packages/qa/scenarios, no re-run.",
"gates": "dispatch-gates --commands on afee5f75: 60 derived; 59 exit 0 (check:type-check-debt under the lock, 322 s); pnpm check:dual-build-cjs-loads exit 3 PREREQUISITE NOT MET (workspace not fully built) = NOT MEASURED, CI is the evidence. --ran with exit codes: 60 accounted, 59 run, 1 NOT MEASURED, 0 UNRUN. Body gates on the PR body: check-changeset-no-major 0, check-adr-0087-registration 0, check-closing-keyword-parity 0, check-partof-closing-keyword 0. --tier: no path-derived mandate. PR check-runs: in_progress at report time.",
"dogfood_battery": "n/a: no `!` in the PR title and no (narrowing) arm",
"deviations": [
"Clause-②: no kept as the claim says, although objectstack-scenarios export-gallery is a new bin command: @objectstack/scenarios has never been published (npm E404, 2026-11-09), so no released surface widens (seat ruling Q1).",
"symlink is one finding code beyond the card's list: the content scan cannot read through a link, and the exporter already refuses one (source.ts).",
"built-consumer.test.ts was not touched: it does not read the bin. Both bin pins live in packed-tarball.test.ts (the import-list pin and a new plain-Node run).",
"APP_LAYOUT, FRAMEWORK_PACKAGE and STABLE_VERSION moved into src/export/contract.ts (inside export/**), re-exported unchanged, so the bin's check entry does not load the exporter's graph."
],
"mcp_calls": "7: issue_read x4 (31122 get, comments x2, 31121 get), pull_request_read get (31667, a body-format read), plus 2 tool-schema loads; no MCP write",
"api_writes": "3: post-stamped comment 6730175330 (step 1), relay pr_create #31748, this report. git push is not counted.",
"open_questions": [],
"security_findings": "none",
"out_of_scope_findings": []
}
Branch protection on objectstack-ai/gallery main, for the maintainer (a setting, not code; not attempted): after PR 2 merges and its check has run once, add a branch ruleset (or classic protection) on main with: require a pull request before merging (required approvals 0 is enough for the one-click merge; dismiss stale approvals on push); require status checks to pass, with the gallery workflow's job (Gallery check, the name PR 2 declares) as required, and "require branches to be up to date" on; block force pushes; restrict deletions; no bypass list for now (under D1, later, the scheduled task's identity is the only one added to it).
{
"issue": 31122,
"status": "done",
"branch": "claude/project-thread-adxihm (objectstack-ai/gallery)",
"pr": "https://github.com/objectstack-ai/gallery/pull/1",
"head": "b0145986",
"session": "session_01QsR2jUtaGRLf12LBQ2uTjA",
"premise_still_valid": true,
"summary": "Gallery workflow .github/workflows/gallery-check.yml: pull_request, permissions contents: read, one job named exactly `Gallery check`. It checks out the PR and objectstack-ai/objectstack at the pinned full SHA c2bb879fe71c16bd1d0b42708109efb7f6543d5d (PR #31748's merge commit), then runs a filtered install, an OS_SKIP_DTS closure build and export-gallery --check. A header comment names the switch to a pinned npx @objectstack/scenarios@VERSION once a release carries it. README gains a 'How content arrives' note (generated content, the scheduled task's PR is the normal path, every PR passes the check, hand edits in apps/README.md only).",
"files_changed": 2,
"line_budget": "2 files: workflow +78 (new), README.md +5 / -1",
"tests": "Fresh detached objectstack worktree at c2bb879f: filtered install exit 0; OS_SKIP_DTS=1 closure build VERDICT command-exit 0 (35 s locked, shared box); export-gallery --check on the gallery branch tree (head b0145986) -> 'gallery check: clean', exit 0. Negative leg on a copy plus .env plus unlisted apps/stray -> exit 1, findings app-unlisted and env-file. YAML parses.",
"gates": "objectstack dispatch-gates does not derive for objectstack-ai/gallery (no package.json, no gates there). The PR's own `Gallery check` run is the evidence: in_progress at report time.",
"dogfood_battery": "n/a: gallery repo",
"deviations": [
"gallery AGENTS.md's list of hand-written files does not name the new workflow. Left alone (outside the one-workflow-plus-README surface) and noted in the PR body as a one-line follow-up.",
"Commit f4be762 was pushed before the pin, as a backup with no PR; b0145986 pins the SHA in a new commit, with no history rewrite."
],
"mcp_calls": "this round: 0 GitHub MCP calls (subscribe_pr_activity is not a GitHub MCP tool)",
"api_writes": "2 this round: relay pr_create objectstack-ai/gallery#1 (read back byte-identical, 4543 B) and this report. git push is not counted.",
"open_questions": [],
"security_findings": "none",
"out_of_scope_findings": []
}
The branch-protection list in 6730658555 stands, with the required status check named exactly Gallery check. Add it after this PR's first run, so the context exists to select.
席位核对 · ACCEPT · 2026-11-09T03:17Z · objectstack-ai/gallery#1 head b0145986e52f3c2dad271e2216e79893a405fd7f
Seat domain:devx#2 reviewed PR 2 of its own dispatch (claim 6730150314, step-1 ruling 6730175330, amendment 6730187617, card thread session_01QsR2jUtaGRLf12LBQ2uTjA, report 6731371522). Checked against GitHub, not against the report.
Shape: 2 files, +85 / -1: the new workflow (+80) and README (+5 / -1, in English and Chinese). Body: Refs objectstack-ai/objectstack#31122. Gallery main had not moved (09ce9b0), and mergeable_state is clean.
Design read: the trigger is pull_request with permissions: contents: read and persist-credentials: false on both checkouts. The install and build run inside the objectstack checkout only. The gallery tree is read by the checker and never executed, so a fork PR gets no write token and runs none of its own code. The job name is exactly Gallery check, the name the branch-protection list requires. The 20-minute wall is sized against the dev's measured filtered install and the OS_SKIP_DTS closure build (35 s).
Check-runs:Gallery check completed success on this head. Dev, through a fresh worktree at the pin: clean on the branch tree (exit 0). The negative leg, a .env plus an unlisted apps/stray, gave exit 1 with two findings.
Accepted deviations: gallery AGENTS.md's list of hand-written files does not name the workflow. That is a one-line follow-up, left out of this PR. The pin went in as a new commit on top of the backup push, with no history rewrite.
The maintainer asked who should build this card's gallery workflow and answered in the QA seat's session, verbatim: 「交 devx 车道」. The QA seat does not claim it; it stays with domain:devx as triaged.
Access, measured today: the maintainer granted the Claude GitHub App on objectstack-ai/gallery. In the QA seat's session add_repo with push access attached it (status: appended), and a shallow clone works (HEAD 09ce9b0, the initialisation commit only: README, AGENTS.md, CLAUDE.md, LICENSE, .gitignore, apps/). A devx session that takes the card attaches the gallery the same way, with push access, and works in that clone.
The gallery's own rules (its AGENTS.md): apps/** and index.json are written only by the exporter; the hand-written files are listed there. The check this card asks for reads the exporter's schema in packages/qa/scenarios/src/export/.
Still the maintainer's hand: the PR-only protection on the gallery's main (a repository setting) and the merge of the workflow PR.
Release: session_01QsR2jTo666XXx9e1Gm21C6 · 2026-11-10T00:00Z · reason: the seat clocks out on the maintainer's order (「当前任务处理完,合并后就下班」); PR 2 waits on the maintainer's merge · next: land gallery#1, then branch protection, then close
Resume-from: none (PR 2 lives in objectstack-ai/gallery: branch claude/project-thread-adxihm @ b0145986e52f3c2dad271e2216e79893a405fd7f, objectstack-ai/gallery#1, open, ready, ACCEPTed by this seat)
State: PR 1 #31748 (export-gallery --check) merged as c2bb879f. PR 2 is objectstack-ai/gallery#1: the read-only Gallery check workflow pinned to PR 1's merge SHA. It waits only on the maintainer's merge.
Next, in order: (1) the maintainer merges gallery#1; (2) the gallery repo's main gets branch protection with Gallery check required and PRs required (a settings change the maintainer makes, or authorizes); (3) a landing note here naming both merges and the protection, then close this card (both PRs say Refs, so nothing closes it automatically). The cross-repo relay works with --repo objectstack-ai/gallery once the session has that repo added with push.
Both PRs have landed: PR 1 objectstack #31748 as c2bb879f, and PR 2 objectstack-ai/gallery#1 as ddf3393ba12ed3b799221d44a58e26e8c2522a06, merged by os-zhuang at 2026-11-10T00:45Z. Every gallery PR now runs the read-only Gallery check.
Still open, so the card stays in pm:queue (released 6754814772; this seat is clocked out):
A PR-only gallery main. The gallery repo has no ruleset (the list reads []), and its branch protection cannot be read from a seat session (403). The maintainer adds a ruleset or protection on main that requires a pull request and requires the Gallery check status check. Once that is in place, whoever holds the card closes it with a one-line note.
Later, not blocking the close: switch the workflow from the pinned objectstack checkout to npx @objectstack/scenarios@VERSION once a release publishes the package. That is a follow-up card when the first release ships.
State: pm:queue → pm:awaiting-maintainer · 2026-11-10T01:09Z · ⛔ Not a claim
Both PRs have landed (landing note 6755616258: objectstack #31748c2bb879f, objectstack-ai/gallery#1ddf3393b). Nothing on this card is dispatchable: the one remaining step is a repository setting on objectstack-ai/gallery, which only its owner can apply (triage 6707853036; a seat session reads its protection as 403).
Maintainer-action: add a ruleset or branch protection on objectstack-ai/gallery main that requires a pull request and requires the Gallery check status check — done when the gallery repo's rulesets or branch protection list it; then any devx seat closes this card with a one-line note.
The later switch to npx @objectstack/scenarios@VERSION is not part of the close (6755616258 item 2): it is a follow-up card once a release publishes the package.
Reading taken 2026-11-12, after the ruleset's updated_at of 04:40:48Z. Sources: GET repos/objectstack-ai/gallery/rulesets/27091720 and GET repos/objectstack-ai/gallery/rules/branches/main.
Both halves of the card have landed: #31748c2bb879f (the --check mode) and objectstack-ai/gallery#1ddf3393b (the workflow). The Maintainer-action's done-when holds: the ruleset lists both a pull request and the Gallery check status check.
Still owed outside this card:
the switch to npx @objectstack/scenarios@VERSION once a release publishes the package (follow-up, per 6755616258 item 2);
Note for the refresh task: the ruleset keeps require_extra_approval_for_unattributed_changes: true. The task's commits must carry an attributed identity, as #31121 already requires (the maintainer's).
Activity
objectstack-fleet commentedon Nov 7, 2026
triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U
Path: none
Triage: audit · p2 kept ·
domain:devx· 2026-11-07T13:57Z⛔ Not a claim.
main. The change lands in objectstack-ai/gallery, a repository the maintainer owns and outside this board's repos. This card tracks it because the gallery has no fleet lane.domain:devx,pm:queuekept. Branch protection on the gallery'smainis a repository setting that only its owner can apply; the seat prepares the workflow and asks for that setting, and does not assume it.Generated by Claude Code
objectstack-fleet commentedon Nov 9, 2026
domain:devx#2 · zhuangjianguo · session_01QsR2jTo666XXx9e1Gm21C6
Claim: PM loop round 10 · 2026-11-09T01:34Z
Session:
session_01QsR2jUtaGRLf12LBQ2uTjA(card thread, dev) · seatsession_01QsR2jTo666XXx9e1Gm21C6Account:
zhuangjianguoBranch:
claude/project-thread-adxihmWorktree:
objectstack-issue-31122Domain:
domain:devxSeat:
domain:devx#2File surface: here,
packages/qa/scenarios/src/export/**(anexport-gallery --check DIRmode), its CLI entry and its tests. Inobjectstack-ai/gallery(same branch name), onepull_requestworkflow withcontents: readand a README note. ⛔ No.github/**here, no gallery content edits (apps/,index.json), no branch-protection change (that is the maintainer's setting).Container & model: M,
mode:thread,model: default tier(no path-derived mandate),effort: highClause-②: no
Metadata-protocol: none
Responsibility: the public gallery's merge safety | no mechanical check runs on gallery PRs, and #31121 will open one per stable release under ruling D2 | the maintainer's one-click merge, and public gallery readers
Thread-read: 6707853036
Premise: holds; the gallery repo was added to the project's repositories 2026-11-09, and the maintainer said 「devx 接手 31122」 (2026-11-09T01:32Z)
Serial constraints cleared: #31729 (this seat) edits
packages/qa/scenarios/src/score/**andrunner/prompts.ts, which are disjoint fromexport/**.Scope: step 1 (repo state, today's tree, the carrying package and version) is posted before code. Then PR 1 here (
Refs #31122) and PR 2 in gallery (Refs objectstack-ai/objectstack#31122). Brief:/mnt/project-files/issue-31122/brief.md.objectstack-fleet commentedon Nov 9, 2026
domain:devx#2 · zhuangjianguo · session_01QsR2jUtaGRLf12LBQ2uTjA
Step 1 · repo state before code · 2026-11-09T01:36Z
Read against objectstack
origin/main4013e30 and objectstack-ai/gallerymain09ce9b06.1. Gallery clone. Yes: objectstack-ai/gallery is cloned in this container, on
claude/project-thread-adxihm(same asmain, one commit, 09ce9b06).git ls-remotelists one head,main.2. Today's tree. Six hand-written files and no generated content:
README.md,AGENTS.md,CLAUDE.md,LICENSE,.gitignore,apps/README.md. There is noindex.jsonand no app directory underapps/(0 entries, 0 app dirs). No.github/. The exporter reads an absent index as an empty gallery (readGalleryVersions,exportGallery), so--checkwill treat it the same: absentindex.jsonplus no app directory passes, andapps/README.mdis not an app directory (a file, not a directory). Expected finding count on today's tree: 0. I will report the measured count after the code exists.3. The package and version that would carry
--check.@objectstack/scenarios(packages/qa/scenarios,./exportsubpath). That package is in thefixedrelease group in.changeset/config.json, so it is released at the@objectstack/cliversion.npm view @objectstack/scenariosanswers E404. The pending changeset31172-publish-scenarios-cli.mdpublishes it at the next release. npm@objectstack/clilatestis 18.3.0 (next18.2.0).--checkfirst exists on npm in the release after PR 1 lands, as@objectstack/scenarios@<that version>. Today there is no version the gallery workflow can pin.4. Plan for PR 1 (here), and the files it needs.
src/export/check.ts(new):checkGallery(dir, { publishedVersions })returns one finding per line. It reusesGalleryIndexSchema/parseIndexfrommanifest.tsandAPP_LAYOUTfromexporter.ts, not a restated copy.src/export/cli.ts:--check DIRshort-circuits before the card and runs loading (which needs a repo checkout), prints the findings, exits 1 on any, 0 on none.framework.versionmust matchSTABLE_VERSION(fromrefresh.ts) and be in@objectstack/cli's published version list. Offline in tests: the list is injected (publishedVersions). Online in the CLI and workflow:npm view @objectstack/cli versions --json, the samenpm viewchannelnpmLatestVersionalready uses./home/,/Users/,/root/,/tmp/,/private/,/var/folders/, a Windows drive path) scanned in every file's contents and names. A bare leading slash is not flagged (URL paths such as/api/v1are legitimate).test/export/check.test.ts, one fixture per failure plus one clean tree, built on the existingtest/export/fixture.ts.Files outside
src/export/**that the published path needs (asking before touching):src/bin.tsplustsup.config.ts: the publishedobjectstack-scenariosbin offers onlyrun,helpandversion. For the gallery workflow to runnpx @objectstack/scenarios@VERSION export-gallery --check ., the bin needs anexport-gallerycommand that loads the built export CLI lazily (one more tsup entry, ascliis forrun). Thetest/build/pins (packed-tarball.test.ts,built-consumer.test.ts) may need a row for it.README.mdof the package: one line documenting the command..changeset/31122-scenarios-gallery-check.md(patch), since the source ships in a published package.Declaration lines. The claim says
Clause-②: no. A new bin command on@objectstack/scenarioswould be widening, but that package has never been published (E404), so no released surface widens. I will copy the claim's lines verbatim and record this underdeviationsunless the seat amends the claim.5. Questions for the seat.
src/bin.ts,tsup.config.ts, the packageREADME.md, the twotest/build/pins and the changeset (above)? Recommend yes: without the bin command the published package cannot run--checkat all.--check: (A) check out objectstack-ai/objectstack at the pinned PR 1 merge SHA, install and build the scenarios closure, and runpnpm --filter @objectstack/scenarios export-gallery --check "$GITHUB_WORKSPACE"; swap to the npm pin in a later PR once released. (B) Open PR 2 as a draft now and pinnpx @objectstack/scenarios@VERSIONonce a release carries it; no workflow runs until then. Recommend A:gallery-refreshruns from a checkout, not from npm, so the scheduled task can open an export PR before the next release, and B leaves that PR unchecked. A costs a monorepo install per gallery PR (minutes) and a second small PR later.--no-screenshots). Recommend the check fails an entry with zero screenshots (a public app with none is a half-written export), and checks that every listed screenshot file exists and thatscreenshots/holds no unlisted file.Write nothing until the seat answers.
objectstack-fleet commentedon Nov 9, 2026
domain:devx#2 · zhuangjianguo · session_01QsR2jTo666XXx9e1Gm21C6
Claim: PM loop round 10 · amendment · 2026-11-09T01:37Z
Session:
session_01QsR2jUtaGRLf12LBQ2uTjA(card thread, dev) · seatsession_01QsR2jTo666XXx9e1Gm21C6Account:
zhuangjianguoBranch:
claude/project-thread-adxihmWorktree:
objectstack-issue-31122Domain:
domain:devxSeat:
domain:devx#2File surface: here,
packages/qa/scenarios/src/export/**(anexport-gallery --check DIRmode), its CLI entry (src/bin.ts,tsup.config.ts: anexport-gallerybin command), the package README, the two test/build pins on the bin list, a patch changeset, and its tests. Inobjectstack-ai/gallery(same branch name), onepull_requestworkflow withcontents: readand a README note. ⛔ No.github/**here, no gallery content edits (apps/,index.json), no branch-protection change (that is the maintainer's setting).Container & model: M,
mode:thread,model: default tier(no path-derived mandate),effort: highClause-②: no
Metadata-protocol: none
Responsibility: the public gallery's merge safety | no mechanical check runs on gallery PRs, and #31121 will open one per stable release under ruling D2 | the maintainer's one-click merge, and public gallery readers
Thread-read: 6707853036
Premise: holds; the gallery repo was added to the project's repositories 2026-11-09, and the maintainer said 「devx 接手 31122」 (2026-11-09T01:32Z); step-1 reading 6730175330 ruled Q1 yes, Q2 A, Q3 yes
Serial constraints cleared: #31729 (this seat) edits
packages/qa/scenarios/src/score/**andrunner/prompts.ts, which are disjoint fromexport/**.Scope: step 1 (repo state, today's tree, the carrying package and version) is posted before code. Then PR 1 here (
Refs #31122) and PR 2 in gallery (Refs objectstack-ai/objectstack#31122). Brief:/mnt/project-files/issue-31122/brief.md.objectstack-fleet commentedon Nov 9, 2026
domain:devx#2 · zhuangjianguo · session_01QsR2jUtaGRLf12LBQ2uTjA
os-dev-report
PR 1 of 2 is open: #31748 (draft, head
03dbda01, Refs only). PR 2 (the gallery workflow) waits for its merge, per the seat's Q2 ruling: it pins this PR's merge commit. Reported at 2026-11-09T02:17Z.{ "issue": 31122, "status": "done", "branch": "claude/project-thread-adxihm", "pr": "https://github.com/objectstack-ai/objectstack/pull/31748", "head": "03dbda01", "session": "session_01QsR2jUtaGRLf12LBQ2uTjA", "premise_still_valid": true, "summary": "export-gallery --check DIR: a read-only check of a gallery tree on the exporter's own contract (GalleryIndexSchema, APP_LAYOUT, STABLE_VERSION), ten finding codes, exit 1 on any. Reachable from a checkout (pnpm export-gallery --check) and from the published bin (objectstack-scenarios export-gallery --check, lazily loaded from dist/export-check.js). Today's gallery main 09ce9b06 (no index.json, no app dir) reads clean, 0 findings, through both doors. PR 2 in objectstack-ai/gallery is owed after this merges.", "files_changed": 13, "line_budget": "+699 / -20 = 719 changed lines vs merge base 4013e308, under the 3000 threshold", "tests": "head afee5f75: pnpm --filter @objectstack/scenarios typecheck && test under os-verify-lock, VERDICT command-exit 0, 32/32 files, 654/654 tests; after build, packed-tarball + library tests 2 files 17 tests passed; check.test.ts 37/37. Ablation: zero-screenshot rule replaced by if(false) via ablation-replace.mjs, check.test.ts 1 failed / 36 passed, restored blob 71c32a9a == HEAD, git diff HEAD empty. Merge of main (03dbda01) brought 3 commits, none in packages/qa/scenarios, no re-run.", "gates": "dispatch-gates --commands on afee5f75: 60 derived; 59 exit 0 (check:type-check-debt under the lock, 322 s); pnpm check:dual-build-cjs-loads exit 3 PREREQUISITE NOT MET (workspace not fully built) = NOT MEASURED, CI is the evidence. --ran with exit codes: 60 accounted, 59 run, 1 NOT MEASURED, 0 UNRUN. Body gates on the PR body: check-changeset-no-major 0, check-adr-0087-registration 0, check-closing-keyword-parity 0, check-partof-closing-keyword 0. --tier: no path-derived mandate. PR check-runs: in_progress at report time.", "dogfood_battery": "n/a: no `!` in the PR title and no (narrowing) arm", "deviations": [ "Clause-②: no kept as the claim says, although objectstack-scenarios export-gallery is a new bin command: @objectstack/scenarios has never been published (npm E404, 2026-11-09), so no released surface widens (seat ruling Q1).", "symlink is one finding code beyond the card's list: the content scan cannot read through a link, and the exporter already refuses one (source.ts).", "built-consumer.test.ts was not touched: it does not read the bin. Both bin pins live in packed-tarball.test.ts (the import-list pin and a new plain-Node run).", "APP_LAYOUT, FRAMEWORK_PACKAGE and STABLE_VERSION moved into src/export/contract.ts (inside export/**), re-exported unchanged, so the bin's check entry does not load the exporter's graph." ], "mcp_calls": "7: issue_read x4 (31122 get, comments x2, 31121 get), pull_request_read get (31667, a body-format read), plus 2 tool-schema loads; no MCP write", "api_writes": "3: post-stamped comment 6730175330 (step 1), relay pr_create #31748, this report. git push is not counted.", "open_questions": [], "security_findings": "none", "out_of_scope_findings": [] }Branch protection on objectstack-ai/gallery
main, for the maintainer (a setting, not code; not attempted): after PR 2 merges and its check has run once, add a branch ruleset (or classic protection) onmainwith: require a pull request before merging (required approvals 0 is enough for the one-click merge; dismiss stale approvals on push); require status checks to pass, with the gallery workflow's job (Gallery check, the name PR 2 declares) as required, and "require branches to be up to date" on; block force pushes; restrict deletions; no bypass list for now (under D1, later, the scheduled task's identity is the only one added to it).ci: pin the gallery check to the objectstack commit that merged expor…
objectstack-fleet commentedon Nov 9, 2026
domain:devx#2 · zhuangjianguo · session_01QsR2jUtaGRLf12LBQ2uTjA
os-dev-report
PR 2 of 2 is open: objectstack-ai/gallery#1 (draft, head
b0145986, Refs #31122). Reported at 2026-11-09T03:15Z.{ "issue": 31122, "status": "done", "branch": "claude/project-thread-adxihm (objectstack-ai/gallery)", "pr": "https://github.com/objectstack-ai/gallery/pull/1", "head": "b0145986", "session": "session_01QsR2jUtaGRLf12LBQ2uTjA", "premise_still_valid": true, "summary": "Gallery workflow .github/workflows/gallery-check.yml: pull_request, permissions contents: read, one job named exactly `Gallery check`. It checks out the PR and objectstack-ai/objectstack at the pinned full SHA c2bb879fe71c16bd1d0b42708109efb7f6543d5d (PR #31748's merge commit), then runs a filtered install, an OS_SKIP_DTS closure build and export-gallery --check. A header comment names the switch to a pinned npx @objectstack/scenarios@VERSION once a release carries it. README gains a 'How content arrives' note (generated content, the scheduled task's PR is the normal path, every PR passes the check, hand edits in apps/README.md only).", "files_changed": 2, "line_budget": "2 files: workflow +78 (new), README.md +5 / -1", "tests": "Fresh detached objectstack worktree at c2bb879f: filtered install exit 0; OS_SKIP_DTS=1 closure build VERDICT command-exit 0 (35 s locked, shared box); export-gallery --check on the gallery branch tree (head b0145986) -> 'gallery check: clean', exit 0. Negative leg on a copy plus .env plus unlisted apps/stray -> exit 1, findings app-unlisted and env-file. YAML parses.", "gates": "objectstack dispatch-gates does not derive for objectstack-ai/gallery (no package.json, no gates there). The PR's own `Gallery check` run is the evidence: in_progress at report time.", "dogfood_battery": "n/a: gallery repo", "deviations": [ "gallery AGENTS.md's list of hand-written files does not name the new workflow. Left alone (outside the one-workflow-plus-README surface) and noted in the PR body as a one-line follow-up.", "Commit f4be762 was pushed before the pin, as a backup with no PR; b0145986 pins the SHA in a new commit, with no history rewrite." ], "mcp_calls": "this round: 0 GitHub MCP calls (subscribe_pr_activity is not a GitHub MCP tool)", "api_writes": "2 this round: relay pr_create objectstack-ai/gallery#1 (read back byte-identical, 4543 B) and this report. git push is not counted.", "open_questions": [], "security_findings": "none", "out_of_scope_findings": [] }The branch-protection list in 6730658555 stands, with the required status check named exactly
Gallery check. Add it after this PR's first run, so the context exists to select.objectstack-fleet commentedon Nov 9, 2026
domain:devx#2 · zhuangjianguo · session_01QsR2jTo666XXx9e1Gm21C6
维护者速读
.github/workflows/gallery-check.yml,每个 PR 都跑export-gallery --check,job 名为Gallery check。检查器取自 objectstack 主干的固定提交c2bb879f(feat(scenarios): export-gallery --check, the mechanical check a gallery PR must pass #31748 的合并提交)。README 中英文各加一段"内容怎么进来"。contents: read,不推送、不评论,也不执行 PR 里的任何文件。回滚 = revert 该 PR。OBJECTSTACK_SHA与最后一步。Gallery check首跑成功(job 128959620292)。main上设分支保护,把Gallery check设为必需检查。席位核对 · ACCEPT · 2026-11-09T03:17Z · objectstack-ai/gallery#1 head
b0145986e52f3c2dad271e2216e79893a405fd7fSeat
domain:devx#2reviewed PR 2 of its own dispatch (claim 6730150314, step-1 ruling 6730175330, amendment 6730187617, card threadsession_01QsR2jUtaGRLf12LBQ2uTjA, report 6731371522). Checked against GitHub, not against the report.Refs objectstack-ai/objectstack#31122. Gallerymainhad not moved (09ce9b0), andmergeable_stateisclean.c2bb879fe71c16bd1d0b42708109efb7f6543d5d, which is feat(scenarios): export-gallery --check, the mechanical check a gallery PR must pass #31748's merge commit. The header names the switch to a version-pinnednpx @objectstack/scenarios@VERSIONonce a release carries--check.pull_requestwithpermissions: contents: readandpersist-credentials: falseon both checkouts. The install and build run inside the objectstack checkout only. The gallery tree is read by the checker and never executed, so a fork PR gets no write token and runs none of its own code. The job name is exactlyGallery check, the name the branch-protection list requires. The 20-minute wall is sized against the dev's measured filtered install and theOS_SKIP_DTSclosure build (35 s).Gallery checkcompletedsuccesson this head. Dev, through a fresh worktree at the pin: clean on the branch tree (exit 0). The negative leg, a.envplus an unlistedapps/stray, gave exit 1 with two findings.AGENTS.md's list of hand-written files does not name the workflow. That is a one-line follow-up, left out of this PR. The pin went in as a new commit on top of the backup push, with no history rewrite.main(list in report 6730658555). This seat then writes the landing note and closes objectstack-ai/gallery: a read-only check workflow on every PR (index schema, complete app directories, no stray files) and a PR-only main, before the scheduled export writes there #31122, because both bodies sayRefs.objectstack-fleet commentedon Nov 9, 2026
qa#1 · zhuangjianguo · session_01QsR2jUARzLeR7GhKms8a5s
Hand-off note · 2026-11-09T23:43Z · ⛔ Not a claim
domain:devxas triaged.add_repowith push access attached it (status: appended), and a shallow clone works (HEAD09ce9b0, the initialisation commit only: README, AGENTS.md, CLAUDE.md, LICENSE,.gitignore,apps/). A devx session that takes the card attaches the gallery the same way, with push access, and works in that clone.apps/**andindex.jsonare written only by the exporter; the hand-written files are listed there. The check this card asks for reads the exporter's schema inpackages/qa/scenarios/src/export/.main(a repository setting) and the merge of the workflow PR.objectstack-fleet commentedon Nov 10, 2026
domain:devx#2 · zhuangjianguo · session_01QsR2jTo666XXx9e1Gm21C6
Release: session_01QsR2jTo666XXx9e1Gm21C6 · 2026-11-10T00:00Z · reason: the seat clocks out on the maintainer's order (「当前任务处理完,合并后就下班」); PR 2 waits on the maintainer's merge · next: land gallery#1, then branch protection, then close
Resume-from: none (PR 2 lives in objectstack-ai/gallery: branch
claude/project-thread-adxihm@b0145986e52f3c2dad271e2216e79893a405fd7f, objectstack-ai/gallery#1, open, ready, ACCEPTed by this seat)State: PR 1 #31748 (
export-gallery --check) merged asc2bb879f. PR 2 is objectstack-ai/gallery#1: the read-onlyGallery checkworkflow pinned to PR 1's merge SHA. It waits only on the maintainer's merge.Next, in order: (1) the maintainer merges gallery#1; (2) the gallery repo's
maingets branch protection withGallery checkrequired and PRs required (a settings change the maintainer makes, or authorizes); (3) a landing note here naming both merges and the protection, then close this card (both PRs sayRefs, so nothing closes it automatically). The cross-repo relay works with--repo objectstack-ai/galleryonce the session has that repo added with push.objectstack-fleet commentedon Nov 10, 2026
domain:devx#2 · zhuangjianguo · session_01QsR2jTo666XXx9e1Gm21C6
Landing note · 2026-11-10T00:46Z
Both PRs have landed: PR 1 objectstack #31748 as
c2bb879f, and PR 2 objectstack-ai/gallery#1 asddf3393ba12ed3b799221d44a58e26e8c2522a06, merged by os-zhuang at 2026-11-10T00:45Z. Every gallery PR now runs the read-onlyGallery check.Still open, so the card stays in
pm:queue(released 6754814772; this seat is clocked out):main. The gallery repo has no ruleset (the list reads[]), and its branch protection cannot be read from a seat session (403). The maintainer adds a ruleset or protection onmainthat requires a pull request and requires theGallery checkstatus check. Once that is in place, whoever holds the card closes it with a one-line note.npx @objectstack/scenarios@VERSIONonce a release publishes the package. That is a follow-up card when the first release ships.objectstack-fleet commentedon Nov 10, 2026
domain:devx#2 · os-support-ai · session_01WGufzjFj4aaaJk1VJLqRdC
State:
pm:queue→pm:awaiting-maintainer· 2026-11-10T01:09Z · ⛔ Not a claimBoth PRs have landed (landing note 6755616258: objectstack #31748
c2bb879f, objectstack-ai/gallery#1ddf3393b). Nothing on this card is dispatchable: the one remaining step is a repository setting on objectstack-ai/gallery, which only its owner can apply (triage 6707853036; a seat session reads its protection as 403).Maintainer-action: add a ruleset or branch protection on objectstack-ai/gallery
mainthat requires a pull request and requires theGallery checkstatus check — done when the gallery repo's rulesets or branch protection list it; then any devx seat closes this card with a one-line note.The later switch to
npx @objectstack/scenarios@VERSIONis not part of the close (6755616258 item 2): it is a follow-up card once a release publishes the package.objectstack-fleet commentedon Nov 12, 2026
epic:#3600#1 · hotlong · session_01Q4EjjPXwX1YfHyKJUh4agu
Maintainer-action done, verified, card closed. Maintainer, verbatim (Claude Code session, 2026-11-12): 「配置好了」.
Reading taken 2026-11-12, after the ruleset's
updated_atof 04:40:48Z. Sources:GET repos/objectstack-ai/gallery/rulesets/27091720andGET repos/objectstack-ai/gallery/rules/branches/main.main(27091720)active, target~DEFAULT_BRANCH, bypass list emptymaindeletion,non_fast_forward,pull_request(0 approvals required),required_status_checkswith contextGallery checkBoth halves of the card have landed: #31748
c2bb879f(the--checkmode) and objectstack-ai/gallery#1ddf3393b(the workflow). The Maintainer-action's done-when holds: the ruleset lists both a pull request and theGallery checkstatus check.Still owed outside this card:
npx @objectstack/scenarios@VERSIONonce a release publishes the package (follow-up, per 6755616258 item 2);Note for the refresh task: the ruleset keeps
require_extra_approval_for_unattributed_changes: true. The task's commits must carry an attributed identity, as #31121 already requires (the maintainer's).