Skip to content

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

Closed

Description

@objectstack-fleet

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).

Premise (read on objectui main)

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 as 43d492ff9).
    • Pass objectui's board constants through the action's declared inputs: github-token (required), anchor-issue and closed-floor.
    • Keep objectui's own trigger, schedule, permissions and concurrency.
  • The sha is the action's newest commit on objectstack main at implementation time (9e9bb4641 when 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 any scripts/__tests__/** that reads this workflow's text.

Acceptance

Activity

  1. added
    domain:devxobjectui devx stream: fix lands on .github/, scripts/ or release pipeline — devx lane cross-repo
    on Sep 30, 2026
  2. objectstack-fleet commented on Sep 30, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: maintainer direct dispatch, round R4 (a child of objectstack-ai/objectstack#18471, which this session took over at 5905052709)
    Session: session_01TdiauJaVCHuj45EzZGUxHh
    Account: huangyiirene (the card's assignee)
    Branch: claude/issue-11174-half-state-patrol-composite-action
    Worktree: objectui-issue-11174
    Domain: domain:devx
    Seat: domain:devx#2
    File surface: .github/workflows/half-state-patrol.yml; the Half-State Patrol section of content/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 other git grep half-state-patrol hit 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}/files over all 5 open objectui PRs finds no .github/**, no ci-cd-pipeline*, and none of the tests or scripts that name this workflow.

  3. objectstack-fleet commented on Sep 30, 2026

    @objectstack-fleet
    ContributorAuthor

    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

  4. objectstack-fleet commented on Sep 30, 2026

    @objectstack-fleet
    ContributorAuthor

    Review of the #11174 dev report 5905306134 against the source: needs_decision accepted. pm:dispatched → pm:blocked on objectstack-ai/objectstack#20793. domain:devx seat 2 (objectui#10917), session_01TdiauJaVCHuj45EzZGUxHh, 2026-09-30T06:19Z. The claim 5905159945 stands, and the assignee stays.

    • The stop is correct. Checked by this seat:
      • The composite action exits 1 on an empty anchor-issue on every non-PR run (objectstack main, .github/actions/half-state-patrol/action.yml:313-315).
      • objectui's workflow documents "no anchor" as a supported setting (objectui#8740; header :110).
      • A plain switch would therefore turn objectui's scheduled patrol red, and the PR-time run cannot show it, because the action skips its anchor steps on pull_request.
    • Q1 (how objectui's anchor-less setting moves onto the action) is the maintainer's to decide: it is either new action surface (A) or reversing the maintainer's own objectui#7852 decline (B). Filed as [Decision] 半状态巡逻改用 composite action 时,objectui「不设锚点」的设置在 action 里没有落脚处:给 action 加一个显式开关,还是 objectui 改设锚点 objectstack#20793, recommending A. This card waits on it.
    • Q2 (which sha to pin): seat ruling A. Pin the objectstack main tip at implementation time, not the action's own last commit.
      • A composite-action pin freezes the whole repository, the sweeper included.
      • Pinning fb7b74691 would silently roll objectui's sweeper back four check-half-states.mjs commits it runs today.
      • Record the sha and the time it was read in the PR body.
    • Correction to this card's own premise: the body's "9e9bb4641 when 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.
      • REST path history: the action's newest change is fb7b74691 (#19718, 2026-09-22), then 43d492ff9 (#19225).
      • The rule the card states (pin at implementation time) stands.
    • Out of scope, noted: .github/workflows/merge-queue-head-patrol.yml's header says half-state-patrol.yml "fails when its anchor variable is unset", which has been false since objectui#8740. carrier: 承接者:无.
    • The empty branch claude/issue-11174-half-state-patrol-composite-action (at base 0ffc423, no commits) stays for the re-dispatch after the ruling.
  5. objectstack-fleet commented on Sep 30, 2026

    @objectstack-fleet
    ContributorAuthor

    Blocked-by: moves: objectstack-ai/objectstack#20793 is closed (the maintainer ruled decision A, record 5905998989). 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 per 5905360637. domain:devx seat 2, session_01TdiauJaVCHuj45EzZGUxHh, 2026-09-30T07:08Z.

  6. objectstack-fleet commented on Sep 30, 2026

    @objectstack-fleet
    ContributorAuthor

    Release: session_01TdiauJaVCHuj45EzZGUxHh (account huangyiirene, domain:devx seat 2) · reason: shift close on the maintainer's order 「当前任务处理完,合并后就下班」, with the card unblocked but not re-dispatched · destination: pm:queue, unassigned, for the next domain:devx seat. Released at 2026-09-30T09:13Z. This releases the claim 5905159945.

    Handover record

    • Blocker cleared: ci(half-state-patrol): the composite action gains a declared opt-in for boards that run with no anchor issue (summary-only), default off — #20793 decision A objectstack#20798 landed as PR objectstack#20812. It merged at 79114850f0f559dcb4fb432f5bcfc12947a03de6 (landing record on #20798), and that sha is objectstack main's tip at release. This body's Blocked-by: line is removed.
    • Branch claude/issue-11174-half-state-patrol-composite-action: its last push is 0ffc423b1 (objectui main of 06:04, no commits of its own), and no PR is open. objectui main is now 37d1662. The next dev starts the branch fresh from main.
    • Rulings that stand for the next dispatch:
      1. The switch passes anchor-optional: true and leaves anchor-issue empty. That is objectui's supported no-anchor configuration (objectui#8740; #20793 decision A, 5905998989).
      2. Q2, seat ruling A (5905360637): pin objectstack main's tip at implementation time, a 40-char sha that contains 79114850f or 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.
      3. A pin older than 79114850f passes anchor-optional as an unexpected input: the runner only warns, and every scheduled run goes red.
    • File surface (unchanged from the claim): .github/workflows/half-state-patrol.yml; the Half-State Patrol section of content/docs/guide/ci-cd-pipeline.md (a review face, so a contract-review record on the landing head is owed); and scripts/__tests__/ci-cd-pipeline-doc.test.ts plus any other git grep half-state-patrol hit whose assertion moves. At release no open objectui PR (9 scanned) touches any of these.
    • Acceptance evidence to ask for: the first live reading of the opt-in is objectui's first scheduled or dispatched run after landing. The expected result is configured=false, a ::notice::, Update skipped, and the run green. The PR's own pull_request run skips both anchor steps and cannot show this.
  7. objectstack-fleet commented on Oct 1, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop, domain:devx lane queue (R5 of domain:devx seat 2, marker 5912527248). The maintainer's concurrency order 「并发保持3」 fills two dev slots from this lane's queue beside objectui#11070 round 6.
    Session: session_01TdiauJaVCHuj45EzZGUxHh
    Account: huangyiirene
    Branch: claude/issue-11174-half-state-patrol-composite-action-r2
    Worktree: objectui-issue-11174
    Domain: domain:devx
    Seat: domain:devx#2 (objectui#10917)
    File surface: unchanged from the handover 5908038257.

  8. objectstack-fleet commented on Oct 1, 2026

    @objectstack-fleet
    ContributorAuthor

    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

  9. objectstack-fleet commented on Oct 1, 2026

    @objectstack-fleet
    ContributorAuthor

    Seat review of the report 5925257121: ACCEPT PR #11332, pending CI and the at-tier record. domain:devx seat 2 (objectui#10917), session_01TdiauJaVCHuj45EzZGUxHh, R5, 2026-10-01T05:21Z.

    PR #11332 (draft, head ec0c6e4, 5 files, +404/−600). check-governed-merges --pr reads NOT governed, 1004 changed lines.

    • The step.
      • One uses: objectstack-ai/objectstack/.github/actions/half-state-patrol@0c5a71b0942d54e56ad365f0b2a173fd84c1c5e1 replaces the objectstack checkout, the run step and the inline anchor steps.
      • It passes github-token, anchor-issue: '', anchor-optional: true and closed-floor: '2026-08-28'. The input names were read off action.yml at the pin.
      • The trigger, schedule, permissions, concurrency, job key and job name are unchanged, verified by a parsed comparison.
    • The pin (Q2 ruling A).
      • It is objectstack 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.yml and the sweeper are byte-identical to what 79114850f landed.
      • No @main remains, and a doc-parity pin now holds the sha shape. Ablation 1 shows the convention gate alone would not.
    • Surface amendment, accepted:
      • scripts/check-action-ref-convention.mjs gains one DECLARED_EXCEPTIONS entry, with its reason and owning issue, and its test's non-vacuity cases now append instead of replacing.
      • Both read this workflow's text, which is the original claim's definition of the surface (5905159945). Without the entry the blocking Action Ref Convention gate goes red on the ruling's own pin.
      • The docblock correctly records that an entry matches by workflow and action, not by spelling.
    • A seat correction: the brief's "a skip-changeset justification" was wrong. objectui's skip-changeset label has no readers, and os-dev.md forbids applying it. The dev applied no label, and check-changeset-presence reads "no changeset is owed".
    • Out-of-scope findings: two prose drifts in other workflows' comments (merge-queue-head-patrol.yml, and the invoked-as.mjs mention 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.
    • Live acceptance after landing: the first scheduled run (cron 37 1,7,13,19) or dispatched run should show configured=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, but content/docs/guide/ci-cd-pipeline.md is a review face, so an at-tier record on ec0c6e4 is owed. It is dispatched once CI is green, followed by ready and enqueue. Fixes #11174 closes the card, and objectstack#18471's Blocked-by: naming it clears.

  10. objectstack-fleet commented on Oct 1, 2026

    @objectstack-fleet
    ContributorAuthor

    Contract review

    Served-tier: CONTRACT_REVIEW_TIER
    Head-sha: ef4ae07a6e3b75a20d02d83e911e7373c1719ad0
    Local-runs: none

    PR #11332 (card #11174), judged as the NET diff against main at the head above — an "update branch" merge of main 770cc5ba4d into the dev commits a13f4e5f and ec0c6e49; 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: 38 success, 3 skipped (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's action.yml at 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's Clause-②: no is right.

    1. uses: pinned to a 40-hex sha, no @main ref — right. At the head the workflow's three uses: lines are actions/checkout@v7, actions/setup-node@v7 and the action at @0c5a71b0942d54e56ad365f0b2a173fd84c1c5e1. The string @main survives only in header comment prose arguing against it (lines 22–23). The 40-hex shape is pinned by the new ci-cd-pipeline-doc.test.ts case, 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.
    2. The pin honours Q2 ruling A (5905360637; handover 5908038257 items 2–3) — right. Compare 79114850f...0c5a71b0: merge-base 79114850f, ahead 127, behind 0 — the pin contains the commit that declared anchor-optional. Compare 0c5a71b0...main: behind 0 — the pin is a main commit (28 behind today's tip). It is not the action's own last commit (fb7b74691), so the sweeper is not rolled back.
    3. "objectstack 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 has merged_at 2026-10-01T04:45:58Z; the next PR to land on main, objectstack#21037, has merged_at 2026-10-01T04:51:07Z. The read falls inside that window. ⚠️ A trap for the next bump: the ten commits that followed carry committer dates BEFORE the read time (merge-queue build times — dff98c1f5 reads 04:39Z but landed at 05:18Z), so git log --until or any committer-date read would wrongly call this pin stale. merged_at is the landing time. Between the pin and 6f578888a (10 commits, 65 files) nothing under .github/actions/half-state-patrol/, scripts/pm/check-half-states.mjs, scripts/invoked-as.mjs or .nvmrc moved.
    4. Inputs match the action's contract at the pin — right. action.yml at 0c5a71b0 declares exactly github-token (required), anchor-issue (default empty), anchor-optional (default false) and closed-floor (default empty). The step passes the same four: none undeclared, the required one present.
    5. anchor-issue: '' beside anchor-optional: true is the objectstack#20793 decision-A opt-in, and the action at the pin honours it — right. Its "Locate the patrol sources" step accepts true|True|TRUE and judges the spelling on every event, so the head's pull_request run 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 to true, an accepted spelling.
    6. The vars.HALF_STATE_ANCHOR_ISSUE read is retired; the anchor is a literal empty string — right, with the narrowing named. The handover ruling says "leaves anchor-issue empty", and the variable is unset on this board (measured in 5905306134), so no behaviour moves today. After this diff the variable name appears nowhere in the repo (code search on main: 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.
    7. Trigger, cron 37 1,7,13,19 * * *, workflow_dispatch, the pull_request path filter, permissions (contents: read, issues: write), concurrency, job key patrol and job name Live half-state sweep — unchanged (all context lines in the diff) — right. The job name is what dependabot-merge-gate.mjs classifies. issues: write is kept as the card asks, and the header states it is never exercised with no anchor.
    8. The caller keeps actions/checkout@v7 and actions/setup-node@v7 with 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.
    9. Docs section — right. It describes the action call, the pin and the bump rule (the tip, not the action's last commit; must contain 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 with PM_SWEEP_CLOSED_FLOOR=2026-08-28 and the pinned-checkout note). The "Action Ref Convention above" cross-reference resolves (## Action Ref Convention at line 446; this section at 2625). The parity test now compares the section against the step's PARSED with: inputs in both directions, plus the floor value, the anchor pair and the ref shape.
    10. The DECLARED_EXCEPTIONS entry — 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's Action Ref Convention check 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.
    11. The SWEEP_DECLARED_NON_RUN_COMMANDS entry — right. The section names scripts/pm/check-half-states.mjs (objectstack's file, absent from this tree) and the job now has no run: step at all.
    12. Acceptance run — right, with the deferred reading named. The head's own pull_request run https://github.com/objectstack-ai/objectui/actions/runs/36826454380 (job Live half-state sweep, 110253114177) is green: Checkout repository, Setup Node.js and Sweep the board all success. 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 carry if: 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-changeset label, with Clause-②: no on 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/ and scripts/. The head's Changeset Declaration, Changeset Claim Re-read and Changeset Fixed Group Check are green, and the body records check-changeset-presence reading "no changeset is owed". The brief-versus-os-dev.md conflict over a skip-changeset label was resolved the right way: no label (it has no readers here) and no changeset. The PR's Clause-②: no line is correct.

    ③ Boundary flags

    • Round-1 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 at 79114850f; this diff passes the opt-in (judgment 5).
    • Round-1 Q2 (which sha to pin) — answered by ruling and implemented. Ruling A: the pin is main's tip at read time, verified against PR merge times (judgments 2–3).
    • Final report (5925257121) open_questions: [] — none open.
    • Dev flag, surface note (two files beyond the enumerated list) — answered: in-surface. scripts/check-action-ref-convention.mjs and 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.
    • Dev flag, skip-changeset conflict — answered (section ②).
    • Dev flag, live opt-in reading NOT MEASURED — answered, condition carried. Structurally unobservable before landing (judgment 12). The seat reads the first scheduled run (cron 37 1,7,13,19 UTC) 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.
    • Dev flag, Dependabot behaviour on a sha-pinned monorepo action path NOT MEASURED — answered, accepted. Any bump arrives as a PR touching this file, which fires the patrol run: a reviewed moment either way.
    • Dev out-of-scope findings (prose drift in merge-queue-head-patrol.yml's header; the invoked-as.mjs mention 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.
    • Reviewer's own flag (informational, nothing owed on this PR): the merge-queue committer-date trap in judgment 3 is worth one sentence in the header's TO BUMP rule the next time that file is touched, so a future "tip at read time" claim is checked against merged_at and not against git log dates.
    • The card's "with the run linked" acceptance line: the PR body describes the run but carries no URL; the dev report names run 36818980862 by id (head 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-r2
    Reviewed-by: session_01TdiauJaVCHuj45EzZGUxHh

    VERDICT: 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.

  11. objectstack-fleet commented on Oct 1, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed: PR #11332 merged through the queue as 2c274e3 at 2026-10-01T07:39Z. Fixes #11174 closed this card as completed. domain:devx seat 2 (objectui#10917), session_01TdiauJaVCHuj45EzZGUxHh, R5, recorded at 2026-10-01T07:39Z.

    • Reviewed head = landed head:
      • The at-tier contract record 5926577785 (PASS, CONTRACT_REVIEW_TIER, Local-runs: none) names ef4ae07a6e3b75a20d02d83e911e7373c1719ad0. That is GitHub's update-branch merge of main into the dev head ec0c6e4.
      • Nothing was pushed after the record.
      • CI on the head: 41 check-runs, 38 success, 3 skipped. The head's own Live half-state sweep pull_request run was green.
    • Delivered: .github/workflows/half-state-patrol.yml calls objectstack-ai/objectstack/.github/actions/half-state-patrol@0c5a71b0942d54e56ad365f0b2a173fd84c1c5e1.
      • The pin contains 79114850f (127 commits after it) and was main's tip when it was read.
      • It runs with anchor-optional: true, an empty anchor-issue, and closed-floor: '2026-08-28'.
      • The adopted upstream prose is gone, and the docs section and its tests follow.
      • The Action Ref Convention gate carries one declared exception, and a doc-parity pin holds the sha shape.
    • The reviewer's notes:
      • The next bump reads the pin's freshness from PR 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.
      • The PR body carries no run URL, so the head's run is linked in the record.
    • Live acceptance is still owed. The first scheduled run after this landing (cron 37 1,7,13,19 UTC, next due 13:37Z) must show configured=false, a ::notice:: naming anchor-optional: true, "Update the pinned anchor issue" skipped, and a green run. The seat reads it and records it here.
    • objectstack#18471: its Blocked-by: line naming this card clears with this landing. Its other two blockers, objectstack#20786 and hotcrm#1972, remain, so it stays pm:blocked.
    • The pm:dispatched residue is stripped in the same act.
  12. objectstack-fleet commented on Oct 1, 2026

    @objectstack-fleet
    ContributorAuthor

    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:devx seat 2 (objectui#10917), session_01TdiauJaVCHuj45EzZGUxHh, R5, 2026-10-01T13:55Z.

    • Which run is first. The seat's landing note expected the 13:37 run. That was wrong: the 07:37 cron fired as run 36832643549 at 2026-10-01T07:50Z, on main 743181a4, and that commit contains this card's fix 2c274e3 (git merge-base --is-ancestor). So the first scheduled run is 36832643549. The next one, 36871233608 (2026-10-01T13:46Z, main edfcf5a5), reads identically and confirms it.
    • What both job logs show (read through the Actions job-log API):
      • "Sweep the board": check-half-states exited 0, under the pinned objectstack action 0c5a71b0942d54e56ad365f0b2a173fd84c1c5e1.
      • "Resolve the anchor issue": ANCHOR_ISSUE empty and ANCHOR_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' …".
      • "Update the pinned anchor issue": outcome=skipped.
      • "Publish the rendered body to the run summary": success, with the no-anchor line.
      • "Fail the run if the sweep could not run": outcome=skipped.
      • Job conclusion: success on both runs.
    • Every item the handover predicted (configured=false, a ::notice:: naming anchor-optional: true, the anchor write skipped, green) is observed on a real scheduled run. Nothing further is owed on this card.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

domain:devxobjectui devx stream: fix lands on .github/, scripts/ or release pipeline — devx lane cross-repopriority:p2

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions