Skip to content

chore(governance): .github/workflows/** joins the governed surfaces (objectui#12255) - #12289

Merged
os-zhuang merged 4 commits into
mainfrom
claude/issue-12255-workflows-governed
Oct 13, 2026
Merged

os-zhuang merged 4 commits into
mainfrom
claude/issue-12255-workflows-governed

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Fixes #12255
Clause-②: no

.github/workflows/** joins this repository's governed surfaces, on the maintainer's word on the card (answer A, verbatim 「两仓加治理行」). A pull request that edits a workflow now waits as a draft for an APPROVED review by an account in GOVERNED_APPROVERS, and the guard's merge_group leg refuses it without one. No tier mechanism, no change to GOVERNED_APPROVERS, no workflow file edited, no behaviour change to any gate other than the register it reads.

Tier H: this pull request touches AGENTS.md, so it stays a draft until an authorized approval is on record; the claiming seat lands it after that.

  • Adds no product-specific widget, dialog, hook or string (see AGENTS.md › Product-neutral renderer)

维护者速读(草稿)

改了什么: 本仓的受管面从五项变成六项,新增 .github/workflows/**。合并队列守卫脚本的登记表加了一行;AGENTS.md 的「受管面」一节(标题改为六项、新增一条、「上面六项」)、CI 指南里的两句话、Dependabot 合并门禁脚本里的一句注释跟着改。守卫的判定逻辑、两条腿、GOVERNED_APPROVERS 名单都没动。

为什么改: 您在卡上答 A(「两仓加治理行」):workflow 决定每次 push 跑什么、发布什么、合并队列拿什么门禁挡,改它们应该经您批准。cloud 仓已经在它的表里加了同一行;objectstack 那边的同类卡还在决策箱里,这个 PR 不碰它。

风险与代价(含回滚): ① 以后每个改 .github/workflows/** 的 PR 都要等您批准才能落地,包括 Dependabot 的 github-actions 升级:自动合并流程照常批准、入队,然后被队列拒绝一次,等您批准后才能落地(Dependabot 每推一次新提交,就会再入队、再被拒一次;不会无限循环)。② 守卫自己的 workflow 文件也受管了,改守卫的接线同样要您批准。③ .github/ 下其余文件(dependabot.yml、labeler.yml、prompts/、新加的 PR 模板)不受管。回滚:revert 这个 PR 即可,无数据或配置迁移。

席位意见:

你要做的: 读一遍改动,同意就在这个 PR 上留一条 approve;之后由席位落地。另有一个小问题请您顺手定(见下方 Acceptance notes 最后一条):您批准过的 Dependabot workflow 升级,由谁来把它重新放进队列。

The six governed surfaces (after this change)

  1. docs/adr/**
  2. .claude/**
  3. skills/**
  4. AGENTS.md
  5. CLAUDE.md
  6. .github/workflows/** (new: register row { id: 'workflows', prefix: '.github/workflows/', glob: '.github/workflows/**', what: 'CI, deploy and release workflows: what runs on every push, what deploys, what gates the queue' })

Still NOT governed, pinned both in the self-test and the pin test: the rest of .github/ (.github/dependabot.yml, .github/labeler.yml, .github/ISSUE_TEMPLATE/**, .github/prompts/**), a near-miss such as .github/workflow/ci.yml, and scripts/check-governed-queue-guard.mjs itself (scripts/** is not a row).

Every file touched

  • scripts/check-governed-queue-guard.mjs: the workflows row; the register's header comment (it named .github/workflows/** as a widening NOT taken; it now names the ruling, what the row costs and what stays out); the restraint example in the comment above carrierVerdict; self-test: six surfaces and the six globs verbatim, the own-workflow case reversed into a GOVERNED pin (named this-guards-own-workflow-IS-governed-and-its-script-is-not) rather than deleted, the .github/ negatives, a near-miss, the Dependabot bump's queue refusal, and the OK summary text (the six ruled surfaces).
  • scripts/__tests__/check-governed-queue-guard.test.ts: declares exactly the six ruled surfaces; does not govern its own workflow, or CI configuration generally reversed into governs every workflow, its own included, and not the script that workflow runs; new does not govern the rest of .github/.
  • AGENTS.md, section 「⛔ 受管面」 only: heading 五项 → 六项, one bullet in the section's own wording, 「上面五项已含 skills/**」 → 「上面六项已含 skills/**」.
  • content/docs/guide/ci-cd-pipeline.md, ## Governed Surface Guard only: the fixed-list sentence, and the "does not govern its own workflow or CI configuration" sentence.
  • scripts/dependabot-merge-gate.mjs: the comment that said a Dependabot diff "touches no governed path"; it now splits npm from github-actions bumps. No behaviour change.
  • .changeset/12255-governed-workflows.md: empty frontmatter, no published package moves.

The dispatch's hypotheses, measured on origin/main (74964ad) before any edit

  • H1(a) holds: governed-surface-guard.yml carries no paths: / paths-ignore: (the pattern exits 1 there; the same pattern hits ci.yml and four other workflows as the control), so the card's paths: clause does not apply and no workflow file is edited.
  • H1(b) holds: dependabot-merge-gate.mjs imports node:fs and ./invoked-as.mjs only; outside the guard, GOVERNED_SURFACES is named only in prose comments and in the guard's own pin test (control: the guard file itself holds it nine times).
  • H1(c) holds: every text the release comment listed moved. Two near-matches were read and left on purpose; see Acceptance notes.
  • H1(d) holds: check-doc-snippet-types.mjs, merge-queue-reporting.test.ts and ci-cd-pipeline-doc.test.ts enumerate no surface list (control: the guard's pin test does).
  • H2 holds, executed as stated: the NOT GOVERNED pin is reversed, not deleted; the .github/ISSUE_TEMPLATE/** and .github/dependabot.yml negatives stay NOT GOVERNED.
  • H3 holds: --test .github/workflows/ci.yml .github/workflows/lint.yml answered NOT GOVERNED (exit 0) before and answers GOVERNED (exit 3) after. On the bump's pull request the guard exits 0 (early warning), so dependabot-merge-gate.mjs still goes green and the workflow approves (as github-actions[bot]) and enqueues; the queue leg's authorized predicate then refuses it with exit 3. The self-test now pins that consequence. Re-enqueue loop: dependabot-auto-merge.yml subscribes pull_request with GitHub's default types only and no merge_group, check_suite or pull_request_review trigger, so a queue refusal fires nothing; the bump re-enters the queue only on Dependabot's next push. Read from the trigger block, not replayed live.
  • H4: objectui has no gate capping AGENTS.md lines or bytes per line. The file-name probe for a line ratchet answers nothing here and answers scripts/pm/check-skill-line-ratchet.mjs in the objectstack checkout (control). So the new bullet is a new line.

Gates, at d5f0181e (the final commit; exit code captured before any pipe)

Command Exit Verdict line
node scripts/check-governed-queue-guard.mjs --self-test 0 OK check-governed-queue-guard self-test: 193 cases pass (the six ruled surfaces …
node scripts/check-governed-queue-guard.mjs --test .github/workflows/ci.yml 3 ⛔ GOVERNED — 1 of 1 path(s) are on a governed surface
node scripts/check-governed-queue-guard.mjs --test over this PR's six files 3 ⛔ GOVERNED — 1 of 6 path(s) are on a governed surface (AGENTS.md)
--test over .github/dependabot.yml .github/labeler.yml .github/ISSUE_TEMPLATE/bug_report.md .github/pull_request_template.md 0 ✅ NOT GOVERNED — 4 path(s) checked against 6 governed surface(s)
pnpm exec vitest run --maxWorkers=2 scripts/ (lock) 0 Test Files 187 passed, 2 skipped (189) · Tests 5622 passed, 2 skipped (5624)
pnpm exec vitest run over the four package tests that read content/docs/** (lock) 0 Test Files 4 passed (4) · Tests 175 passed (175)
pnpm type-check:scripts (lock; the pin test and the guard are in its --listFilesOnly) 0 VERDICT command-exit 0
pnpm exec eslint --format json over the three touched script files 0 3 files, 0 errors, 0 warnings
node scripts/check-control-bytes.mjs 0 ✅ check-control-bytes: OK
node scripts/check-new-cross-file-line-citations.mjs 0 VERDICT new-cross-file-line-citations: 0 new citation(s)
node scripts/check-doc-links.mjs 0 Links are valid across 17 scan roots.
node scripts/check-shell-escape-residue.mjs 0 ✅ check-shell-escape-residue: OK (5/5 root(s) resolved …
node scripts/check-doc-fence-languages.mjs (+ --self-test) 0 / 0 ✅ check:doc-fences …
node scripts/check-doc-example-ids.mjs 0 ✅ 415 real reference(s) all resolve
node scripts/check-doc-component-types.mjs 0 ✅ Every documented component type is registered.
node scripts/check-pre-install-import-graph.mjs (+ --self-test) 0 / 0 ✅ check-pre-install-import-graph: OK …
node scripts/markdown-test-inputs.mjs --audit 0 123 candidate test files, all adjudicated
node scripts/check-changeset-presence.mjs 0 ✅ … no changeset is owed.
node scripts/check-changeset-no-major.mjs, check-changeset-claims.mjs, check-pending-changeset-literals.mjs 0 green
node scripts/check-test-path-roots.mjs, check-entry-guard.mjs, check-action-ref-convention.mjs 0 green

The eslint run is a declared narrowing, not a repo-wide run: the root config lints .ts/.tsx with tseslint.configs.recommended (the .mjs files resolve to zero rules); no parserOptions.project or projectService is set, so type-aware linting is off and this diff cannot move a verdict on an untouched file. pnpm lint itself is CI's. Not run locally: the built-package gates of Repo Gates (check-doc-snippet-types.mjs, check-doc-example-types.mjs, check-doc-json-fences.mjs, check-skill-examples.mjs), because this diff adds no fenced code block; CI runs them.

Ablation (one-time proof, not a kept test)

With the fix committed, node scripts/ablation-replace.mjs (objectstack's tool) deleted the workflows row through a literal anchor that hit once (blob 81a9eef6 → abf64d8b, on-disk row count 1 → 0), ran the pins, and restored. Mutant: --self-test exit 1, 4 of 192 case(s) failed (the-register-declares-exactly-the-six-ruled-surfaces, and-they-are-the-ruled-globs-verbatim, this-guards-own-workflow-IS-governed-and-its-script-is-not, a-github-actions-bump-approved-only-by-the-bot-is-REFUSED-at-the-queue-with-code-3); the pin test exit 1, 3 failed; --test .github/workflows/ci.yml back to NOT GOVERNED, exit 0. Restore: blob equals HEAD (81a9eef6) and git diff HEAD is empty. Direction observed: red, as expected.

Acceptance notes

  • scripts/__tests__/child-verdict.test.ts carries the string the five ruled surfaces inside a synthetic self-test line it feeds to a parser. It is a fixture of the parser, not a claim about the register, so it is left as is.
  • ci-cd-pipeline.md's shell-escape-residue paragraph and that script's header name AGENTS.md, CLAUDE.md, skills/** and .claude/** as governed. That lists the governed members of that scan's roots, not the whole set, and stays true.
  • ci-cd-pipeline.md's ### Dependabot Auto-Merge section still says patch and minor bumps are approved and enqueued. That stays true; the queue refusal for github-actions bumps is written in the Governed Surface Guard section this PR edits, and in the gate script's comment. Carrier: none.
  • .github/pull_request_template.md arrived on main while this branch was open. It is outside the row and NOT GOVERNED (the --test row above).
  • The pin test keeps its .github/ negatives to YAML paths (.github/ISSUE_TEMPLATE/config.yml stands in for the card's ISSUE_TEMPLATE/**): a markdown path literal in a test source is read by markdown-test-inputs.mjs --audit as a document the test consumes, which the audit flagged on the first version. The self-test keeps the .github/prompts/** negative.
  • Open question for the maintainer, raised here and not acted on: once an authorized approval is on a governed Dependabot github-actions bump, nothing re-enqueues it. dependabot-auto-merge.yml does not subscribe pull_request_review, and ruling C hands landing to "the claiming seat", which a Dependabot PR does not have. This PR changes neither.

Session: https://claude.ai/code/session_011oKFDZMRoPGDbStvxQa172


Generated by Claude Code

…objectui#12255)

The maintainer's ruling on objectui#12255 (answer A, verbatim 「两仓加治理行」)
adds `.github/workflows/**` to this repository's governed surfaces.

- scripts/check-governed-queue-guard.mjs: the `workflows` register row; the
  header comment that named the row as a widening NOT taken now names what it
  costs (the guard governs its own workflow; a Dependabot github-actions bump
  is governed) and what stays out (the rest of .github/); the carrierVerdict
  comment's restraint example moves with it; the self-test pins six surfaces,
  reverses the own-workflow case into a GOVERNED pin, and adds the .github/
  negatives, a near-miss and the Dependabot bump's queue refusal.
- scripts/__tests__/check-governed-queue-guard.test.ts: the six-surface case,
  the reversed own-workflow case and the .github/ negatives.
- AGENTS.md 「受管面」: 五项 -> 六项, one bullet, 上面六项.
- content/docs/guide/ci-cd-pipeline.md: the fixed-list sentence and the
  "does not govern" sentence.
- scripts/dependabot-merge-gate.mjs: the comment that said a Dependabot diff
  touches no governed path. No behaviour change.

Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011oKFDZMRoPGDbStvxQa172
…aragraph names

`ci-cd-pipeline-doc.test.ts`'s workflow inventory reads every bare `NAME.yml`
in prose as a workflow file; `dependabot.yml` is the Dependabot config, not a
workflow, so it is spelled `.github/dependabot.yml` (and its two neighbours
likewise), the form that test skips by design.

Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011oKFDZMRoPGDbStvxQa172
…n test

`markdown-test-inputs.mjs --audit` reads a markdown path literal in a test
source as a document that test consumes, and flagged
`.github/prompts/component.prompt.md` as unadjudicated. The pin test now names
YAML paths only (`.github/ISSUE_TEMPLATE/config.yml` stands in for the card's
`.github/ISSUE_TEMPLATE/**`); the self-test keeps the `.github/prompts/**`
negative, and the audit is green again.

Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011oKFDZMRoPGDbStvxQa172
@github-actions github-actions Bot added documentation Improvements or additions to documentation tests labels Oct 13, 2026
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

维护者速读(终稿)

席位 domain:devx @ objectui seat 1 · session_011oKFDZMRoPGDbStvxQa172 · 2026-10-13T02:06Z · 对照 head d5f0181e 的 diff 校正。

改了什么:按您「两仓加治理行」的裁决,把 .github/workflows/** 加进 objectui 的受管面。守卫 check-governed-queue-guard.mjs 的登记表加一行。AGENTS.md「受管面」从五项改为六项。CI 指南两句、Dependabot 门禁一条注释随之更新。守卫自测把原来钉「workflow 不受管」的用例反转成钉「受管」,没有删。.github/ 下其余文件(dependabot.yml、labeler.yml、prompts/)仍不受管。

为什么改:本轮每个 CI PR 都实际等了您的批准,而守卫还答 NOT GOVERNED,规则和机器对不上。合并后,改 workflow 的 PR 没有授权批准就进不了合并队列。

风险与代价(含回滚):

  • Dependabot 的 github-actions 升级从此也要等授权批准:自动批准仍会发生,但批准者是 github-actions[bot],队列会拒。npm 升级不受影响。
  • 守卫自己的 workflow 文件也受管,改它要您批准。
  • 回滚:revert 这一个 squash commit,规则即回到五项。

席位意见:可合。登记行与您的裁决逐字一致,6 个文件 +112/−38,CI 全绿。dev 留的一个问题我已按既有规则答复:批准后的 Dependabot workflow 升级,您批准时可顺手入队,否则由本席落地,不加新触发器。

你要做的:批准本 PR(os-zhuang 或 hotlong 任一账号的 Approve)。批准后由席位转 ready 并入队落地。


Generated by Claude Code

@os-zhuang
os-zhuang marked this pull request as ready for review October 13, 2026 02:14
@os-zhuang
os-zhuang added this pull request to the merge queue Oct 13, 2026
Merged via the queue into main with commit 45ae6b8 Oct 13, 2026
33 checks passed
@os-zhuang
os-zhuang deleted the claude/issue-12255-workflows-governed branch October 13, 2026 02:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation tests

Projects

None yet

3 participants