Context
packages/loopover-miner/lib/contribution-profile.ts (#6795, the ContributionProfile schema) defines ContributionSignalSource as one of four values:
export type ContributionSignalSource =
"labels" | "contributing_md" | "pr_template" | "agent_docs";
with the design comment explicitly noting: "#6794 found the primary source differs per repo — some state rules only in agent docs, some only in labels." CONTRIBUTION_SIGNAL_SOURCES (the exported runtime vocabulary) freezes the same four values.
packages/loopover-miner/lib/contribution-profile-extract.ts (#6796, the extractor that actually populates a ContributionProfile) only ever fetches two of the four: repo labels (fetchRepoLabels, source "labels") and CONTRIBUTING.md/.github/CONTRIBUTING.md (fetchContributing, source "contributing_md"). It never fetches an AI-agent-facing doc (AGENTS.md, CLAUDE.md) and the extractor never emits a "agent_docs" provenance entry — despite the schema being explicitly designed around that source existing and #6794's own research (docs/ams-contribution-signal-inventory.md) motivating it.
AGENTS.md/CLAUDE.md are full contributor-instruction documents (the same size/nature class as CONTRIBUTING.md, not a short signpost), so the existing extractPrBody/signpost-size heuristic (CONTRIBUTING_SIGNPOST_MAX_BYTES) is directly reusable without inventing a new sizing rule — unlike a PR template (typically short by design), which is why this issue is scoped to agent_docs only, not pr_template.
Requirements
⚠️ Required pattern. Mirror fetchContributing's exact shape (probe a fixed list of repo-root paths via the GitHub contents API, decode with the existing decodeContents, return the first hit or null) for a new fetchAgentDocs that probes AGENTS.md then CLAUDE.md at the repo root, in that order.
- Add
fetchAgentDocs(base, target, headers, fetchImpl, sleepFn): Promise<string | null> that probes AGENTS.md then CLAUDE.md (repo root only — do not add .github/-prefixed variants; neither of these files follows CONTRIBUTING.md's .github/ convention in real repos) using the same getJson/decodeContents helpers fetchContributing already uses.
extractContributionProfile must call fetchAgentDocs alongside the existing fetchContributing call.
- Precedence rule (exact, not left to interpretation):
CONTRIBUTING.md stays authoritative when it yields a non-absent prBody rule (unchanged behavior — zero regression risk for every repo that already has a real CONTRIBUTING.md). Only when extractPrBody(contributing) resolves to { confidence: "absent" } (no CONTRIBUTING.md at all) does the agent-doc candidate get evaluated, through the exact same extractPrBody logic (same CONTRIBUTING_SIGNPOST_MAX_BYTES floor, same LINKED_ISSUE_TERMS match), with its resulting provenance source tagged "agent_docs" instead of "contributing_md".
- Do not add a new field to
ContributionProfile — the result still lands in the existing prBody: ContributionSignalRule<ContributionPrBodyRequirements> slot, exactly as CONTRIBUTING.md-derived results already do; only the provenance source differs.
Deliverables
Test Coverage Requirements
packages/loopover-miner/** is not Codecov-gated (only src/** is), but npm run test:ci must stay green with full branch coverage on the new logic in test/unit/miner-contribution-profile-cache.test.ts or a new/existing extract-focused test file — cover: (1) CONTRIBUTING.md present and non-absent (agent docs never fetched or ignored), (2) no CONTRIBUTING.md but AGENTS.md present and large enough (provenance tagged agent_docs), (3) no CONTRIBUTING.md, AGENTS.md missing but CLAUDE.md present, (4) neither CONTRIBUTING.md nor any agent doc present (stays absent), and (5) an agent doc present but below the signpost-size floor (stays unknown, matching extractPrBody's existing signpost branch).
Expected Outcome
A repo whose contribution rules live only in AGENTS.md/CLAUDE.md (no CONTRIBUTING.md) now produces a real, provenance-tagged prBody signal instead of the schema's own agent_docs source sitting permanently unused — the exact gap #6794's own research flagged as a real-world pattern.
Links & Resources
Context
packages/loopover-miner/lib/contribution-profile.ts(#6795, theContributionProfileschema) definesContributionSignalSourceas one of four values:with the design comment explicitly noting: "#6794 found the primary source differs per repo — some state rules only in agent docs, some only in labels."
CONTRIBUTION_SIGNAL_SOURCES(the exported runtime vocabulary) freezes the same four values.packages/loopover-miner/lib/contribution-profile-extract.ts(#6796, the extractor that actually populates aContributionProfile) only ever fetches two of the four: repo labels (fetchRepoLabels, source"labels") andCONTRIBUTING.md/.github/CONTRIBUTING.md(fetchContributing, source"contributing_md"). It never fetches an AI-agent-facing doc (AGENTS.md,CLAUDE.md) and the extractor never emits a"agent_docs"provenance entry — despite the schema being explicitly designed around that source existing and #6794's own research (docs/ams-contribution-signal-inventory.md) motivating it.AGENTS.md/CLAUDE.mdare full contributor-instruction documents (the same size/nature class asCONTRIBUTING.md, not a short signpost), so the existingextractPrBody/signpost-size heuristic (CONTRIBUTING_SIGNPOST_MAX_BYTES) is directly reusable without inventing a new sizing rule — unlike a PR template (typically short by design), which is why this issue is scoped toagent_docsonly, notpr_template.Requirements
fetchAgentDocs(base, target, headers, fetchImpl, sleepFn): Promise<string | null>that probesAGENTS.mdthenCLAUDE.md(repo root only — do not add.github/-prefixed variants; neither of these files follows CONTRIBUTING.md's.github/convention in real repos) using the samegetJson/decodeContentshelpersfetchContributingalready uses.extractContributionProfilemust callfetchAgentDocsalongside the existingfetchContributingcall.CONTRIBUTING.mdstays authoritative when it yields a non-absentprBodyrule (unchanged behavior — zero regression risk for every repo that already has a realCONTRIBUTING.md). Only whenextractPrBody(contributing)resolves to{ confidence: "absent" }(noCONTRIBUTING.mdat all) does the agent-doc candidate get evaluated, through the exact sameextractPrBodylogic (sameCONTRIBUTING_SIGNPOST_MAX_BYTESfloor, sameLINKED_ISSUE_TERMSmatch), with its resulting provenancesourcetagged"agent_docs"instead of"contributing_md".ContributionProfile— the result still lands in the existingprBody: ContributionSignalRule<ContributionPrBodyRequirements>slot, exactly asCONTRIBUTING.md-derived results already do; only the provenancesourcediffers.Deliverables
fetchAgentDocsadded tocontribution-profile-extract.ts, mirroringfetchContributing's structure.extractContributionProfilewired to fall back to the agent-docs source per the precedence rule above.extractPrBody(or a thin wrapper) tags provenancesource: "agent_docs"for an agent-doc-derived result, matchingCONTRIBUTION_SIGNAL_SOURCES's existing vocabulary.Test Coverage Requirements
packages/loopover-miner/**is not Codecov-gated (onlysrc/**is), butnpm run test:cimust stay green with full branch coverage on the new logic intest/unit/miner-contribution-profile-cache.test.tsor a new/existing extract-focused test file — cover: (1)CONTRIBUTING.mdpresent and non-absent (agent docs never fetched or ignored), (2) noCONTRIBUTING.mdbutAGENTS.mdpresent and large enough (provenance taggedagent_docs), (3) noCONTRIBUTING.md,AGENTS.mdmissing butCLAUDE.mdpresent, (4) neitherCONTRIBUTING.mdnor any agent doc present (staysabsent), and (5) an agent doc present but below the signpost-size floor (staysunknown, matchingextractPrBody's existing signpost branch).Expected Outcome
A repo whose contribution rules live only in
AGENTS.md/CLAUDE.md(noCONTRIBUTING.md) now produces a real, provenance-taggedprBodysignal instead of the schema's ownagent_docssource sitting permanently unused — the exact gap #6794's own research flagged as a real-world pattern.Links & Resources
packages/loopover-miner/lib/contribution-profile-extract.ts(the file to change —fetchContributing,extractPrBody,extractContributionProfile)packages/loopover-miner/lib/contribution-profile.ts(ContributionSignalSource,CONTRIBUTION_SIGNAL_SOURCES— the schema this closes the gap against)agent_docs), AMS contribution-profile: design the ContributionProfile schema and caching shape #6795 (schema), AMS contribution-profile: implement generic label/docs/agent-file extraction #6796 (original extractor issue)