Skip to content

feat(source-control): pr_body_required_sections accepts none (no required sections) - #1142

Merged
kyle-sexton merged 1 commit into
mainfrom
feat/1138-pr-body-sections-none
Jul 23, 2026
Merged

feat(source-control): pr_body_required_sections accepts none (no required sections)#1142
kyle-sexton merged 1 commit into
mainfrom
feat/1138-pr-body-sections-none

Conversation

@kyle-sexton

Copy link
Copy Markdown
Contributor

Closes #1138

Summary

pr_body_required_sections now accepts the literal keyword none — "this repo requires no PR-body sections" as a stated convention, previously unstatable (absence yields the portable default, the opposite of what a deliberately empty-body repo wants). Parallel to the sibling keys trailer_policy and pr_body_attribution: a resolved none means /pull-request create drafts no section scaffold and the §2.4.2.2 pre-create gate requires nothing. The §2.4.2.1 closing-keyword check is independent and unchanged; ad hoc ## Related content from real refs is still never dropped. none participates in per-key layering as a resolved value, not an absence — a layer declaring it overrides a lower layer's list wholesale, while a key unset in every layer still falls through to the portable default (Summary, Test plan).

Surfaces updated: reference/config-resolution.md (value grammar + layering semantics), docs/conventions/pr-body-convention/README.md (owner doc — new "none: no required sections" section with the consumer-evidence rationale), pull-request/reference/create.md (§2.4.1 resolve step, template build, §2.4.2.2 vacuous pass), setup/SKILL.md (check-report rendering none (no required sections), interview offer, config template). source-control 0.19.0 → 0.20.0 + CHANGELOG.

Test plan

  • jq -e validates both edited evals.json files and plugin.json.
  • Both eval files conform to the skill-quality evals.schema.json (required id+prompt, kebab-case name, no extra fields).
  • New model-graded evals cover the resolution contract: pull-request eval 19 (team-layer none → empty scaffold, gate passes vacuously, closing-keyword check still enforced; fixture source-control-required-none.md), eval 20 (none wins the per-key override across all three layers; absence vs none distinguished), setup eval 16 (check report renders resolved none distinctly from unset).
  • typos clean over the touched trees.

Related

🤖 Generated with Claude Code

…uired sections (0.20.0)

The key could express a list or absence (absence yields the portable
default), so a repo whose convention is no PR-body sections could not
state that in config. The literal keyword `none` now resolves to zero
required sections, parallel to trailer_policy / pr_body_attribution:
the create draft emits no section scaffold and the pre-create gate has
nothing to require; the closing-keyword check is independent and
unchanged, and ad hoc Related content from real refs is never dropped.
`none` participates in per-key layering as a resolved value, not an
absence — a layer declaring it overrides a lower layer's list, while a
key unset everywhere still falls through to the portable default.

Documented in reference/config-resolution.md and the pr-body-convention
seam README; setup check renders a resolved `none` distinctly and the
apply interview offers it. New pull-request evals 19-20 and setup eval
16 cover resolution, layering, and reporting.

Closes #1138

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@claude

claude Bot commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Claude encountered an error after 1s —— View job


I'll analyze this and get back to you.

@claude

claude Bot commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Claude encountered an error after 0s —— View job


I'll analyze this and get back to you.

@github-actions

Copy link
Copy Markdown

Warning

Automated review did not complete — this is an infrastructure failure, not a review verdict.

Treat any Claude comment on this PR (including a placeholder like "I'll analyze this and get back to you") as incomplete, not "no findings."

Re-running the job, or pushing a new commit, will retry the review.

@github-actions

Copy link
Copy Markdown

Warning

Automated security review did not complete — this is an infrastructure failure, not a review verdict.

Treat any Claude comment on this PR (including a placeholder like "I'll analyze this and get back to you") as incomplete, not "no findings."

Re-running the job, or pushing a new commit, will retry the review.

@kyle-sexton

Copy link
Copy Markdown
Contributor Author

Pre-merge CI classification

  • 25/25 checks green (hygiene, plugin-gate, changelog-parity-gate, skill-quality-gate, pr-issue-linkage, pr-title, portability-lint, silent-skip-gate, orphaned-fixture-gate, sync gates, zizmor, GitGuardian, security-review/changes all pass).
  • claude-review / claude-security-review hit the known instant infra failure (ci: claude-review + claude-security-review workflows infra-fail instantly (0-1s, cost 0) on every attempt #1122, claude-code-action internal error, 0–1s, rerun-proof) — fail-open by workflow design with warning comments; not a review verdict.
  • Codex review window observed post-green (7-min cooldown + comment/thread sweep): no findings, no review threads.

Merging per the drive-to-merged directive on record for this issue chain (#1138#1141).

@kyle-sexton
kyle-sexton merged commit 9770ad9 into main Jul 23, 2026
25 checks passed
@kyle-sexton
kyle-sexton deleted the feat/1138-pr-body-sections-none branch July 23, 2026 11:47
kyle-sexton added a commit that referenced this pull request Jul 23, 2026
… consensus window (#1144)

Closes #1139

## Summary

`/source-control:setup`'s convention-inference history signal previously
sampled a fixed `git log -50` tail — too small to detect a convention
shift or an informal variant family (live-run evidence in the issue: a
2,122-subject year-scale analysis found a rising ticket-prefix pattern
at 78.8% recent vs 71.9% older with Conventional Commits at 0%,
invisible at n=50). Inference now runs one `git log --since="<window>"
--no-merges --date=short --format='%ad|%s'` pass, excludes auto-subjects
(`Revert `/`fixup!`/`squash!`; merges via `--no-merges`),
bucket-classifies in-context, and reports volume-weighted percentages
with a recent-vs-older recency split — the user picks from the evidence
table; no bucket is silently promoted into config.

Every knob is plugin `userConfig`, never a constant (per the item's
author-stated design principle): `setup_inference_window`
(git-approxidate string, default `1 year`),
`setup_inference_recency_days` (default `90`),
`setup_inference_min_commits` (default `50`). A surviving literal
`${user_config.…}` placeholder applies the manifest default. Keys
declared in `plugin.json`, documented in the README config table.

Generic caveats handled and stated in the report when they apply:
shallow clones (`git rev-parse --is-shallow-repository`) report the
actual covered span; young repos widen to full history, then degrade to
low-confidence below the min-commits threshold; squash-merge-only repos
are flagged as one signal (subjects ARE the PR titles), not two
independently corroborating ones.

source-control 0.20.0 → 0.21.0 + CHANGELOG.

## Test plan

- `jq -e` validates `plugin.json` and `evals.json`.
- New userConfig entries follow the current plugins-reference manifest
schema (type/title/description/default/min; fetched 2026-07-23).
- New setup eval 17 (`inference-uses-consensus-window-not-fixed-sample`)
covers: configurable window with manifest-default fallback, auto-subject
exclusion, bucketed recency-split percentages, evidence-table pick (no
silent promotion). Conforms to the skill-quality evals schema.
- `typos` clean over the touched tree.

## Related

- Issue chain: #1138 (merged, PR #1142) → #1139 (this) → #1140#1141
(source-control convention SSOT series).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
kyle-sexton added a commit that referenced this pull request Jul 23, 2026
…ly-convention spoke split (#1146)

Closes #1140

## Summary

Skill-quality pass over `source-control:setup` per the F4 audit finding.
The audit's MD041/MD013 lint findings were **verified against the repo's
actual markdownlint config first** (per the issue's explicit
instruction): `.markdownlint-cli2.jsonc` disables both MD013 and MD041,
so they do not apply under the repo's own gate — no lint edits made for
them; markdownlint reports clean.

Added a `## Gotchas` surface recording real first-contact failure
patterns from the live audits: omission-never-resets per-key
fallthrough, `none` vs absence as distinct states, resolved-value (not
file-presence) inference gating, nested-directory cwd-relative read
degradation, linked-worktree hooks-dir resolution, `--since`
committer-date vs `%ad` author-date recency skew (review-caught during
#1139), and same-session stale `userConfig` reads.

**Hub-split decision: DONE, not deferred.** #1139's consensus-window
inference had pushed the hub to 512 lines — over the skill-quality
gate's 500-line hard cap — so the split fell out naturally: the `apply`
convention write path (layer selection, non-interactive update
semantics, the 7-step interview, the written-file template, per-layer
verification scripts, failure remediations) moved verbatim to a
progressive-disclosure spoke
`skills/setup/reference/apply-convention.md` (332 lines, one relative
link re-depthed), with a normative pointer + summary in the hub. Hub now
211 lines.

source-control 0.21.0 → 0.22.0 + CHANGELOG.

## Test plan

- `skill-quality:check` (bundled `check-skill.sh`, twenty-check static
gate) on `setup`: **PASS — 0 errors**; all 8 base-ref trigger phrases
preserved; markdownlint clean; no Gotchas WARN; hub 211/500 lines (only
remaining note: advisory soft target 200).
- Spoke content moved verbatim from the hub (diff-inspected); the one
internal link (`config-resolution.md`) re-depthed for the new location.
- `jq -e` validates `plugin.json`.

## Related

- Issue chain: #1138 (PR #1142, merged) → #1139 (PR #1144, merged) →
#1140 (this) → #1141 (source-control convention SSOT series).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
kyle-sexton added a commit that referenced this pull request Jul 23, 2026
…ntion_source (#1149)

Closes #1141

## Summary

Author-directed reopen of #913's recorded "no YAML / no path rename"
decision — the four reopen grounds (author directive, a real consuming
machine hand-syncing three byte-identical regex copies, the ecosystem's
prose-only AGENTS.md pointer standard with no machine format, and the
plugin-audit recurring-concerns memory contradicting the decline) are
recorded in #1141; a comment recording the outcome goes on #913 at
merge.

The team-tracked `.claude/source-control.md` may now declare `##
convention_source`: a **repo-relative flat-scalar YAML file**
(`subject_pattern`, `pr_title_pattern`, optional
`pr_body_required_sections` list or `none`, optional `dialect:`
defaulting `posix-ere`) that enforcement (commit-msg hooks, CI) and
drafting (any agent) consume as one source. Key contract points, all
recorded in the commit-convention seam README:

- **Back-compat absolute:** no pointer → today's markdown-H2 behavior,
zero action for existing consumers.
- **Everything repo-declared:** the path is the consuming repo's call
(no hardcoded doc root; no well-known search list in V1 — recorded
decision with rationale). The `Conventional Commits` keyword and the
pr-title deferral marker work identically on both surfaces.
- **Per-key precedence:** the neutral file is authoritative for keys it
carries; omitted keys fall back to the markdown H2; plugin-only keys
(`trailer_policy`, `pr_body_attribution`) stay `.claude/`-side;
user/local overlay layers unchanged.
- **Enforcement contract unchanged:** POSIX ERE only, unresolved = no
enforcement, team-only policy floor — including the pointer itself (an
overlay cannot redirect the gate). A declared-but-broken pointer
(absolute/backslash/`..` path, missing file) or a non-`posix-ere`
dialect **fails closed** with a diagnostic, never a silent markdown
fallback that could enforce a migration-retired pattern.
- **Incumbent steelman documented:** markdown-H2's
doubles-as-documentation purposes tested against the move (YAML `#`
comments + prose pointer doc); frontmatter-hybrid re-examined and
declined for V1 with rationale.
- **`setup apply`** gains the offer-and-migrate path: repo-chosen path,
YAML write, pointer declaration, and retiring duplicated markdown keys
so both surfaces are never authoritative for the same key. Monorepo
per-directory scoping: out of scope V1, recorded.

`lib/resolve-convention-pattern.sh` extended; the guardrails vendored
copy synced byte-identical via
`scripts/sync-resolve-convention-pattern.sh` (gate:
resolve-convention-pattern-sync), with guardrails 0.12.3 → 0.13.0 +
CHANGELOG per the bump gate. source-control 0.22.0 → 0.23.0 + CHANGELOG.

## Test plan

- `bash lib/resolve-convention-pattern.test.sh`: **44 cases, 0 failed**
— 14 new neutral-SSOT cases: quoted/double-quoted/unquoted YAML values,
CC keyword and deferral marker in YAML, explicit `posix-ere` dialect,
non-ERE dialect → fail closed, missing-file pointer → fail closed with
no stale markdown fallback, absolute/traversal pointer rejection,
omitted-key markdown fallback, YAML-wins-over-unretired-duplicate,
comment/blank inertness, overlay-pointer ignored (team-only floor).
- `scripts/sync-resolve-convention-pattern.sh --check`: guardrails copy
byte-identical.
- `skill-quality:check` on `setup`: PASS, 0 errors.
- `jq -e` validates both manifests and the evals file; new setup eval 18
covers the apply migration path.

## Related

- #913 — the reopened decision (outcome comment lands there on merge).
- Issue chain: #1138 (PR #1142) → #1139 (PR #1144) → #1140 (PR #1146) →
#1141 (this), all merged in order.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
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.

source-control: pr_body_required_sections accepts 'none' (no required sections)

1 participant