Skip to content

feat(mine): enrich decisions with GitHub PR text (kb mine --prs, ADR slice 2)#36

Merged
v0ropaev merged 1 commit into
masterfrom
feat/pr-mining
Jul 10, 2026
Merged

feat(mine): enrich decisions with GitHub PR text (kb mine --prs, ADR slice 2)#36
v0ropaev merged 1 commit into
masterfrom
feat/pr-mining

Conversation

@v0ropaev

Copy link
Copy Markdown
Owner

What

The network slice of ADR mining: kb mine --prs enriches decisions mined from squash-merged commits (subject ending in (#NN)) with the pull request's title/body via the new kb.git.forge module — PRProvider protocol + GitHubPRProvider (stdlib urllib; GITHUB_TOKEN/GH_TOKEN optional, anonymous works for public repos; --repo-slug overrides the origin-derived slug).

Strictly opt-in and the only networked step in the toolchain — without --prs, behavior is byte-identical to slice 1.

The identity story (the design core)

PR text is mutable after merge — without an identity pin, editing a PR and re-mining with --force would silently swap the payload under an unchanged artifact_id (the silent-collision class this repo fixed twice). Per the sink-registry precedent, a digest of the capped PR text is folded into framework_versions (identity-bearing): an edited PR yields a new artifact id and the manifest re-points. The enriched prompt runs under its own system prompt and pins its own prompt_version="2+pr1" (the describe repo-prompt precedent); plain prompts and plain ids stay byte-identical.

A failed fetch (404 / network / rate limit) degrades softly to the byte-identical plain artifact and is counted per run (pr_enriched/pr_fetch_failed in the CLI summary) — a failure is a property of the run, not the knowledge. Exactly two identities exist per (sha, model): plain and enriched(digest). PR text stays context + payload fact — never grounding (D5: the decision remains grounded on the commit's changed spans).

Gates (stay fifteen)

ADR-mining gate grows six tests: enrichment identity, floor under enrichment (REAL kept / FAKE dropped), post-merge-edit → new id, fetch-failure degradation, no-PR byte-compat, slug/subject/provider parsing incl. fail-soft HTTP paths (monkeypatched urllib — no network in CI).

Verified live before this PR

GITHUB_TOKEN=$(gh auth token) kb mine . --prs --force --max-commits 6 on the dogfood DB: 2 decisions enriched with real PR bodies (titles match gh pr view), digests identity-bearing (prompt_version=2+pr1), the 2000-char body cap exercised on a real long PR body, confidence 0.833 (Laplace), 0 fetch failures.

Local: ruff clean, mypy --strict clean, pytest -q → 122 passed, 1 skipped.

…slice 2)

New kb.git.forge module - the ONLY networked step in the toolchain,
strictly opt-in: PRText/PRProvider protocol + GitHubPRProvider (stdlib
urllib against api.github.com; GITHUB_TOKEN/GH_TOKEN optional,
anonymous works for public repos), origin_slug (https/ssh forms) and
pr_number_from_subject (squash '(#NN)' anchor; the Revert case yields
the revert's own PR).

A mined commit whose subject carries (#NN) is enriched: PR title/body
feed the prompt (own system prompt - the plain one says 'ONLY the
commit message') and land in the payload (capped). PR text is context
and a payload fact - never grounding. Because PR text is MUTABLE after
merge, a digest of the capped text is folded into framework_versions
(identity-bearing, the sink-registry precedent): an edited PR yields a
NEW artifact id, never a silent payload swap. The enriched prompt pins
its own prompt_version '2+pr1' (the describe repo-prompt precedent);
plain prompts and plain artifact ids stay byte-identical.

A failed fetch (404/network/rate limit) degrades softly to the
byte-identical plain artifact and is counted per run (pr_enriched /
pr_fetch_failed in the CLI summary) - a failure is a property of the
RUN, not of the knowledge; exactly two identities exist per
(sha, model): plain and enriched(digest). Merge commits stay skipped
(squash flow is fully covered; grounding a classic merge on its
first-parent diff is an open question). docs-only commits pay neither
LLM nor network.

ADR-mining gate grows six tests (enrichment identity, floor under
enrichment, post-merge-edit -> new id, fetch-failure degradation,
no-PR byte-compat, slug/subject/provider parsing incl. fail-soft HTTP
paths). Headline HARD gates stay fifteen. Verified live against real
GitHub + LLM: 2 decisions enriched, digests identity-bearing, body cap
exercised, 0 fetch failures.
@v0ropaev v0ropaev merged commit ce2ebb9 into master Jul 10, 2026
4 checks passed
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.

1 participant