Skip to content

Prohibit agent-originated product behavior in code review - #201

Open
mikeangstadt wants to merge 2 commits into
chore/forbid-blind-scope-dropfrom
guard/no-agent-originated-product-behavior
Open

mikeangstadt wants to merge 2 commits into
chore/forbid-blind-scope-dropfrom
guard/no-agent-originated-product-behavior

Conversation

@mikeangstadt

Copy link
Copy Markdown
Collaborator

Summary

Adds "Agent-originated product behavior — never ship it" to the four reviewer prompts that operate on symphony-alpha:

  • plugins/code/agents/code-review-guidelines.md
  • plugins/code/agents/code-reviewer.md
  • plugins/code-review/prompts/github-review.md
  • .claude/agents/pr-reviewer.md

The rule. An agent must not originate user-visible product behavior. Every rule deciding what a user sees — shown, withheld, refused, defaulted, thresholded, ranked, reworded — must cite a human source: ticket AC, PRD, or an operator instruction. If it cannot, that is the finding, reported at High.

Why it needs a reviewer rule and not just a repo doc. This class ships looking correct. The implementer reasons their way to a defensible position, writes a persuasive comment, and pins it with tests. Every downstream reader then treats it as intended. Nothing in the existing severity table catches it, because the code is well-formed, well-tested, and internally consistent — it is simply behavior nobody asked for.

The review heuristic is the prose itself. A behavior a human specified CITES that human. A behavior an agent invented ARGUES FOR ITSELF. Length correlates with invention. A thorough suite around an uncited product rule is evidence of the defect, not of diligence.

Sits beside "Blind scope drop — never an option" in code-review-guidelines.md and follows its shape: named prohibition, concrete tells, and a measured instance.

The measured instance

symphony-alpha ISS-10354, 2026-09-15. A Sessions LOC/$ card refused to publish its ratio whenever a coverage probe returned anything but Complete. No human specified that rule. It shipped with a paragraph of justification, a canonical state-to-copy map, a feature flag, and a nine-case suite pinning each refusal.

In production it rendered LOC / $ — on a row that simultaneously displayed Total estimated cost $37,927 and PRs shipped 362 — both of its own operands, present and rendering. One refused state (MigrationPending, "still being rebuilt") described a rebuild that no job performs, so the blackout was permanent rather than transient.

The code's own comment admitted what it was: "the coverage verdict is a refusal to publish a number that exists." It was caught by a human looking at a screenshot, after code-side analysis of the coverage state machine missed it twice.

Companion change in symphony-alpha: closedloop-ai/symphony-alpha#7356, which deletes the refusal and adds the matching sections to AGENTS.md, .claude/review/soul.md and .claude/logical/discipline-core.md.

Test plan

Prose-only change to four reviewer prompt files; no code paths, no runtime behavior. Verified each file received the section exactly once and that the insert is idempotent (re-running skips a file that already carries it).

🤖 Generated with Claude Code

mikeangstadt and others added 2 commits September 15, 2026 16:28
Adds "Agent-originated product behavior — never ship it" to the four
reviewer prompts that operate on symphony-alpha.

The rule: an agent must not originate user-visible behavior. Refusing to
show something is product behavior, as is a default, a threshold, a
fallback, an ordering, or an empty-state sentence. Every such rule must
cite a human source; if it cannot, that is the finding, reported at High.

The review heuristic is the prose itself. A behavior a human specified
cites that human. A behavior an agent invented argues for itself — and
length correlates with invention. A thorough test suite around an
uncited product rule is evidence of the defect, not of diligence,
because it makes the invention permanent and makes the next reader
assume intent.

Includes the measured instance that motivated it: a Sessions LOC/$ card
that refused to publish a ratio while both of its operands rendered
beside it on the same row, behind a rule no human specified, carrying a
justification paragraph, a canonical reason map, a feature flag and a
nine-case suite.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The Plugin Version Bump check requires any plugin whose files changed to
carry a version bump. This change edits reviewer prompts in both
plugins/code and plugins/code-review.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@shafty023

Copy link
Copy Markdown
Collaborator

Beginning a code-review. Please allow time for me to finish before merging the PR


**Never refuse a derivation you have the inputs for.** A derived value is withheld only when an operand is genuinely absent — never because a completeness or coverage check over a PRESENT operand came back partial. Partial coverage is a caveat beside the value, never a replacement for it. Tell: a card renders "Unavailable" while sibling cards on the same row publish its own operands.

**How to review for it.** For each user-visible decision in the diff, name the human source. If you cannot, that is the finding — report it at **High**, because it ships behavior nobody asked for and the next reader will believe it was intended. Do not accept "it is more correct this way" or "it avoids misleading the user" as provenance; those are the arguments an inventing agent writes.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: This GitHub-only prompt is read by the orchestrator, not the reviewers that inspect the patch. Both local and GitHub review workers receive shared_prompt.txt, while local mode skips this file entirely, so the new rule never runs where it needs to catch anything.

Put the reviewer-facing provenance rule in tools/prompts/shared_prompt.txt (keep GitHub-only output instructions here if needed).


**A test does not confer provenance.** Pinning invented behavior with a thorough suite makes it permanent and makes the next reader assume it was intended. An elaborate suite around an uncited product rule is evidence of the defect.

**Never refuse a derivation you have the inputs for.** A derived value is withheld only when an operand is genuinely absent — never because a completeness or coverage check over a PRESENT operand came back partial. Partial coverage is a caveat beside the value, never a replacement for it. Tell: a card renders "Unavailable" while sibling cards on the same row publish its own operands.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: This turns the ISS-10354 LOC/$ decision into the same kind of uncited global product rule we’re trying to catch. That ruling says this card must publish its value despite partial coverage; it does not say every derived metric with present inputs must always be shown.

A different product requirement may deliberately withhold a value below a specified confidence or coverage threshold, and this will tell reviewers to reject it anyway. Keep the provenance check, but scope the partial-coverage guidance to cases where the ticket/PRD/operator decision says to publish the value.

"name": "code-review",
"description": "Code review plugin",
"version": "1.5.5",
"version": "1.5.6",

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: The version bumps need their generated changelog entries too. .githooks/pre-push rejects plugin changes without a root or plugin-local changelog diff, but the current CI version check only verifies the manifest bump, so this passes CI and then fails the repository’s release guardrail.

Run /update-documentation and include the generated entries for both code-review and code.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants