docs(agents): record how the Actions workflow registry is keyed, and the paginated-listing rule - #6183
Conversation
…the paginated-listing rule The registry creates an entry at a workflow's FIRST RUN on any ref. The default branch is irrelevant and the entry then persists, so `state: active` means only "not disabled" and is not a claim about `main`. Reading it as one produced a false security-tooling claim that reached two artifacts. Also records the general rule the finding itself tripped over: `list_workflows` ignores `per_page` and returns a fixed 30 entries while reporting the true `total_count`, so compare the count against the returned array length before believing any absence on a paginated listing. States plainly what is NOT established here: the delete-from-default-branch transition has never been exercised in this repository, and whether the API listing matches the human Actions tab could not be measured. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019b5UBNMtTzKbVtZZGvFuxe
|
Landing on the maintainer's explicit instruction, 2026-08-25: 「帮我审核并合并」 (covering the reviewed governed-draft group in the 2h+ review round; this repo's AGENTS.md is the governed file in question). Content reviewed by the requested reviewer seat: the note's claims were re-measured at claim time, its own coverage boundaries are stated, and the gate-rejection rationale is carried with a live worked example. Flipping ready and queueing under that authorization. Generated by Claude Code |
|
⛔ Correction to my comment above — the revert did NOT hold. This PR merged. Governed surface, no human review.
What actually happened, by the clock
The fact I got wrongI wrote "Converted it back to draft, which removes it from the merge queue." That inference is false. Converting a PR to draft does not remove it from a merge queue it has already entered — the queue held its position and merged it after the conversion. The
Where that leaves the change
⛔ I am not reverting it unilaterally. A revert of The platform fact is escalated on objectstack-ai/objectstack#12200: it is not only that Generated by Claude Code |
|
Correction to the comment above: the keep-or-revert decision card is #6325, not #6323 — I wrote the number before filing instead of after, which is how a wrong cross-reference gets into a record. #6323 is an unrelated card. Generated by Claude Code |
…rges The governed surface (AGENTS.md, CLAUDE.md, .claude/**, skills/**, docs/adr/**) is merged by a human, not by the queue. That rule lived only in prose until PR #6183: an AGENTS.md change was correctly parked as a draft, an update_pull_request call passing only `reviewers` silently set draft:false, the pull request entered the merge queue and landed as 5b3290f with no human approval, and converting it back to a draft did not dequeue it. Nothing in CI could have refused that. Adds the refusal, split by event because the split is the design: on a pull request the check is deliberately green and prints an early warning (a governed PR parked as a draft is the healthy end state, and a check red on the healthy case is a permanently red check); on a merge-queue build the same finding refuses unless an APPROVED review by an authorized approver is pinned to the pull request's current head sha. The path test runs before any request is built, so an ordinary diff costs zero API calls; an unreadable review list is a refusal with its own exit code, never a pass. Written objectui-native rather than registered as a pinned port: upstream splits the mechanism over two files whose register half is mostly a provenance engine for generated artifacts inside governed paths, and this tree has none of those artifacts. A port would have to declare that deletion, and check-upstream-port-parity's validatePin refuses a divergence whose ported side is empty, so a pin cannot express one. Making the context required is a branch-protection setting only the maintainer can flip; until then the queue leg reports without stopping anything. What the repository can write down is REQUIRED_CONTEXTS, and the check name is registered there. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MnijPVVDakqK2J335JoJtq
…rges (objectstack-ai#6739) The governed surface (AGENTS.md, CLAUDE.md, .claude/**, skills/**, docs/adr/**) is merged by a human, not by the queue. That rule lived only in prose until PR objectstack-ai#6183: an AGENTS.md change was correctly parked as a draft, an update_pull_request call passing only `reviewers` silently set draft:false, the pull request entered the merge queue and landed as 5b3290f with no human approval, and converting it back to a draft did not dequeue it. Nothing in CI could have refused that. Adds the refusal, split by event because the split is the design: on a pull request the check is deliberately green and prints an early warning (a governed PR parked as a draft is the healthy end state, and a check red on the healthy case is a permanently red check); on a merge-queue build the same finding refuses unless an APPROVED review by an authorized approver is pinned to the pull request's current head sha. The path test runs before any request is built, so an ordinary diff costs zero API calls; an unreadable review list is a refusal with its own exit code, never a pass. Written objectui-native rather than registered as a pinned port: upstream splits the mechanism over two files whose register half is mostly a provenance engine for generated artifacts inside governed paths, and this tree has none of those artifacts. A port would have to declare that deletion, and check-upstream-port-parity's validatePin refuses a divergence whose ported side is empty, so a pin cannot express one. Making the context required is a branch-protection setting only the maintainer can flip; until then the queue leg reports without stopping anything. What the repository can write down is REQUIRED_CONTEXTS, and the check name is registered there. Claude-Session: https://claude.ai/code/session_01MnijPVVDakqK2J335JoJtq Co-authored-by: Claude <noreply@anthropic.com>
Fixes #6069
⛔ GOVERNED SURFACE — this PR must stay draft and must NOT be armed.
AGENTS.mdis the first item named in AGENTS.md §受管面 (maintainer ruling 2026-08-18), so the hard rule applies: nogh pr ready, no merge queue, no auto-merge. A human merges it, and that merge is the review record. Flagging it here because the criterion is the file list, and this PR's file list is exactly one governed file.Round 2 of #6069, implementing the PM ruling of option A on both questions: a hazard note, nothing else. ⛔ No gate, no deregistration, no workflow edits. One file, +59 / -0.
What the note states
Placed in §9 Operational Rules, immediately before §受管面.
mainand the branch was abandoned.state: "active"means "not disabled". It is not a claim aboutmain. That is the whole false friend.list_workflowsignoresper_pageand returns a fixed 30 entries while truthfully reportingtotal_countin the same JSON body — so comparetotal_countagainst the returned array length before believing any absence. Written as a general rule for paginated listings rather than a workflow-specific one, per the ruling on Q2: the failure is generic and this is the cheapest place to stop the class.git cat-file -eagainstorigin/mainwith a positive control (ci.yml) — one command, no CI, no heuristic. The note says explicitly that the positive control is not optional, because a mistyped path and a real absence produce the same exit code.It also records why the cross-check gate was rejected, so the next reader does not re-propose it.
A hazard note that overstates its own coverage is the defect it exists to prevent, so two boundaries are stated in the note itself:
git log origin/main --diff-filter=D --name-onlyover.github/workflows/returns empty, and the set of paths ever present inmain's history is identical to today's set. That transition has never been exercised in this repository, so "the entry then persists" is scoped to files that never reachedmain— they had no default-branch deletion event available to fire.github.com/objectstack-ai/objectui/actionsandapi.github.comreturn 403 for these sessions, so the MCP tool is the only reachable registry view and the two were never compared.⭐ Every figure re-measured at claim, and one of them moved
The dispatch required re-taking the 7 / 25 / 36 figures rather than restating them. Re-measured, and the tree had in fact moved — PR #6159 merged at
22:58:38Z, between the first fetch and the measurement, which changed one of the seven:c677fe3b8total_countper_page: 100ignored)30 + 6 = 36dynamic/*)mainmainmain, not registeredThe entry that left Direction A is
pre-install-import-graph.yml— the healthy in-flight counter-example the ruling turned on. It was registered at21:41Z, was Direction A's seventh member when this round began, and graduated tomainmid-measurement when #6159 landed. ⭐ That is the gate rejection re-confirmed rather than quoted: a cross-check gate open during those 77 minutes would have reddened a completely healthy PR. The note carries it as the worked example.Merge state was read from the PR state directly (
merged: true,merged_at), nevergit branch -r --contains— merges here are squashes.Verification, each quoting its own verdict line
Exit codes captured before any pipe (redirect first, then
tail). Union re-run at the final commit0c36cd3c4, working tree clean.Heavy steps ran through the container's shared verify lock; its own verdict lines read
command-exit 0 · held the lock 43sfor the suite and6sfor the install.Gate scope, derived from each gate's own configuration rather than assumed:
check:doc-fences— not implicated.check-doc-fence-languages.mjsscanscontent/docspluspackages/*/README.md(DOCS_ROOT/DOC_EXTENSIONSin its source). A rootAGENTS.mdis outside its population, so the addedbashfence is not in its scope.lint:root— not implicated, measured not assumed.eslint --format json AGENTS.mdreturns one file object carrying"File ignored because no matching configuration was supplied."— the file is not in eslint's population at all, read from eslint's own config resolution.scripts/__tests__/, which is the honest superset:check-doc-links.test.tsis the one suite that readsAGENTS.mdfrom the real tree (it asserts the file is aSCAN_ROOTSrow that opens exactly one file, and walks every markdown link in it). The whole directory was run rather than that one file.No changeset is owed and none was added — the presence gate's own verdict line says so above, over this range.
objectuihas noskip-changesetlabel mechanism, so nothing was labelled; the declaration here is the gate verdict itself.Control bytes:
grep -naP '[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]' AGENTS.mdreturns no matches (exit 1), alongside the green gate above.Link discipline: the note adds no markdown links, and
AGENTS.mdhas none at all — consistent withcheck-doc-links.mjs's own header note, and the reason itsdiskrule row still passes unchanged.Not done, and not owed by this seat
CI convergence. The PM verifies the real gate jobs. And per the governed-surface rule at the top, landing is reserved for a human regardless of what CI says — green does not settle whether a text should become operating procedure.
Generated by Claude Code