Repository navigation
ci(half-state-patrol): run objectstack's composite action pinned to a sha instead of checking out objectstack main — objectui's half of objectstack-ai/objectstack#18471 (ruling 只做②) #11174
Copy link
Copy link
Closed
Labels
domain:devxobjectui devx stream: fix lands on .github/, scripts/ or release pipeline — devx lane cross-repoobjectui devx stream: fix lands on .github/, scripts/ or release pipeline — devx lane cross-repopriority:p2
Description
Filing gate: ④ coordination-node child. objectui's half of objectstack-ai/objectstack#18471, ruling 只做② (5713650969, maintainer 「9593 A,其他同意」). Filed by domain:devx seat 2 (objectui#10917), session_01TdiauJaVCHuj45EzZGUxHh, on the maintainer's direct order (R4 marker 5905019353).
- Who acts on it:
domain:devxseat 2 (this session) claims and dispatches it in the same round. - Duplicate check: all objectui
domain:devxissues, open and closed (551), againsthalf-state|半状态|patrol|check-half-states|18471|18466|composite action.- 9 hits, all closed and an older scope (installing or porting the patrol): the
check-half-states.mjsport can no longer be re-synced by command: 5 of its 11 declared divergence anchors have vanished upstream, and the gap is 13,159 vs 36,176 lines #10063, finding(ci): objectui's half-state patrol RUNS but its findings reach nobody — the run summary is unreadable from a seat, and the one exit code that is readable does not mean "clean" #9842, re-sync the pinnedcheck-half-states.mjsport to an upstream ref ≥a39e385eed— instruction ④ (decision-box dependency flags) arrives with it; a hand port redscheck:upstream-port-parityby construction #9395, finding(pm-gate): H26's "can never CLOSE" premise is asserted, not counted — and check-half-states.mjs refutes it twice in its own text #9317, [ci] Both patrols must degrade gracefully when no anchor is configured — the maintainer has declined the anchor setup, so the current hard failure is now permanent red #8740, docs(ci-cd-pipeline): the Half-State Patrol section describesPM_SWEEP_CLOSED_WINDOW_PAGES: '0', a knob the workflow no longer sets — the closed-card reader is ON withPM_SWEEP_CLOSED_FLOOR#8043, [ci] the half-state patrol has been red on all 50 scheduled runs since 2026-08-28 (no anchor configured), and ci-cd-pipeline.md documents a knob the workflow no longer sets #7852, The half-state patrol needs its anchor issue created and HALF_STATE_ANCHOR_ISSUE set — a maintainer action outside GitHub's API surface for agent seats #5986, Install the parameterised half-state patrol (sweeper + workflow pair from objectstack PR #11294) #5791. - None is open.
- 9 hits, all closed and an older scope (installing or porting the patrol): the
Premise (read on objectui main)
.github/workflows/half-state-patrol.ymlchecks outobjectstack-ai/objectstackatmain, unpinned. The file says so itself: "The checkout is NOT pinned to a sha: each run executes objectstack'smain".- It then runs
scripts/pm/check-half-states.mjsfrom that checkout. Its prose is adopted from objectstack PR finding(components,plugin-grid): the row menu decides "is a gate declared?" with its own test, so an action authoredvisible: ' 'shows in a related list's toolbar and is missing from its rows #11294. - The ruling requires the opposite:
uses:pinned to a sha, ⛔ never@main, with per-board constants passed aswith:inputs, and the copies deleted.
Target
- Replace the checkout and run steps with
uses: objectstack-ai/objectstack/.github/actions/half-state-patrol@<40-char sha>(landed in objectstack PR #19225 as43d492ff9).- Pass objectui's board constants through the action's declared inputs:
github-token(required),anchor-issueandclosed-floor. - Keep objectui's own trigger, schedule, permissions and concurrency.
- Pass objectui's board constants through the action's declared inputs:
- The sha is the action's newest commit on objectstack
mainat implementation time (9e9bb4641when this card was filed). The PR body records it and the date it was read; a later bump is a one-line sha change. - Delete the adopted prose that now describes upstream mechanics this repo no longer carries.
- Correct everything that pins the old shape in the same PR: the Half-State Patrol section of
content/docs/guide/ci-cd-pipeline.md, and anyscripts/__tests__/**that reads this workflow's text.
Acceptance
- One PR in objectui.
- The workflow's
uses:line pins a 40-character sha and no@mainremains. - The patrol still reads this board with the same constants. The dev proves it with the repo's workflow-lint and harness tests, plus one run of the patrol (manual dispatch or the PR's own trigger, whichever the workflow allows), with the run linked.
Clause-②: no (CI wiring, no published contract).- When this lands, [decision] 半状态巡逻的送法与形状:每天都在改的仪器靠「手工复制三个文件」分发,副本必然掉队——换成引用并把「写坏的」那半搬到写侧 objectstack#18471's
Blocked-by:line naming this card clears.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
domain:devxobjectui devx stream: fix lands on .github/, scripts/ or release pipeline — devx lane cross-repoobjectui devx stream: fix lands on .github/, scripts/ or release pipeline — devx lane cross-repopriority:p2
Activity
objectstack-fleet commentedon Sep 30, 2026
Claim: maintainer direct dispatch, round R4 (a child of objectstack-ai/objectstack#18471, which this session took over at
5905052709)Session:
session_01TdiauJaVCHuj45EzZGUxHhAccount:
huangyiirene(the card's assignee)Branch:
claude/issue-11174-half-state-patrol-composite-actionWorktree:
objectui-issue-11174Domain:
domain:devxSeat:
domain:devx#2File surface:
.github/workflows/half-state-patrol.yml; the Half-State Patrol section ofcontent/docs/guide/ci-cd-pipeline.md; and the tests or scripts that read this workflow's text (scripts/__tests__/ci-cd-pipeline-doc.test.ts, and any othergit grep half-state-patrolhit whose assertion moves). ⛔ No other workflow, and ⛔ nothing in objectstack. (stop on breach; explain in the report)Container & model:
M,mode:subagent, model: opus (TIER_DEFAULT; the tier gate reads no path-derived mandate for objectui)Clause-②: no. CI wiring, no published contract, as the ruling says.
content/docs/**is a review face, so a same-form contract-review record on the landing head is owed before enqueue.Thread-read: none
Serial constraints cleared: none.
GET /pulls/{n}/filesover all 5 open objectui PRs finds no.github/**, noci-cd-pipeline*, and none of the tests or scripts that name this workflow.objectstack-fleet commentedon Sep 30, 2026
os-dev-report
{ "issue": 11174, "status": "needs_decision", "branch": "claude/issue-11174-half-state-patrol-composite-action", "pr": null, "session": "session_01TdiauJaVCHuj45EzZGUxHh", "premise_still_valid": true, "summary": "STOPPED BEFORE EDITING, per the seat constraint for a board setting with no with: home. The workflow is unchanged: .github/workflows/half-state-patrol.yml is 481 lines before and 481 after. No PR, no commit, no test or doc changed. The card premise holds. objectui main (0ffc423b1) checks out objectstack-ai/objectstack with no ref: input, so it runs main unpinned, and runs its scripts/pm/check-half-states.mjs with the objectui constants in env:. The target does not hold for one constant. objectui runs with NO anchor on purpose: objectui#7852 (the patrol red on 50 scheduled runs with no anchor) was closed not_planned, and objectui#8740 made an empty anchor a supported setting (::notice::, exit 0, findings go to the run summary only). This is measured live: scheduled run 36657770288 (2026-09-30, conclusion success) shows Resolve the anchor issue = success, Update the pinned anchor issue = skipped, and the notice annotation that begins \"No anchor issue configured for objectstack-ai/objectui, which is a supported configuration here (objectui#8740)\". The 8 latest scheduled runs all concluded success. The composite action has no home for that setting. In the action, Resolve the anchor issue (if: github.event_name != pull_request) prints ::error::No anchor issue configured ... and exits 1 when anchor-issue is empty. That is true at 43d492ff9 (action.yml blob c4f5abfc) and at fb7b74691 (blob fc455f1e, identical to the main tip). A plain switch therefore turns every scheduled objectui run red, 4 a day, which is exactly what objectui#8740 fixed. The PR-time patrol run the card accepts as proof cannot see this: the action skips both anchor steps on pull_request, so that run reads green. Card-premise correction: \"last changed at 9e9bb4641\" is wrong. /home/user/objectstack is a shallow clone and 9e9bb4641 is listed in its .git/shallow, so git log -- PATH shows the boundary commit as adding every file. REST GET /commits/9e9bb4641 lists 39 files and none under .github/actions. The REST history filtered by path (full history, not affected by shallow) gives fb7b74691 (#19718, 2026-09-22T11:19:49Z) as the newest change to the action, then 43d492ff9 (#19225). The positive control is that 43d492ff9 is returned as well. The objectstack main tip, 4b4ee88fbc530a155ce3ea0570ad81d905d3afbb (2026-09-30T05:38:58Z), has the same action blob as fb7b74691. Both were read at 2026-09-30T06:08:23Z. No sha was pinned.", "constants_to_inputs": [ "ANCHOR_ISSUE (workflow env: vars.HALF_STATE_ANCHOR_ISSUE, or 9857 only when the repo is objectstack, else empty; EMPTY on objectui today) → input anchor-issue EXISTS, but in the action an empty value is ::error:: + exit 1 on every non-PR run. The objectui#8740 empty-is-supported branch (notice, exit 0, summary-only delivery, the matching summary line) has NO HOME. This is the blocker.", "PM_SWEEP_CLOSED_FLOOR 2026-08-28 (sweep-step env) → input closed-floor: 2026-08-28. Has a home.", "GITHUB_TOKEN = secrets.GITHUB_TOKEN (sweep-step env) → input github-token (required). Has a home.", "PM_SWEEP_REPO = github.repository → set inside the action to the same expression; not an input, by design. Nothing to pass.", "PM_SWEEP_CHECKOUT = github.workspace → set inside the action to the same expression. Nothing to pass.", "PROVENANCE (run / commit / trigger) → built inside the action; the text is identical. Nothing to pass.", "Step Check out the objectstack sweeper (repository objectstack-ai/objectstack, path objectstack-tooling, sparse scripts/pm, no ref) → REMOVED by uses: at a sha. The runner places the whole objectstack repo at that sha as github.action_path.", "Step Checkout repository (actions/checkout@v7) → STAYS in the caller. It is the subject tree; without it the sweep refuses with exit 3.", "Step Setup Node.js (actions/setup-node@v7, node-version 22) → STAYS in the caller. The action has no Node pin and only asserts a floor read from objectstack .nvmrc, which is 22 at the tip.", "on: (cron 37 1,7,13,19, workflow_dispatch, pull_request on this file), permissions (contents read, issues write), concurrency half-state-patrol → caller-owned. The action requires exactly contents read + issues write. No change is required by the action." ], "hypotheses": "H1 CONFIRMED: an unpinned objectstack main checkout, the sweeper run from it, and the constants in env:. The mapping is in constants_to_inputs. H2 PARTLY CONFIRMED: the action runs no checkout of objectstack; the runner places the repo at the pinned sha. But it does NOT set up Node. objectstack#19396 was closed completed on 2026-09-22 by fb7b74691 (#19718), which rewrote the reason: the action holds no Node pin, and a setup-node step inside it would install the very version its floor is compared against. The caller still owes: (1) actions/checkout of its own repo, the swept subject; (2) actions/setup-node at or above the objectstack .nvmrc floor (22); (3) permissions contents read + issues write; (4) with: github-token. H3 NOT MEASURED: nothing under .github/workflows was committed or pushed. The only push was the empty-branch probe, which succeeded and says nothing about the workflow token scope.", "tests": "No file changed, so no gate is owed and none was run. actionlint is not on PATH and not in node_modules/.bin: NOT MEASURED. The readings behind the decision: REST GET actions/workflows/half-state-patrol.yml/runs (total 157; the 8 latest are schedule/success), jobs and annotations of run 36657770288 (quoted in summary), action.yml fetched raw at 43d492ff9 and fb7b74691 and read at the tip, git rev-parse of the action.yml blob at fb7b74691, 9e9bb4641 and the tip (all fc455f1e), and REST GET commits/9e9bb4641 (39 files, zero under .github/actions). Shallow check: git rev-parse --is-shallow-repository = true in /home/user/objectstack. The negative leg (git log -- PATH names 9e9bb4641) is void on a shallow clone. The control leg is the REST path history, which returned both known changes (fb7b74691, 43d492ff9).", "mcp_calls": "0 - no MCP GitHub tool was called", "api_writes": "1 REST write + 1 git push. git push -u origin claude/issue-11174-half-state-patrol-composite-action (the empty-branch probe; the branch sits at base 0ffc423b1 with no commits of mine, and remote refs cannot be deleted from this container). POST /repos/objectstack-ai/objectui/issues/11174/comments (this os-dev-report, via post-stamped.mjs). No pr_create and no label-write/assignee write, because no PR exists.", "open_questions": [ { "question": "objectui runs the patrol with NO anchor issue, by the maintainer's decision (objectui#7852 closed not_planned) and objectui#8740's ruling that an empty anchor is a supported setting. The objectstack composite action treats an empty anchor-issue as a failure (::error::, exit 1) on every non-pull_request run. Switched as it stands, objectui's 4 daily scheduled runs go red, the state objectui#7852 recorded over 50 runs. The PR's own run would still read green, because the action skips both anchor steps on pull_request. Which route?", "options": [ "A - objectstack adds a declared, opt-in summary-only mode to the action: a new input, default OFF, so an empty anchor still fails loudly unless the caller declares the opt-in; a non-numeric anchor fails either way; with the opt-in, an empty anchor gives notice + exit 0 + summary delivery. The seat files it as an objectstack card, and objectui#11174 gets a Blocked-by line naming it; after that the objectui switch is mechanical (anchor-issue from vars.HALF_STATE_ANCHOR_ISSUE, the opt-in, closed-floor 2026-08-28). BUSINESS: measured pull from one named consumer, objectui, whose 8 latest scheduled runs all took this path; the anchor state of cloud and hotcrm is NOT MEASURED. LONG-TERM: one action carries the setting as a declared contract, and objectui keeps no patrol logic. The cost is one input and roughly 20 lines in action.yml plus one objectstack PR ahead of this card. ANTI-AI-ERROR: the setting is declared and enforced, and the default is unchanged, so objectstack losing its own variable still fails loudly; an agent copying a caller sees the opt-in by name. STARTUP: one input with measured pull; it is not a gate.", "B - objectui configures an anchor (open a tracking-labeled issue, set the repository variable HALF_STATE_ANCHOR_ISSUE) and switches with no objectstack change. BUSINESS: it reverses the maintainer's own decline (「7852 太麻烦,直接关闭」), needs a repo-admin action only the maintainer can take, and gives the findings a reader (the summary-only cost objectui#5791 measured goes away). LONG-TERM: zero new action surface; objectui matches the reference caller exactly. ANTI-AI-ERROR: no new setting, but the anchor is rewritten 4 times a day, and in objectstack its rows were measured costing seats a handling step each (objectstack ruling #208 retired the schedule there for that). STARTUP: no capability expansion; it adds a standing board write and the maintainer's time.", "C - switch now and accept red scheduled runs until A or B lands. ANTI-AI-ERROR: the worst option. A check red on the healthy case trains readers to ignore red, which is the state objectui#8740 repaired, and the acceptance run (pull_request) cannot see it. BUSINESS / LONG-TERM: it buys the pin a few days earlier at the cost of a known-bad signal. STARTUP: no new surface.", "D - a caller-side workaround: continue-on-error on the action step, or an if: that skips the action on non-PR runs while the variable is empty. ANTI-AI-ERROR: continue-on-error also swallows exits 2 and 3, the sweep's own death, which is the shape where could-not-read looks clean. The if: variant stops the scheduled sweep outright. Both are tolerance on the consumer side, which the dispatch forbids inventing. LONG-TERM: a second setting that lives only in objectui.", "E - objectui retires its standing patrol, as objectstack did under ruling #208. This is outside ruling 5713650969, which names objectui as a sibling that switches, so it is the maintainer's call. It still needs A or B for any manual run. STARTUP favours it. BUSINESS is NOT MEASURED: nobody has measured who reads objectui's run summaries." ], "recommendation": "A. On business it serves a measured, live objectui setting rather than asking the maintainer to reverse a decline. On long-term it keeps the one-action, contract-first shape that ruling 5713650969 set. On anti-AI-error the opt-in is declared and the loud default is kept, whereas C trains ignore-red and D hides the sweep's own death. On startup it adds one input with named pull and no gate. Choose B instead only if the maintainer prefers zero new action surface and is willing to reopen the anchor setup he closed." }, { "question": "Which sha does the eventual switch pin? The brief says \"the action's newest commit on objectstack main\". A composite-action pin freezes the WHOLE repository, the sweeper included, not only action.yml.", "options": [ "A - the objectstack main tip at implementation time (read now: 4b4ee88fbc530a155ce3ea0570ad81d905d3afbb, whose action.yml blob is identical to the last change to the action).", "B - the newest commit that touched .github/actions/half-state-patrol (read now: fb7b74691f7d192430f6b3b457a858dc442ad0e0, 2026-09-22). That rolls objectui's sweeper back 4 check-half-states.mjs commits (628e55dfa, 4a12ac0c4, f151ef2c9, 6eaa0f4a8, all 2026-09-23) behind what it runs today from main." ], "recommendation": "A. BUSINESS: the board keeps the sweeper it has today, with no regression. LONG-TERM and ANTI-AI-ERROR: the pin is one reviewed moment either way, and B silently downgrades predicates. STARTUP: same cost. Either way the PR body records the sha and the time it was read." } ], "out_of_scope_findings": [ "carrier: 承接者:无 · noted, not filed (prose drift, outside the three filing classes): the .github/workflows/merge-queue-head-patrol.yml header says \"`half-state-patrol.yml` fails when its anchor variable is unset\". That has been false since objectui#8740. Run 36657770288 shows an unset anchor giving a ::notice:: and success. Option C would make it true again. The objectui#11174 claim bars other workflows, so the migration PR cannot carry it.", "dedupe words for the option-A card, if the seat files one: half-state-patrol action anchor optional · anchor-issue empty summary-only · composite action no-anchor supported configuration · objectui#8740 action parity · sibling patrol without anchor" ] }Generated by Claude Code
objectstack-fleet commentedon Sep 30, 2026
Review of the #11174 dev report
5905306134against the source:needs_decisionaccepted.pm:dispatched→pm:blockedon objectstack-ai/objectstack#20793.domain:devxseat 2 (objectui#10917),session_01TdiauJaVCHuj45EzZGUxHh, 2026-09-30T06:19Z. The claim5905159945stands, and the assignee stays.anchor-issueon every non-PR run (objectstackmain,.github/actions/half-state-patrol/action.yml:313-315).:110).pull_request.maintip at implementation time, not the action's own last commit.fb7b74691would silently roll objectui's sweeper back fourcheck-half-states.mjscommits it runs today.9e9bb4641when this card was filed" as the action's newest commit is wrong. This seat read it off a shallow objectstack clone, where the boundary commit appears to add every file.fb7b74691(#19718, 2026-09-22), then43d492ff9(#19225)..github/workflows/merge-queue-head-patrol.yml's header sayshalf-state-patrol.yml"fails when its anchor variable is unset", which has been false since objectui#8740. carrier: 承接者:无.claude/issue-11174-half-state-patrol-composite-action(at base0ffc423, no commits) stays for the re-dispatch after the ruling.objectstack-fleet commentedon Sep 30, 2026
Blocked-by:moves: objectstack-ai/objectstack#20793 is closed (the maintainer ruled decision A, record5905998989). This card now waits on its execution card, objectstack-ai/objectstack#20798: the action's declared opt-in for boards with no anchor issue, claimed and dispatched by this seat (5906044322). When #20798 lands, this card switches with the opt-in on and the sha pinned per5905360637.domain:devxseat 2,session_01TdiauJaVCHuj45EzZGUxHh, 2026-09-30T07:08Z.objectstack-fleet commentedon Sep 30, 2026
Release:
session_01TdiauJaVCHuj45EzZGUxHh(accounthuangyiirene,domain:devxseat 2) · reason: shift close on the maintainer's order 「当前任务处理完,合并后就下班」, with the card unblocked but not re-dispatched · destination:pm:queue, unassigned, for the nextdomain:devxseat. Released at 2026-09-30T09:13Z. This releases the claim5905159945.Handover record
79114850f0f559dcb4fb432f5bcfc12947a03de6(landing record on #20798), and that sha is objectstackmain's tip at release. This body'sBlocked-by:line is removed.claude/issue-11174-half-state-patrol-composite-action: its last push is0ffc423b1(objectuimainof 06:04, no commits of its own), and no PR is open. objectuimainis now37d1662. The next dev starts the branch fresh frommain.anchor-optional: trueand leavesanchor-issueempty. That is objectui's supported no-anchor configuration (objectui#8740; #20793 decision A,5905998989).5905360637): pin objectstackmain's tip at implementation time, a 40-char sha that contains79114850for later. Do NOT pin the action's own last commit, which would roll the sweeper back. Record the sha and the time it was read in the PR body.79114850fpassesanchor-optionalas an unexpected input: the runner only warns, and every scheduled run goes red..github/workflows/half-state-patrol.yml; the Half-State Patrol section ofcontent/docs/guide/ci-cd-pipeline.md(a review face, so a contract-review record on the landing head is owed); andscripts/__tests__/ci-cd-pipeline-doc.test.tsplus any othergit grep half-state-patrolhit whose assertion moves. At release no open objectui PR (9 scanned) touches any of these.configured=false, a::notice::, Update skipped, and the run green. The PR's ownpull_requestrun skips both anchor steps and cannot show this.objectstack-fleet commentedon Oct 1, 2026
Claim: PM loop,
domain:devxlane queue (R5 ofdomain:devxseat 2, marker5912527248). The maintainer's concurrency order 「并发保持3」 fills two dev slots from this lane's queue beside objectui#11070 round 6.Session:
session_01TdiauJaVCHuj45EzZGUxHhAccount:
huangyiireneBranch:
claude/issue-11174-half-state-patrol-composite-action-r2Worktree:
objectui-issue-11174Domain:
domain:devxSeat:
domain:devx#2(objectui#10917)File surface: unchanged from the handover
5908038257..github/workflows/half-state-patrol.yml:uses: objectstack-ai/objectstack/.github/actions/half-state-patrol@<40-char sha>withanchor-optional: trueandanchor-issueempty. Pin objectstackmain's tip read at implementation time, which must contain79114850f; record the sha and the time it was read in the PR body.content/docs/guide/ci-cd-pipeline.md. This is a review face, so an at-tier record on the landing head is owed.scripts/__tests__/ci-cd-pipeline-doc.test.ts, and any othergit grep half-state-patrolhit whose assertion moves.Container & model:
S,mode:subagent, model: opus (TIER_DEFAULT; the--tierrun over the surface printed "no path-derived mandate").Clause-②: no. CI wiring only; no published contract or accept set moves.
Thread-read: 5908038257
Serial constraints cleared: 2026-10-01T04:42Z, against objectui
origin/main5262f7dand objectstackorigin/main5dbeb7d7b, over the 9 open objectui PRs (fix(plugin-detail): record:quick_actions.requiredPermissions publishes the contract's shared describe (objectui#10224) #11329, fix(types,layout,app-shell): a nav entry's inline locale-map label passes the door and renders in the viewer's locale; three inert nav resolver props retire (objectui#11299) #11325, fix(react,app-shell,plugin-kanban,plugin-calendar): a standalone object-kanban / object-calendar honours the spec'spagenavigation, and a mode-less block, through the host's record navigator (objectui#11293) #11323, docs: taught action:* nodes move their executor keys into the specpropertiesbag (objectui#11183) #11317, docs(skills): the project-setup guide stops mounting app-shell's ObjectView with an objectName prop it never had (objectui#11011) #11316, feat(cli):objectui validateandobjectui checkjudge through the strict authoring face (objectui#5250, slice A) #11069 parked, dependabot, release). None touches this surface. objectui#11070 round 6 and objectui#11101, dispatched beside it, are file-disjoint.objectstack-fleet commentedon Oct 1, 2026
os-dev-report
{ "issue": 11174, "status": "done", "branch": "claude/issue-11174-half-state-patrol-composite-action-r2", "pr": "https://github.com/objectstack-ai/objectui/pull/11332", "session": "session_01TdiauJaVCHuj45EzZGUxHh (mode:subagent, so this is the parent seat's id, and it is the Claude-Session trailer on both commits)", "premise_still_valid": true, "final_head": "ec0c6e49105ba128702b77f97dcb2688a8bcdd6f", "summary": "Implemented the Zone 1 rulings in draft PR #11332, head ec0c6e49105ba128702b77f97dcb2688a8bcdd6f; the newest Claim, 5924897388, names this branch. THE STEP: .github/workflows/half-state-patrol.yml no longer checks out objectstack (no ref:, so main) or runs node objectstack-tooling/scripts/pm/check-half-states.mjs, and the inline resolve, update, summary and fail steps and the ANCHOR_ISSUE env are gone. One step replaces them: uses: objectstack-ai/objectstack/.github/actions/half-state-patrol@0c5a71b0942d54e56ad365f0b2a173fd84c1c5e1, with github-token, anchor-issue: '' (passed explicitly so the declaration is visible), anchor-optional: true and closed-floor: '2026-08-28'. actions/checkout@v7 and actions/setup-node@v7 (node '22') stay in the caller because the action needs both. Trigger, schedule, permissions, concurrency, the job key and the job name 'Live half-state sweep' (the name dependabot-merge-gate classifies) are unchanged; both versions were parsed and compare SAME. The prose adopted from upstream is deleted. The header now carries only this board's own content: the pin and how to bump it, the no-anchor decision, the closed-card floor. THE PIN: 0c5a71b0942d54e56ad365f0b2a173fd84c1c5e1 is objectstack origin/main's tip, read at 2026-10-01T04:46:15Z. git merge-base --is-ancestor 79114850f0f559dcb4fb432f5bcfc12947a03de6 0c5a71b0942d54e56ad365f0b2a173fd84c1c5e1 gives exit 0, which proves itself even on the shallow clone; 127 commits lie between them. At the pin, action.yml (blob 2df36034) and check-half-states.mjs (blob fa35f635) are byte-identical to what 79114850f landed. The input names were read off action.yml at the pin: declared and passed are the same four, with none undeclared and the required github-token passed. The PR body records the sha, the read time and the ancestry proof. DOCS and TESTS: the Half-State Patrol section of content/docs/guide/ci-cd-pipeline.md is rewritten. In scripts/__tests__/ci-cd-pipeline-doc.test.ts, the objectui#8043 block compared PM_SWEEP_* env keys, and the workflow no longer sets any. It now compares the section with the patrol step's parsed with: inputs in both directions, and holds the floor value, the anchor configuration and the 40-hex ref shape. One SWEEP_DECLARED_NON_RUN_COMMANDS entry is added: the section names objectstack's sweeper, and the job has no run: step any more. SURFACE NOTE, stated rather than silently taken: the ruling's sha pin is off-convention for this repo's Action Ref Convention gate, which is blocking and admits exceptions only as DECLARED_EXCEPTIONS entries. So the PR also edits scripts/check-action-ref-convention.mjs (one entry with its reason and issue, plus the docblock that said 'deliberately empty') and scripts/__tests__/check-action-ref-convention.test.ts. That test's two non-vacuity cases replaced the real table with a synthetic one and went red once the table held an entry; they now append to it. Neither file was a git grep half-state-patrol hit before the change. Both read this workflow's text, which is the original claim's definition of the surface (5905159945, 'the tests or scripts that read this workflow's text'). No other workflow and nothing in objectstack was touched; the seat may want to amend the claim's surface. CONFLICT NOTED: the brief asks for 'a skip-changeset justification if no released package changes', but os-dev.md says objectui's skip-changeset label has no readers and must never be applied. No label was written. check-changeset-presence printed 'no changeset is owed', and the PR body says why. ACCEPTANCE: this PR's pull_request run of Half-State Patrol (run 36818980862) cannot show the opt-in, because it skips both anchor steps; the PR body says so. At report time that run was in_progress with 'Set up job' = success, meaning the runner resolved the action at the pinned sha. The live reading is the first scheduled (cron 37 1,7,13,19 UTC) or dispatched run after landing. Expected: configured=false, the ::notice:: naming anchor-optional: true, Update the pinned anchor issue skipped, and a green run. The PR is assigned to huangyiirene. It is draft; it was not marked ready and not enqueued. The worktree is removed, and no process I started is still running.", "tests": "All on the final head ec0c6e49105ba128702b77f97dcb2688a8bcdd6f unless a sha is named. (1) vitest run scripts/__tests__/ via os-verify-lock, slot objectui-issue-11174-scripts-final, NODE_OPTIONS=--max-old-space-size=4096, --maxWorkers=2, under a MemAvailable watchdog of 2500 MB: 'Test Files 177 passed | 2 skipped (179)', 'Tests 5374 passed | 2 skipped (5376)', 'VERDICT command-exit 0', held 294s on a shared box. The identical result on a13f4e5f. (2) Targeted: vitest run ci-cd-pipeline-doc.test.ts + check-action-ref-convention.test.ts gives 2 files and 104 tests passed; the base 5262f7dd gave 101. (3) actionlint 1.7.7, a release binary because actionlint is not wired in this repo: exit 0 on the workflow. Positive control: permissions: misspelled gives exit 1, 'unexpected key permissionz'. actionlint cannot check a remote composite action's inputs, so the inputs were checked by parsing action.yml at the pin. (4) tsc -p tsconfig.scripts.json --listFiles on a13f4e5f via the lock: exit 0, both edited test files are in the program. ec0c6e49 changes only the YAML. (5) Gates, all exit 0 on ec0c6e49: check:doc-fences; docs:check-links ('Links are valid across 17 scan roots'); check:control-bytes; check-changeset-presence ('no changeset is owed'); check:action-ref-convention ('0 off-convention and undeclared, 0 stale'); check:new-line-citations ('0 new citation(s)'); check:test-path-roots; check-shell-escape-residue. Also check-governed-queue-guard --test over the 5 paths ('NOT GOVERNED'), a control-byte grep over the 5 files (no match), and a CJK scan of the added lines (0). (6) ESLint, narrowed and proven: eslint --format json over the 3 lintable files on a13f4e5f reports 3 files, 0 errors, 0 warnings. The population is root lint:root (eslint . minus packages/, examples/, apps/, docs/), and the YAML and MD are not in it. eslint.config.js has no parserOptions or projectService, so linting is not type-aware, and eslint-rules/*.js read no files (zero hits for readFileSync/existsSync/readdirSync), so untouched files' verdicts cannot move. The full pnpm lint is CI's. (7) Ablations: four through objectstack scripts/ablation-replace.mjs in WRAP mode on committed head a13f4e5f, each with the anchor hit once, the blob changed, and the file restored with blob == HEAD and git diff HEAD empty. With @main in place of the sha: exactly 1 red ('pins the action to a 40-character sha'), while check-action-ref-convention.test.ts stayed GREEN; that is the hole the new pin covers, because the exception matches by workflow and action, not by spelling. With anchor-issue '9857': 1 red. With closed-floor deleted: 2 red. With the github-token name stripped from the doc bullet: 1 red. A fifth proof needed no mutation: scan(root, {exceptions: []}) gives 1 offender, 'half-state-patrol.yml ... [sha]'. NOT MEASURED: (a) the live opt-in reading, which cannot exist before landing because the PR run skips the anchor steps; (b) this PR's CI at report time: of 25 runs, 16 success, 1 skipped (Dependabot Auto-merge) and 8 in_progress (Lint, CI, Live E2E, Spec Main Shape Gate, Doc Snippet Types, Skill Examples, Half-State Patrol, README Exports), and convergence belongs to the PM; (c) whether Dependabot's github-actions updater proposes bumps for this sha-pinned ref.", "mcp_calls": "0. No MCP GitHub tool was called.", "api_writes": "3 fleet-relay writes and 3 git pushes. git push (not REST): the empty-branch probe at 5262f7dd, then a13f4e5f, then ec0c6e49. pr_create through scripts/pm/fleet-write/dispatch.mjs: POST /repos/objectstack-ai/objectstack/dispatches (204), relay run 36818946388 succeeded, executing POST /repos/objectstack-ai/objectui/pulls (draft) and creating #11332, whose body read back byte-identical (11196 bytes, no differing index). label-write --assign huangyiirene on #11332 with no label verbs: dispatch relay run 36819019151 succeeded, executing POST /repos/objectstack-ai/objectui/issues/11332/assignees; the read-back matches. This os-dev-report comment on #11174 went through scripts/pm/post-stamped.mjs. Reads only otherwise: REST GETs of #11174 and its comments, objectstack comment 5905998989, #8740, the PR, and its runs and jobs.", "open_questions": [], "out_of_scope_findings": [ "carrier: 承接者:无 · noted, not filed (prose drift; it is outside the three filing classes, and the claim excludes every other workflow). merge-queue-head-patrol.yml's header still says half-state-patrol.yml 'fails when its anchor variable is unset'. That has been false since objectui#8740 and stays false. Its env comment cites 'the reason half-state-patrol.yml states' (that an issue number is only meaningful in the repo it was minted in); the new header keeps that sentence, so the citation still resolves.", "carrier: 承接者:无 · noted, not filed (prose drift that predates this PR, since objectui#10208). The comments in changeset-guard.yml, performance-budget.yml and lockfile-dedupe.yml, and the render-budget-comment.test.ts docblock, say half-state-patrol.yml lists scripts/invoked-as.mjs in its paths. It has listed only itself since objectui#10208.", "carrier: this PR (#11332) · handled in place, not a finding: the Action Ref Convention gate's DECLARED_EXCEPTIONS is matched by workflow and action, not by spelling, so the ruling's 'never @main' half was held by nothing. The new doc-parity pin in ci-cd-pipeline-doc.test.ts holds it, as ablation 1 shows." ] }Generated by Claude Code
objectstack-fleet commentedon Oct 1, 2026
Seat review of the report
5925257121: ACCEPT PR #11332, pending CI and the at-tier record.domain:devxseat 2 (objectui#10917),session_01TdiauJaVCHuj45EzZGUxHh, R5, 2026-10-01T05:21Z.PR #11332 (draft, head
ec0c6e4, 5 files, +404/−600).check-governed-merges --prreads NOT governed, 1004 changed lines.uses: objectstack-ai/objectstack/.github/actions/half-state-patrol@0c5a71b0942d54e56ad365f0b2a173fd84c1c5e1replaces the objectstack checkout, the run step and the inline anchor steps.github-token,anchor-issue: '',anchor-optional: trueandclosed-floor: '2026-08-28'. The input names were read offaction.ymlat the pin.main's tip, read at 2026-10-01T04:46:15Z.git merge-base --is-ancestor 79114850f… 0c5a71b0…exits 0, with 127 commits between them.action.ymland the sweeper are byte-identical to what79114850flanded.@mainremains, and a doc-parity pin now holds the sha shape. Ablation 1 shows the convention gate alone would not.scripts/check-action-ref-convention.mjsgains oneDECLARED_EXCEPTIONSentry, with its reason and owning issue, and its test's non-vacuity cases now append instead of replacing.5905159945). Without the entry the blocking Action Ref Convention gate goes red on the ruling's own pin.skip-changesetjustification" was wrong. objectui'sskip-changesetlabel has no readers, andos-dev.mdforbids applying it. The dev applied no label, andcheck-changeset-presencereads "no changeset is owed".merge-queue-head-patrol.yml, and theinvoked-as.mjsmention in three workflows plus one test docblock). Both predate this PR, sit outside the filing classes, and have no carrier. They are noted, not filed.37 1,7,13,19) or dispatched run should showconfigured=false, the::notice::, "Update the pinned anchor issue" skipped, and a green run. The seat reads that run before it calls the card done.Landing:
Clause-②: no, butcontent/docs/guide/ci-cd-pipeline.mdis a review face, so an at-tier record onec0c6e4is owed. It is dispatched once CI is green, followed by ready and enqueue.Fixes #11174closes the card, and objectstack#18471'sBlocked-by:naming it clears.objectstack-fleet commentedon Oct 1, 2026
Contract review
Served-tier:
CONTRACT_REVIEW_TIERHead-sha:
ef4ae07a6e3b75a20d02d83e911e7373c1719ad0Local-runs: none
PR #11332 (card #11174), judged as the NET diff against
mainat the head above — an "update branch" merge ofmain770cc5ba4dinto the dev commitsa13f4e5fandec0c6e49; 5 files, +404/−600. Inputs: the card body and all 8 comments, the PR body, file list and diff, and the 41 check-runs on the head: 38success, 3skipped(dependabot,Test (coverage), the coverage shard — all event-gated, none a gate on this PR), 0 failures. Factual claims in the PR body were re-read against the public GitHub API (objectstack's history and PR merge times, the action'saction.ymlat the pin, the head's own job); nothing was built, run or re-run.① Derived judgments
Public surface and accept set: nothing under
packages/**; no exported type, schema or governed rule text moves. The five files are one workflow, one docs page (content/docs/**, a review face — hence this record), two tests and one CI gate script. The PR'sClause-②: nois right.uses:pinned to a 40-hex sha, no@mainref — right. At the head the workflow's threeuses:lines areactions/checkout@v7,actions/setup-node@v7and the action at@0c5a71b0942d54e56ad365f0b2a173fd84c1c5e1. The string@mainsurvives only in header comment prose arguing against it (lines 22–23). The 40-hex shape is pinned by the newci-cd-pipeline-doc.test.tscase, which is the only check holding the "never a branch" half: the convention gate matches an exception by workflow and action, not by spelling, and the diff's docblock says so rather than hiding it.5905360637; handover5908038257items 2–3) — right. Compare79114850f...0c5a71b0: merge-base79114850f, ahead 127, behind 0 — the pin contains the commit that declaredanchor-optional. Compare0c5a71b0...main: behind 0 — the pin is amaincommit (28 behind today's tip). It is not the action's own last commit (fb7b74691), so the sweeper is not rolled back.main's tip, read at 2026-10-01T04:46:15Z" — right, verified by a witness the dev did not use. The pin's PR objectstack#21026 hasmerged_at2026-10-01T04:45:58Z; the next PR to land onmain, objectstack#21037, hasmerged_at2026-10-01T04:51:07Z. The read falls inside that window.dff98c1f5reads 04:39Z but landed at 05:18Z), sogit log --untilor any committer-date read would wrongly call this pin stale.merged_atis the landing time. Between the pin and6f578888a(10 commits, 65 files) nothing under.github/actions/half-state-patrol/,scripts/pm/check-half-states.mjs,scripts/invoked-as.mjsor.nvmrcmoved.action.ymlat0c5a71b0declares exactlygithub-token(required),anchor-issue(default empty),anchor-optional(defaultfalse) andclosed-floor(default empty). The step passes the same four: none undeclared, the required one present.anchor-issue: ''besideanchor-optional: trueis the objectstack#20793 decision-A opt-in, and the action at the pin honours it — right. Its "Locate the patrol sources" step acceptstrue|True|TRUEand judges the spelling on every event, so the head'spull_requestrun already proves the spelling; its "Resolve the anchor issue" step takes the empty-plus-opt-in branch to a::notice::and exit 0. The YAML boolean stringifies totrue, an accepted spelling.vars.HALF_STATE_ANCHOR_ISSUEread is retired; the anchor is a literal empty string — right, with the narrowing named. The handover ruling says "leavesanchor-issueempty", and the variable is unset on this board (measured in5905306134), so no behaviour moves today. After this diff the variable name appears nowhere in the repo (code search onmain: 2 hits — the doc section and the workflow header — both rewritten here), so no instruction dangles. What narrows: turning delivery on is now a workflow edit, not a repository-variable flip. The header and the doc both say exactly that and call it the maintainer's decision. Consistent with the ruling's words and its "by name, not by omission" rationale.37 1,7,13,19 * * *,workflow_dispatch, thepull_requestpath filter,permissions(contents: read,issues: write),concurrency, job keypatroland job nameLive half-state sweep— unchanged (all context lines in the diff) — right. The job name is whatdependabot-merge-gate.mjsclassifies.issues: writeis kept as the card asks, and the header states it is never exercised with no anchor.actions/checkout@v7andactions/setup-node@v7with node'22'— right. The action's Node floor at the pin (.nvmrc) is 22, and the checkout is the swept subject the sweeper refuses to run without.79114850f), the four inputs, the no-anchor configuration and its accepted cost, the PR-run blind spot, the floor, and the hand-run recipe (now withPM_SWEEP_CLOSED_FLOOR=2026-08-28and the pinned-checkout note). The "Action Ref Convention above" cross-reference resolves (## Action Ref Conventionat line 446; this section at 2625). The parity test now compares the section against the step's PARSEDwith:inputs in both directions, plus the floor value, the anchor pair and the ref shape.DECLARED_EXCEPTIONSentry — right, and in-surface. The blocking Action Ref Convention gate admits exactly this form of exception; the entry names workflow, action, owning issue and a real reason; the head'sAction Ref Conventioncheck is green. The two non-vacuity tests now APPEND a synthetic entry to the real table instead of replacing it, so the tree's own entry stays declared under test (the test already imported the table). The docblock's "deliberately empty" claim is removed rather than left false.SWEEP_DECLARED_NON_RUN_COMMANDSentry — right. The section namesscripts/pm/check-half-states.mjs(objectstack's file, absent from this tree) and the job now has norun:step at all.pull_requestrun https://github.com/objectstack-ai/objectui/actions/runs/36826454380 (jobLive half-state sweep, 110253114177) is green: Checkout repository, Setup Node.js and Sweep the board allsuccess. It proves the pin resolves on a real runner, the inputs are accepted and the sweep ran to exit 0 (the action's own fail-if-the-sweep-could-not-run step would otherwise have failed the composite step). It cannot show the opt-in: both anchor steps carryif: github.event_name != 'pull_request'at the pin. The PR body, the header and the doc each say so and name the first scheduled or dispatched run after landing as the live reading (configured=false, a::notice::, the update skipped, a green run).Nothing judged wrong.
② Semver level
No changeset and no
skip-changesetlabel, withClause-②: noon the PR body (its second line) and on the card. This matches what the diff publishes: no released package's source, exports map, schema or contract text moves — only.github/workflows/,content/docs/andscripts/. The head'sChangeset Declaration,Changeset Claim Re-readandChangeset Fixed Group Checkare green, and the body recordscheck-changeset-presencereading "no changeset is owed". The brief-versus-os-dev.mdconflict over askip-changesetlabel was resolved the right way: no label (it has no readers here) and no changeset. The PR'sClause-②: noline is correct.③ Boundary flags
open_questions(5905306134), Q1 (how the no-anchor setting moves onto the action) — answered by ruling and implemented. Route A: objectstack#20793 decision A, executed as objectstack#20812 landing at79114850f; this diff passes the opt-in (judgment 5).main's tip at read time, verified against PR merge times (judgments 2–3).5925257121)open_questions: []— none open.scripts/check-action-ref-convention.mjsand its test read this workflow's text and their verdict moves with it, which is the original claim's own definition of the surface (5905159945). Without the entry the ruling's own pin turns a blocking gate red. No other workflow and nothing in objectstack is touched, so the ⛔ exclusions hold.skip-changesetconflict — answered (section ②).37 1,7,13,19UTC) after landing before calling the card done; a red there is the action's to own, and the roll-back is the one-line pin.merge-queue-head-patrol.yml's header; theinvoked-as.mjsmention in three workflows and one test docblock) — correctly left out. Both predate this PR and sit behind the claim's ⛔ "no other workflow"; no carrier. Not a blocker; the seat's to file or not.merged_atand not againstgit logdates.ec0c6e49). The run on the reviewed head is linked in judgment 12. A presentation gap only.Implemented-by:
claude/issue-11174-half-state-patrol-composite-action-r2Reviewed-by:
session_01TdiauJaVCHuj45EzZGUxHhVERDICT: PASS
Rendered 2026-10-01T07:14Z · isolated contract-review subagent of the seat named in
Reviewed-by:, read-only: no worktree, no build, no test, no gate re-run.objectstack-fleet commentedon Oct 1, 2026
Landed: PR #11332 merged through the queue as
2c274e3at 2026-10-01T07:39Z.Fixes #11174closed this card as completed.domain:devxseat 2 (objectui#10917),session_01TdiauJaVCHuj45EzZGUxHh, R5, recorded at 2026-10-01T07:39Z.5926577785(PASS,CONTRACT_REVIEW_TIER,Local-runs: none) namesef4ae07a6e3b75a20d02d83e911e7373c1719ad0. That is GitHub's update-branch merge ofmaininto the dev headec0c6e4.Live half-state sweeppull_requestrun was green..github/workflows/half-state-patrol.ymlcallsobjectstack-ai/objectstack/.github/actions/half-state-patrol@0c5a71b0942d54e56ad365f0b2a173fd84c1c5e1.79114850f(127 commits after it) and wasmain's tip when it was read.anchor-optional: true, an emptyanchor-issue, andclosed-floor: '2026-08-28'.merged_at, not from git-log committer dates. Merge-queue committer dates predate the landing, so the git-log reading would wrongly call a fresh pin stale.37 1,7,13,19UTC, next due 13:37Z) must showconfigured=false, a::notice::naminganchor-optional: true, "Update the pinned anchor issue" skipped, and a green run. The seat reads it and records it here.Blocked-by:line naming this card clears with this landing. Its other two blockers, objectstack#20786 and hotcrm#1972, remain, so it stayspm:blocked.pm:dispatchedresidue is stripped in the same act.objectstack-fleet commentedon Oct 1, 2026
Owed reading recorded: the scheduled Half-State Patrol after this card's fix landed is green, through the no-anchor opt-in, as designed.
domain:devxseat 2 (objectui#10917),session_01TdiauJaVCHuj45EzZGUxHh, R5, 2026-10-01T13:55Z.36832643549at 2026-10-01T07:50Z, onmain743181a4, and that commit contains this card's fix2c274e3(git merge-base --is-ancestor). So the first scheduled run is36832643549. The next one,36871233608(2026-10-01T13:46Z,mainedfcf5a5), reads identically and confirms it.check-half-states exited 0, under the pinned objectstack action0c5a71b0942d54e56ad365f0b2a173fd84c1c5e1.ANCHOR_ISSUEempty andANCHOR_OPTIONAL: true→configured=false, and the::notice::"No anchor issue configured for objectstack-ai/objectui, which is a supported configuration for this caller: it declares 'anchor-optional: true' …".outcome=skipped.outcome=skipped.successon both runs.configured=false, a::notice::naminganchor-optional: true, the anchor write skipped, green) is observed on a real scheduled run. Nothing further is owed on this card.ci(half-state-patrol): call objectstack's composite action pinned to …
ci(half-state-patrol): a declared `anchor-optional` input lets a boar…