Skip to content
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
This repository was archived by the owner on Nov 4, 2026. It is now read-only.

governance: agent-instruction files are human-merge only — AGENTS.md carries the governed-surface rule #5149

Closed

Description

@os-zhuang

Maintainer ruling (2026-08-18, PM chat, objectstack skills-seat session session_01Rn7aaamsR99FXRqLcpL99q). The maintainer asked whether edits to AGENTS.md-class files need human review including in the objectui and cloud repos (「任何对 agents.md 等文件的修改是不是也需要人类审核? 包括 objectui cloud仓库」) and approved the seat's recommendation verbatim: 「同意」.

Named reader: the repo:objectui execution seat — this card is the cross-repo replication half of objectstack#9495 and lands here (file-at-destination).

What to land (this repo's AGENTS.md, one rule block)

  1. Governed surface for this repo: AGENTS.md, CLAUDE.md, .claude/** (agents, hooks, skills, settings — all of it), plus docs/adr/** if/where it exists here.
  2. Hard rule: agent seats never flip ready, never enqueue, and never arm auto-merge on a PR whose diff touches the governed surface — such PRs stay draft, awaiting a human merge; the human's merge action IS the review record (per the objectstack#9495 model: no per-PR approval click required).
  3. Mixed diff: one governed path in the diff forks the whole PR to human-merge — no proportionality judgment.
  4. Keep the wording durable (the maintainer's standing criterion: transient/transition-window facts do not enter instruction files).

Audit tooling note: the report-only governed-merges audit ships first for objectstack only (objectstack#9495); this repo relies on the rule text + seat discipline until a cross-repo audit follow-up exists — state that plainly in the rule block rather than implying tooling that isn't there.

The implementing PR is itself governed by the rule it lands: draft, human merge.

Activity

  1. claude commented on Aug 21, 2026

    @claude
    Contributor

    Claim: PM loop round 21
    Session: session_01RV6yuVCxymHYE16PL9vQkE
    Branch: claude/issue-5149-governed-surface-rule
    Worktree: objectui-issue-5149
    Domain: repo:objectui
    File surface: this repo's AGENTS.md, one rule block (stop on breach; explain in the report)
    Container & model: M, mode:subagent
    Clause-②: no — instruction text, no code behaviour change
    Serial constraints cleared: none — no in-flight card touches AGENTS.md.

    ⚠️ This PR is itself governed by the rule it lands (the card says so): it stays draft, and ⛔ the seat will NOT flip it ready, enqueue it, or arm auto-merge. It awaits a human merge.

    Why now: the absence of this rule text caused a measurable miss today. The dev on #5081 (PR #5464) declined to arm auto-merge because it believed the published skills/ tree was maintainer-merge-only. It is not — this card's ruling scopes the governed surface to AGENTS.md, CLAUDE.md, .claude/** and docs/adr/**, and the published skills/ dir is outside it. The dev erred safe, so nothing broke, but a rule that exists only in an unlanded issue is a rule agents have to guess at.


    Generated by Claude Code

  2. os-support-ai commented on Aug 21, 2026

    @os-support-ai
    Collaborator

    os-dev-report

    {
      "issue": 5149,
      "status": "done",
      "branch": "claude/issue-5149-governed-surface-rule",
      "pr": "https://github.com/objectstack-ai/objectui/pull/5472",
      "premise_still_valid": true,
      "summary": "Landed one rule block in this repo's AGENTS.md: a new '### 受管面(governed surface)' subsection in §9, placed immediately after the merge-flow bullets it qualifies. It carries the 2026-08-18 ruling verbatim/untranslated, the four governed paths (AGENTS.md, CLAUDE.md, .claude/**, docs/adr/**), the hard rule (never flip ready, never enqueue, never arm auto-merge; stays draft awaiting a human merge; the human merge IS the review record, no per-PR approval click), the mixed-diff fork with no proportionality judgment, authoring-stays-open vs landing-is-reserved, and the already-armed recovery note scoped to your own arming (a shared GitHub identity means state you did not set belongs to another actor: ask, do not revert). The .claude/skills/** vs published skills/** boundary is called out as its own warning block with one criterion — does the path start with .claude/ — and names the conservative-direction misjudgment as equally a misjudgment. Audit honesty is stated as a durable mechanism fact: this repo has no CODEOWNERS, no required check, no hook and no audit; objectstack's report-only post-merge audit covers that repo only; and tooling not named in the block does not exist. Compared against objectstack AGENTS.md Prime Directive #14 and followed its shape while copying none of its tooling claims. PR #5472 is draft and stays draft — it is governed by the rule it lands.",
      "tests": "Gate union re-run at final commit a365d3f21 with a clean working tree (git status --porcelain empty). Scope derived from the actual changed paths (AGENTS.md + .changeset/*.md); objectui has no scripts/pm/dispatch-gates.mjs (counter-probed: scripts/ exists and lists 20+ check-*.mjs). `pnpm check:control-bytes` -> '✅ check-control-bytes: OK (scanned 4525 tracked text file(s); skipped 85 binary).' exit 0. `pnpm changeset:check` -> '✅ All workspace packages are in the changeset fixed group. / ✅ privatePackages declared / ✅ No changeset declares a major bump.' exit 0. `node scripts/check-changeset-presence.mjs` -> '✅ No source of a released package changed in this range, so no changeset is owed.' (an empty-frontmatter changeset was added anyway as the repo's explicit publishes-nothing declaration, following .changeset/delete-dead-release-workflow-5405.md). `pnpm docs:check-links` -> 'Links are valid across 13 scan roots.' exit 0. Control-byte self-scan over both changed files: clean; the scan pattern was itself counter-probed — an initial tab probe was INVALID because \\x09 is deliberately outside the class, redone with \\x0b which the pattern does catch. No ablation applies (docs-only, no build artifacts). Honesty note: `pnpm check:skills-paths` passes but its SCAN_ROOT is skills/ only, so it did NOT validate the paths asserted in the new block; those rest on the git ls-files measurements below. No test skipped, disabled or quarantined. Governed-surface measurement at merge-base e912a16f9, every zero counter-probed: AGENTS.md and CLAUDE.md present, one each at repo root; .claude/** present with 8 tracked files (5 hooks, settings.json, launch.json, skills/verify/SKILL.md); docs/adr/** PRESENT with 10 ADRs, so the card's 'if/where it exists' hedge resolves to it-exists and the rule states it flatly with no hedge and no count; published skills/objectui/** present with 29 tracked files; .agents/skills/ tracks only its .gitignore (I corrected an earlier draft that asserted symlinks — a fresh checkout has none). No CODEOWNERS anywhere: `git ls-files | grep -i codeowners` returns zero, counter-probed against .github/** which has 26 tracked files. No pre-existing governance text: repo-wide git grep for human-merge|maintainer-merge|人工合并|人类审核|人工审核|governed surface|受管面 returned zero hits, counter-probed with auto-merge which hits 3 times in AGENTS.md — that zero is the mechanism behind the miss the card cites.",
      "open_questions": [
        {
          "question": "objectstack's 2026-08-18 governed-surface quotation lists `skills/**` among ITS governed paths, but this card scopes objectui's surface to four paths with the published `skills/**` explicitly OUTSIDE. Both repos publish a skills catalog with the same propagate-into-codebases-we-cannot-see property that objectstack's own rule text gives as the reason skills/** is governed there. Deliberate asymmetry, or a transcription gap when the ruling was replicated to this repo?",
          "options": [
            "A — Land as the card specifies (published skills/** NOT governed here) and flag the asymmetry for the maintainer to settle at merge time. This is what I did: the card is explicit, recent, repo-specific, and cites a measured cost from the opposite guess; and the PR's own human merge is a review gate the maintainer passes through before the text takes effect.",
            "B — Stop and escalate as needs_decision before writing anything. Costs the rule another round of not existing, which is the actual measured harm today (agents guessing, one guessing wrong).",
            "C — Extend objectui's surface to include published skills/** to match objectstack. Rejected: that would widen a maintainer ruling on my own authority, in the one file class where doing so is least acceptable."
          ],
          "recommendation": "A, taken. Real business need: the rule's absence has already cost a round, so shipping it beats a second round of silence. Long-term soundness: the four-path surface is exactly what the ruling as transcribed says, and widening it unilaterally in an instruction file would be the workaround, not the fix. Hard-to-get-wrong: the block makes the boundary a single mechanical criterion (does the path start with .claude/) rather than a judgment call, which is the failure mode that produced today's miss. The asymmetry is surfaced prominently in the PR body so the maintainer decides it at the moment of merging, not later."
        },
        {
          "question": "`.agents/skills/.gitignore` is agent-adjacent configuration (it decides which third-party skills are tracked vs restored from skills-lock.json) but is not on the ruling's four-path surface. Governed or not?",
          "options": [
            "A — Leave it off the surface, as the ruling's enumeration implies. What the block does today: it names .agents/skills/ on the NOT-governed side, as an install location rather than protocol text.",
            "B — Add it to the governed surface as agent configuration."
          ],
          "recommendation": "A, taken — anything the ruling does not name is not governed, and inventing scope in an instruction file is exactly the move this card exists to prevent. Raised only because it is a skills-named path adjacent to the confusion the card asked me to eliminate, so leaving it unmentioned would have left a third tree for the next agent to guess about."
        }
      ],
      "out_of_scope_findings": []
    }

    Scope note. One bounded in-place fix inside the same file, named rather than left silent: AGENTS.md line 273 read 「CI 全绿即自行合并,不必等维护者确认」 followed by the gh pr ready + gh pr merge --auto recipe. Landing the rule without touching it would have left a live contradiction inside one instruction file. I added a one-sentence carve-out to that same bullet pointing at the new block. Same file, same defect class, no new verification surface, and the shape is pinned by the sibling declaration — objectstack's AGENTS.md cross-references Prime Directive #14 from its own merge-flow sections the same way. The file surface is unchanged: AGENTS.md plus the changeset.

    ⛔ PR #5472 stays draft. Not flipped ready, not enqueued, no auto-merge armed — it is governed by the rule it lands, and it awaits a human merge.


    Generated by Claude Code


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions