You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat(mine): enrich decisions with GitHub PR text (kb mine --prs, ADR slice 2) (#36)
New kb.git.forge module - the ONLY networked step in the toolchain,
strictly opt-in: PRProvider protocol + GitHubPRProvider (stdlib urllib,
GITHUB_TOKEN/GH_TOKEN optional), origin_slug and
pr_number_from_subject (squash '(#NN)' anchor).
PR text feeds the prompt (own system prompt) and the payload (capped) -
context and fact, never grounding. PR text is MUTABLE after merge, so
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
prompt_version '2+pr1'; plain prompts and plain ids stay byte-
identical. A failed fetch degrades to the byte-identical plain
artifact, counted per run. Merge commits stay skipped.
ADR-mining gate grows six tests; headline HARD gates stay fifteen.
Verified live against real GitHub + LLM before merge.
multi-branch dedup, mutable branch pointers exercise; eval Tiers 2/3 (build when the artifacts
295
301
they score exist; stub the Tier-3 question schema now); GC; SCIP/scip-python upgrade.
296
302
@@ -418,12 +424,12 @@ freshness(current|stale@sha)`, with a deterministic tie-break for reproducible e
418
424
|`kb.introspect`| Eval-only runtime oracle: runs a FastAPI app in a network-blocked sandbox and emits `app.openapi()` for the Tier-1 API gate. Never on the index path. | subprocess sandbox, fastapi |
419
425
|`kb.embed`| Replaceable embedding adapters + snapshot population for `search_knowledge`. Torch isolated behind the `embed` extra and a lazy import. | sentence-transformers (default), OpenAI (optional), pgvector |
420
426
|`kb.rag`| Frozen pgvector RAG-over-source baseline — the "other arm" of the knowledge-vs-RAG A/B (no provenance/grounding). | deterministic line-window chunker, pgvector |
|`kb.daemon`| Orchestration + CLI: index a repo @ SHA (full or incremental), run extractors in order, write snapshot, host MCP; `kb watch` polls a local branch ref and indexes new first-parent commits incrementally (`branch_ref` cursor, per-commit crash-safe advance). | typer |
426
-
| `kb.extract.semantic` | **Shipped:** `kb describe` — LLM-grounded NL descriptions of routes/entities/modules, **per-package architecture overviews** (a package grounded on its own + direct-child modules' spans; the overview synthesizes the import graph + public surface + member-module summaries as context, claims code-grounded), **process-path labels** (one per materialized `process_path`, grounded on every span along the path, confidence < 1.0), **event-handler descriptions**, **and the whole-repo overview** (one `desc:repo` per snapshot, grounded on the bounded top-level surface via `queries.repo_target`, synthesizing package summaries + cross-package imports + artifact counts as context), each claim validated against the target's spans by a deterministic sub-property gate (`grounding.validate_claims`); separate key-gated pass, never on `index`. **`kb mine`** — ADR-candidate mining over local first-parent history: one `decision` per mined commit, grounded on the commit's changed spans (role `changed`), message verbatim in the payload, same claim floor. *Deferred:* PR-description mining. | thin LLM adapter (`kb.llm`); `PathEngine` + YAML sink registry live in `kb.extract.deterministic.paths` |
432
+
| `kb.extract.semantic` | **Shipped:** `kb describe` — LLM-grounded NL descriptions of routes/entities/modules, **per-package architecture overviews** (a package grounded on its own + direct-child modules' spans; the overview synthesizes the import graph + public surface + member-module summaries as context, claims code-grounded), **process-path labels** (one per materialized `process_path`, grounded on every span along the path, confidence < 1.0), **event-handler descriptions**, **and the whole-repo overview** (one `desc:repo` per snapshot, grounded on the bounded top-level surface via `queries.repo_target`, synthesizing package summaries + cross-package imports + artifact counts as context), each claim validated against the target's spans by a deterministic sub-property gate (`grounding.validate_claims`); separate key-gated pass, never on `index`. **`kb mine`** — ADR-candidate mining over local first-parent history: one `decision` per mined commit, grounded on the commit's changed spans (role `changed`), message verbatim in the payload, same claim floor; `--prs` enriches squash-merged commits with PR title/body (digest identity-bearing in `framework_versions`; enriched prompt pinned by its own `prompt_version`). | thin LLM adapter (`kb.llm`); `PathEngine` + YAML sink registry live in `kb.extract.deterministic.paths` |
427
433
428
434
---
429
435
@@ -511,9 +517,10 @@ Review fact-checked these against current (2026) sources. Caveats are first-clas
Copy file name to clipboardExpand all lines: README.md
+7-5Lines changed: 7 additions & 5 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -94,12 +94,12 @@ flowchart LR
94
94
-**A frozen RAG-over-source baseline** and the **Tier-3 knowledge-vs-RAG recall gate** — the honest A/B that backs the "knowledge > RAG" thesis.
95
95
-**LLM-grounded descriptions** — an optional, key-gated `kb describe` pass has an LLM write NL summaries for routes, entities, **event handlers**, modules (per file), **packages** (a per-package architecture overview that synthesizes the import graph + public surface + member-module summaries, grounded on the package's own and its direct submodules' spans), **business-process paths** (each materialized `process_path` chain gets an LLM-written label grounded on every span along the path, with a confidence that honestly stays < 1.0), and **the repo as a whole** (one whole-repo overview per snapshot, grounded on the bounded top-level surface and synthesizing the package overviews beneath it); every claim is validated against the target's own spans by a deterministic sub-property gate, so ungrounded claims are *dropped* (the anti-hallucination invariant, with a model in the loop). Stored as `extraction_method = "llm_grounded"`, grounded on code spans.
96
96
-**Incremental re-index** — `kb index --parent <sha>` reuses unchanged files' spans from the parent snapshot and parses only the diff; extraction stays full, so the result is identical to a full re-index (a HARD gate proves it). Auto-detects the parent; falls back to full when none is indexed.
97
-
-**ADR-candidate mining** — an optional, key-gated `kb mine` pass walks local first-parent git history and has an LLM extract the *decision* a commit records (the "why" that code alone cannot show). The provenance bridge: each `decision` artifact is grounded on the spans its source commit **changed** — prose-born knowledge still points at exact code spans; the commit message is stored verbatim as a fact (immutable, pinned by the sha), and every claim passes the same deterministic span-validation floor (fabricated claims dropped; a commit with no surviving claim stores nothing). Local commits only; PR-description mining is a future slice.
97
+
-**ADR-candidate mining** — an optional, key-gated `kb mine` pass walks local first-parent git history and has an LLM extract the *decision* a commit records (the "why" that code alone cannot show). The provenance bridge: each `decision` artifact is grounded on the spans its source commit **changed** — prose-born knowledge still points at exact code spans; the commit message is stored verbatim as a fact (immutable, pinned by the sha), and every claim passes the same deterministic span-validation floor (fabricated claims dropped; a commit with no surviving claim stores nothing). With **`--prs`** (strictly opt-in — the only networked step in the toolchain), a squash-merged commit's GitHub PR title/body enrich the prompt and the payload; PR text stays context, never grounding, and a digest of it is folded into the artifact's identity, so a PR edited after merge yields a *new* artifact instead of a silent payload swap.
98
98
-**Fifteen HARD CI eval gates** (see [Development](#development)).
99
99
100
100
-**A nightly LLM-judged A/B** (optional, key-gated, **non-gating**) — an answerer LLM answers each question from knowbase's grounded context vs a RAG-over-source context, and a judge LLM scores **answer accuracy** (against hand-written gold) + **hallucination**. Tracked metrics on top of recall; it never blocks CI.
101
101
102
-
**Not done yet** (and deliberately not faked): PR-description mining (the network slice of ADR mining) and languages beyond Python. See the [Roadmap](#roadmap).
102
+
**Not done yet** (and deliberately not faked): languages beyond Python. See the [Roadmap](#roadmap).
`kb mine` walks the local first-parent history from the latest indexed commit (`--sha` to start elsewhere, `--max-commits` to bound the LLM spend) and has an LLM extract the decision each commit records from its message plus its changed code. Each stored `decision` artifact is **grounded on the spans the commit changed** — the same ≥ 1-span invariant as everything else — with the commit message kept verbatim in the payload as a fact. Claims are span-validated (fabricated claims dropped; nothing survives → nothing stored); merge commits are skipped (PR mining is a future slice), docs-only commits never pay an LLM call, and re-running skips already-mined commits (`--force` to re-mine). Requires the commits to be indexed first (`kb index` / `kb watch`).
179
+
`kb mine` walks the local first-parent history from the latest indexed commit (`--sha` to start elsewhere, `--max-commits` to bound the LLM spend) and has an LLM extract the decision each commit records from its message plus its changed code. Each stored `decision` artifact is **grounded on the spans the commit changed** — the same ≥ 1-span invariant as everything else — with the commit message kept verbatim in the payload as a fact. Claims are span-validated (fabricated claims dropped; nothing survives → nothing stored); merge commits are skipped (squash-merge flow is fully covered; grounding a classic merge on its first-parent diff is an open question), docs-only commits never pay an LLM call, and re-running skips already-mined commits (`--force` to re-mine). Requires the commits to be indexed first (`kb index` / `kb watch`).
180
+
181
+
Add `--prs` to enrich decisions with GitHub PR titles/bodies (`GITHUB_TOKEN=... kb mine <repo> --prs`) — strictly opt-in, the only networked step in the toolchain (anonymous works for public repos at 60 req/h; `--repo-slug owner/name` overrides the origin-derived slug). A digest of the fetched PR text is identity-bearing, and a failed fetch degrades to plain mining with a per-run counter.
12.**Semantic grounding floor** — the LLM-grounded describer's claims are validated against the artifact's own spans by a deterministic sub-property gate; an adversarial fabricated claim is *dropped*, never stored, on every describe path (artifacts incl. event handlers, modules, packages, process paths, and the whole-repo overview — whose grounding is provably bounded: a grandchild module never grounds it). Run on a stub LLM, so it gates without an API key.
281
283
13.**Incremental re-index equivalence** — an incremental re-index (reuse unchanged files' spans from the parent, parse only the diff) yields the *identical*`{logical_key: artifact_id}` snapshot as a full re-index of the same tree, and the parse is provably skipped for unchanged files (counter assertions); a missing/unindexed parent falls back to full.
282
284
14.**Tier-1 process-paths oracle** — materialized business-process paths match a hand-labeled oracle (2-hop cross-file chain, 0-hop direct-sink handler, event-handler entrypoint); the flagship artifact is grounded across **three files**; a reachable call cycle cannot hang the BFS; the fixture's own `.kb/sinks.yaml` proves the override chain; a no-sink route yields no artifact; depth caps are honored.
283
-
15.**ADR-mining floor** — mined `decision` artifacts are grounded on the spans their source commit changed (role `changed`, provenance limited to the touched files); an adversarial fabricated claim is *dropped*; a commit whose changed code backs no claim stores nothing; a docs-only commit never calls the LLM; merges are skipped; re-mining is idempotent and never re-bills stored decisions (run on a stub LLM, so it gates without an API key).
285
+
15.**ADR-mining floor** — mined `decision` artifacts are grounded on the spans their source commit changed (role `changed`, provenance limited to the touched files); an adversarial fabricated claim is *dropped*; a commit whose changed code backs no claim stores nothing; a docs-only commit never calls the LLM; merges are skipped; re-mining is idempotent and never re-bills stored decisions. PR enrichment is covered too: the PR-text digest is identity-bearing (an edited PR yields a new id, never a silent swap), a failed fetch degrades to the byte-identical plain artifact, and commits without a PR reference stay byte-compatible (run on stub LLM/PR providers, so it gates without keys or network).
284
286
285
287
The identity rules in `kb.ids` (and `kb.structural`) are **LOCKED**: changing one is a breaking change, gated behind a `NORMALIZATION_VERSION` / `extractor_version` bump so existing digests are invalidated rather than silently colliding.
286
288
@@ -310,7 +312,7 @@ Next milestones:
310
312
-[x]**LLM-grounded semantic layer** — model-backed artifacts that still carry ≥ 1 span (`extraction_method = "llm_grounded"`): `kb describe` writes span-validated descriptions for routes, entities, event handlers, modules, per-package architecture overviews, and a whole-repo overview. *(shipped)*
311
313
-[x]**Incremental re-index on git push** — `kb index --incremental`/`--parent` reuses unchanged files' spans from the parent snapshot (extraction stays full; equivalence is gated), and `kb watch` polls a local branch ref, indexing each new first-parent commit incrementally with a `branch_ref` cursor (`--max-catchup` guard, `--once` for cron/CI). *(shipped)*
312
314
-[x]**ADR mining — slice 1 (local commit history)** — `kb mine` walks first-parent history and stores span-grounded `decision` candidates: each grounded on the spans its commit changed, message verbatim as a fact, claims under the deterministic span-validation floor. *(shipped)*
313
-
-[]**PR-description mining** — the network slice of ADR mining (PR titles/bodies mapped onto merge commits).
315
+
-[x]**PR-description mining** — `kb mine --prs` (strictly opt-in, the only networked step) enriches decisions with GitHub PR titles/bodies for squash-merged commits; the PR-text digest is identity-bearing, so post-merge PR edits can never silently swap a payload. *(shipped)*
314
316
-[x]**Grounded business-process extraction** — `process_path` artifacts (entrypoint → call chain → sink-registry match, multi-file grounding) plus LLM labeling via `kb describe` (a span-validated NL label per path, grounded on the path's own spans, confidence honestly < 1.0). *(shipped)*
0 commit comments