feat(source-control): setup inference reads a configurable year-scale consensus window - #1144
Conversation
…onsensus window (0.21.0) Convention inference sampled a fixed git log -50 tail — too small to see a convention shift or an informal variant family (live-run evidence: a 2,122-subject year-scale analysis found ticket-prefix at 78.8% recent vs 71.9% older, Conventional Commits 0%, invisible at n=50). The history signal is now one git log --since="<window>" --no-merges pass with subjects date-stamped for a recency split, auto-subjects (Revert/fixup!/ squash!) excluded, bucket-classified in-context and reported as volume-weighted percentages recent-vs-older — the user picks from the evidence table, nothing is silently promoted into config. Every knob is plugin userConfig, never a constant: setup_inference_window (default 1 year), setup_inference_recency_days (default 90), setup_inference_min_commits (default 50); documented in the README config table. Caveats handled and stated in the report: shallow clones report the actual covered span, young repos widen to full history then degrade to low-confidence, squash-merge-only repos are one signal (subjects ARE the PR titles), not two. New setup eval 17 covers the inference. Closes #1139 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Claude encountered an error after 0s —— View job I'll analyze this and get back to you. |
|
Claude encountered an error after 1s —— View job I'll analyze this and get back to you. |
|
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. |
|
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. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 098c15baf5
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…038) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Claude encountered an error after 0s —— View job I'll analyze this and get back to you. |
|
Claude encountered an error after 1s —— View job I'll analyze this and get back to you. |
…since's clock --since filters the revision walk by committer timestamp while %ad renders the author timestamp, so a rebased or cherry-picked commit could enter the window yet land in the wrong recency bucket and skew the consensus recommendation. Render %cd instead — one clock for both the filter and the split. Codex review finding on PR #1144, classified VALID. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Claude encountered an error after 0s —— View job I'll analyze this and get back to you. |
|
Claude encountered an error after 1s —— View job I'll analyze this and get back to you. |
|
Pre-merge CI classification
Merging per the drive-to-merged directive on record for this issue chain (#1138 → #1141). |
…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>
…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>
Closes #1139
Summary
/source-control:setup's convention-inference history signal previously sampled a fixedgit log -50tail — 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 onegit 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, default1 year),setup_inference_recency_days(default90),setup_inference_min_commits(default50). A surviving literal${user_config.…}placeholder applies the manifest default. Keys declared inplugin.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 -evalidatesplugin.jsonandevals.json.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.typosclean over the touched tree.Related
🤖 Generated with Claude Code