Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions .claude/board/entries/2026-11-11-codegraph-recon-2.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# 2026-11-11 — Coverage-aware impact; report-rs #33 recovered from compiler facts

**Status:** MEASURED (probe). `.claude/probes/2026-11-11-codegraph-recon-2/`. Follows
`2026-11-11-codegraph-recon-1` (#2000). Board: EXO-229, EXO-230.

`Codegraph::impact_report` (additive; `impact` unchanged) returns `impact`'s masks plus typed gaps:
external consumers unobserved, targets not extracted or undeclared, excluded regions, unresolved
dispatch, incomplete harvest, stale or unrecorded files, and `.rs` files under a read directory that
`files.tsv` does not list. Missing coverage never enters `Graded.unknown`. A missing symbol carries
its crate's gaps. 14 tests; every guard disable-verified red.

report-rs `81705d9` through Charon (lib, default features, `crate::app` opaque): CRATE `COMPLETE`,
yet 14 of 59 `src/` files unread (`iam.rs`, `main.rs`, `project_plan/*`, …). The store recovers the
first #33 finding: `workbook_delta::WorkbookSource::poll` has no library caller and no path to
`Ledger::ingest`; `Ledger::pull → source_fake::pull` is dynamic and reported UNKNOWN.

Blind arms graded strictly against the EXO-185 key (12 items): source arm 12 correct; store arm
7 correct, 3 partial, 2 unsupported; 0 wrong in both. The store's misses are configuration
(feature-gated `iam`), targets (test callers) and manifest facts (Cargo.toml). n = 1 per arm.

#2000 reproduces from its documented commands: rows equal, `machine-recovered.mmd` byte-identical,
Charon recall column identical.

OPEN: per-configuration stores (features, test targets); recording targets and opaque modules in
the store instead of declaring them.
3 changes: 2 additions & 1 deletion .claude/board/entries/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,11 @@ index row, (3) no duplicate entry id. Checks 1 and 2 are deliberately
opposite directions; the stranding this convention prevents shows up in
exactly one of them, never both.

597 entries, 2026-08-06 .. 2026-11-11.
598 entries, 2026-08-06 .. 2026-11-11.

| date | entry id | finding | file |
|---|---|---|---|
| 2026-11-11 | `codegraph-recon-2` | | [2026-11-11-codegraph-recon-2.md](2026-11-11-codegraph-recon-2.md) |
| 2026-11-11 | `codegraph-recon-1` | | [2026-11-11-codegraph-recon-1.md](2026-11-11-codegraph-recon-1.md) |
| 2026-11-10 | `lab-resolve-borrow-all` | | [2026-11-10-lab-resolve-borrow-all.md](2026-11-10-lab-resolve-borrow-all.md) |
| 2026-11-10 | `int8-direct-packed-b` | | [2026-11-10-int8-direct-packed-b.md](2026-11-10-int8-direct-packed-b.md) |
Expand Down
26 changes: 26 additions & 0 deletions .claude/probes/2026-11-11-codegraph-recon-2/GRADES.tsv
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#version 1
#schema key arm grade note
K1.1 M CORRECT both identities, source_fake.rs:19 and workbook_delta/source.rs:210
K1.1 C PARTIAL both identities CONFIRMED; defining lines UNKNOWN (the store records spans, not struct lines)
K1.2 M CORRECT source_fake.rs:29 impl Source
K1.2 C CORRECT IMPLEMENTS rows; witness source_fake.rs:39 (the pull fn, not the impl line)
K1.3 M CORRECT inherent poll, returns Poll, no Source impl
K1.3 C CORRECT no Source impl for the delta type, ABSENT-IN-SCOPE
K1.4 M CORRECT Ledger::pull calls src.pull (333) then ingest (334); projection.rs:409 passes source_fake
K1.4 C CORRECT ingest edge CONFIRMED at source.rs:334; dyn Source call reported UNKNOWN, not CONFIRMED
K1.5 M CORRECT no src caller of poll; callers in tests/p20 and examples/workbook_sync.rs; lands in Workbook::ingest
K1.5 C PARTIAL poll has 0 callers in the lib scope and no edge to Ledger::ingest; test/example callers not named (targets not extracted, reported as a gap)
K1.6 M CORRECT does not claim poll has no callers at all
K1.6 C CORRECT ABSENT-IN-SCOPE with tests/examples UNOBSERVED; never "no callers"
K2.1 M CORRECT iam.rs:250, behind feature iam (lib.rs:22-23)
K2.1 C UNSUPPORTED iam.rs reported unread, feature off, call UNOBSERVED
K2.2 M CORRECT no authorize_scoped anywhere
K2.2 C CORRECT ABSENT-IN-SCOPE, with the iam build UNOBSERVED
K2.3 M CORRECT gating stated; default build does not compile iam
K2.3 C CORRECT does not claim report-rs never authorizes
K3.1 M CORRECT no dt64-lance dependency (Cargo.toml), no MapLog in any file
K3.1 C PARTIAL no MapLog symbol in scope; the dependency fact is outside the store and not stated; lance-feature build left UNOBSERVED
K3.2 M CORRECT IdentityFrame holds MapTable (frame.rs:55-57), advanced in commit (189-203)
K3.2 C CORRECT MapTable::new frame.rs:69, advance frame.rs:195 in IdentityFrame::commit, called from ingest.rs:264
K3.3 M CORRECT absence stated over every file and Cargo.toml, independent of features
K3.3 C UNSUPPORTED did not frame it as a dependency-scope fact
152 changes: 152 additions & 0 deletions .claude/probes/2026-11-11-codegraph-recon-2/REPORT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
# D-CODEGRAPH-RECON-2: coverage-aware impact, and report-rs #33 from compiler facts

D-CODEGRAPH-RECON-1 (#2000) showed that `Codegraph::impact` returns an empty set for a public
symbol whose callers live in crates the store does not hold. This probe keeps `impact` as it is
and adds `Codegraph::impact_report`, which returns the same masks plus a typed list of what the
answer could not see. It then answers three questions about report-rs PR #33 from a Charon store
and grades the answers against the manual EXO-185 findings, which were held out.

Result: the store recovers the first #33 finding (the SharePoint drive source never reaches
`Ledger::ingest` from library code), explains it correctly, and names every region it could not
see. Both arms made no wrong statement. The source-reading arm was more complete, because the
store sees one build configuration and one target.

## 1. `impact_report` (Gate A)

`crates/lance-graph-codegraph/src/impact_report.rs`. `Codegraph::impact` is unchanged and
`ImpactReport.graded` is exactly its output. Missing coverage is never written into
`Graded.unknown`, which stays "observed functions a dynamic call may reach".

| gap | source of the fact |
|---|---|
| `ExternalConsumersUnobserved` | the symbol or anything that reaches it is `PUBLIC`, and the consumer set is not declared closed; when it is declared closed, every stored crate's coverage is checked |
| `TargetsNotExtracted` / `TargetsUndeclared` | declared per crate (the store does not record targets) |
| `RegionsExcluded` | declared: opaque modules, features left off |
| `UnresolvedDispatch` | `UNRESOLVED_CALL` rows that may reach the symbol |
| `HarvestIncomplete` | residuals file, CRATE status |
| `StaleSource` / `FilesUnrecorded` / `FreshnessUnchecked` | `<crate>.files.tsv` digests against the source root |
| `SourceFilesUnread` | `.rs` files below a directory the extraction read from, absent from `files.tsv` |

A missing symbol in a stored crate carries its crate's target, region and file gaps, because each
is a place it may still be defined. `closed_in_scope()` is true only for a found symbol with no
gap, and it claims nothing about code outside the scope. `Coverage::no_known_gap()` alone is not
treated as closure: test 2 asserts it is true while the report is not closed.

`tests/impact_coverage.rs`, 14 tests: one per case in the brief, three found while running
Gate B (excluded regions, target gaps of a missing symbol, unread files), and three from review
(a private symbol behind a public caller, a closed consumer set checks every stored crate, a
missing symbol's harvest gap). Every guard was disabled
and its test went red: external consumers, missing targets, undeclared targets, dispatch fire,
dispatch silence, stale source, owner stored, observed consumers, closed symbol, harvest,
missing-symbol scope gaps, excluded regions, unread files (fire and silence), missing-symbol file
gaps, public frontier, closed consumer set, missing-symbol harvest.

## 2. The report-rs store (Gate B)

Inputs: report-rs `81705d9` (#33 head). Charon `c69e231`, nightly-2026-09-17, library target,
default features, `--opaque 'crate::app'` (the full crate ran out of memory at 15 GB). ruff_charon
from ruff `9752608`.

| step | time (µs, reported, not gates) | result |
|---|---|---|
| charon | 42,192,655 | exit 0 |
| ruff_charon import | 25,202,579 | 29,542 harvested, 1 residual (`REFERENCE_NOT_NAMED view::Scope::only`) |
| six cg_query runs (cold open each) | 435,149 | |

The CRATE row says `COMPLETE`, yet 14 of 59 files under `src/` were never read: `app.rs` and
`app/plan_routes.rs` (opaque), `iam.rs`, `login.rs`, `flow_scratch.rs`, `project_plan/*` (features
off), `main.rs` (binary target), `workbook_delta/dt64/p21_lane_socket_lab.rs`. That is what
`SourceFilesUnread` reports, from `files.tsv` alone. Nothing was inserted into the store by hand.

Raw query output is in `store-output/`.

### Q1: the two `WorkbookSource` types

```mermaid
flowchart LR
load["Projection::load_v1"] -->|"CONFIRMED projection.rs:409"| new["source_fake::WorkbookSource::new"]
load -->|"CONFIRMED projection.rs:408"| lpull["Ledger::pull"]
into["source_graph::pull_into"] -->|"CONFIRMED source_graph.rs:357"| lpull
lpull -->|"UNKNOWN dyn Source, source.rs:333"| fpull["source_fake impl Source::pull"]
fpull -.->|IMPLEMENTS| spull["Source::pull"]
lpull -->|"CONFIRMED source.rs:334"| ingest["Ledger::ingest"]
poll["workbook_delta WorkbookSource::poll"] -.-|"0 callers in lib; tests, examples, app, main unread"| gap(("UNOBSERVED"))
```

- Confirmed: two identities, `report_rs::source_fake::WorkbookSource` and
`report_rs::workbook_delta::source::WorkbookSource<T>`; only the first implements `Source`.
`Ledger::pull` calls `Ledger::ingest` (source.rs:334). `Projection::load_v1` builds the
`source_fake` source (projection.rs:409) and passes it to `Ledger::pull`.
- Possible / unknown: `Ledger::pull` reaches `source_fake::pull` only through `&mut dyn Source`
(source.rs:333). The compiler does not name that target, so the store reports UNKNOWN, not an edge.
- Absent in scope: `poll` has no caller in the library target with default features, and no path
from it reaches `Ledger::ingest`. Gaps: tests and examples not extracted, `crate::app` opaque,
`main.rs` unread, the symbol is public.
- Falsifier: one `src/` call of `WorkbookSource::poll` whose result reaches `Ledger::ingest`
(for example an `impl Source` for the delta type) turns this into a confirmed edge on re-import.

### Q2: authorization

`lance_graph_rbac` symbols are missing with `owner_stored: false`; `report_rs::iam::*` is missing
with `SourceFilesUnread` naming `src/iam.rs`. The store therefore cannot say whether report-rs
authorizes: the module that would do it was not compiled. Falsifier: re-extract with
`--features iam` and query `iam` callers.

### Q3: map persistence

No `lance_graph_dt64_lance` symbol in scope. `IdentityFrame::commit` calls
`lance_graph_dt64::dr::MapTable::advance` (frame.rs:195), CONFIRMED. Whether report-rs depends on
`lance-graph-dt64-lance` is a manifest fact the store does not hold; the store answer is
"absent in scope". Falsifier: a `MapLog` call in any compiled file.

## 3. Graded comparison (Gate D)

Two blind arms on the same model, the same questions (`questions.md`) and the same revision.
Arm M read source only. Arm C queried the store with `cg_query` and read source only at lines the
store printed. Grading against `answer-key.md`, strict: a materially false statement is WRONG even
with a coverage disclaimer. Full grades in `GRADES.tsv`; answers in `answers/`.

| | correct | partial | unsupported | wrong | tool calls | elapsed s | tokens |
|---|---|---|---|---|---|---|---|
| M (source) | 12 | 0 | 0 | 0 | 13 | 71.0 | 456,784 |
| C (store) | 7 | 3 | 2 | 0 | 8 | 59.8 | 456,309 |

The token counts are dominated by the shared session context both arms load, so they do not
separate the arms. n = 1 per arm; this is an observation, not a ranking.

Where the store was weaker, and why:

- **Build configuration.** Source text includes `#[cfg(feature = "iam")]` code; the store holds
one configuration. K2.1 (the `authorize_memberships` call) is visible only to arm M.
- **Targets.** The store holds the library target, so the test and example callers of `poll`
(K1.5) are unobserved. Arm C reported the gap; it did not name the callers.
- **Manifest facts.** "report-rs does not depend on dt64-lance" (K3.1, K3.3) comes from
Cargo.toml, which the store does not read.
- **Definition lines.** The store records function spans, not struct lines (K1.1).

Where the store was stronger: arm C's `Ledger::pull → source_fake::pull` is reported UNKNOWN
(dynamic dispatch) instead of asserted, and every absence it states carries its scope. Arm M's
text search is feature-blind in both directions: it saw the `iam` call, and it would equally have
reported a cfg-dead call as live.

Acceptance (brief): the store independently recovers the first #33 missing-integration finding,
explains it correctly, and reports what it cannot prove. Met.

## 4. #2000 checks

- The PR description, REPORT.md §4 and `recon.py --self-test` all give 15 tests; the self-test
passes.
- CI at the head (`90fc5a7`) and the merge (`317c4ff`) is green on every workflow.
- Reproduction from the documented commands, in a fresh worktree at `317c4ff` with sibling ndarray
at `fd3d2e7`: rows per crate equal REPORT.md's table (represented + 3), `machine-recovered.mmd`
is byte-identical, and the Charon column of `score.tsv` is identical (61 HIT, 26 MISS,
32 UNOBSERVED). The rust-analyzer column was not re-run.

## 5. Open

- Feature and target matrices: one store per configuration, merged, would close K1.5 and K2.1.
Charon needs `crate::app` opaque at 15 GB.
- `RegionsExcluded` and `Targets` are declared by the caller. The extractor could record both in
the store (they are its own arguments), which would turn them into store facts.
- `SourceFilesUnread` scans the top directory of each recorded path; files recorded at the source
root trigger no scan.
45 changes: 45 additions & 0 deletions .claude/probes/2026-11-11-codegraph-recon-2/answer-key.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# Held-out answer key — D-CODEGRAPH-RECON-2 Gate B/D

Source: EXO-185 manual findings (2026-11-10/11), re-checked by hand against
report-rs `81705d9` (PR #33 head). This file is NOT an input to any store and
is never shown to an arm before grading.

## Q1 — the two `WorkbookSource` types (EXO-185 loose end A)

K1.1 Two distinct identities:
- `report_rs::source_fake::WorkbookSource` (src/source_fake.rs:19)
- `report_rs::workbook_delta::source::WorkbookSource<T: DriveTransport>` (src/workbook_delta/source.rs:210)
K1.2 Only `source_fake::WorkbookSource` implements `report_rs::source::Source`
(src/source_fake.rs:29); its `pull` builds an `IngestBatch` (source_fake.rs:39, :61).
K1.3 `workbook_delta::source::WorkbookSource` has an inherent `poll`
(workbook_delta/source.rs:292) returning `Poll` (`Unchanged` | `Changed(VerifiedSnapshot)`);
it has no `Source` impl and builds no `IngestBatch`.
K1.4 `Ledger::pull(&mut dyn Source, _)` (src/source.rs:331) calls `Source::pull` (dynamic)
and `Ledger::ingest` (source.rs:334). The lib's only `Ledger::pull` caller with a
workbook source is `projection.rs:409`, passing `source_fake::WorkbookSource::new`.
K1.5 Missing integration: no lib (`src/`) code calls `workbook_delta::...::WorkbookSource::poll`.
Its only caller is `tests/p20_workbook_delta.rs:304`, which feeds `Workbook::ingest`
(tests/p20:308), not the ledger. So the real SharePoint puller never reaches
`Ledger::ingest`. Absence scope: all of `src/` and `tests/` at 81705d9, default features.
K1.6 Correct framing: the edge `poll → IngestBatch/Ledger::ingest` is ABSENT within the
lib target; test callers exist (p20). Claiming "poll has no callers at all" is FALSE.

## Q2 — reader scope (EXO-185 loose end B, ledger item 3)

K2.1 report-rs calls `lance_graph_rbac::authorize::authorize_memberships` only from
`src/iam.rs:250`, and `iam` is behind feature `iam` (src/lib.rs:22-23; Cargo.toml:107),
OFF by default.
K2.2 No call to `authorize_scoped` anywhere in report-rs `src/` or `tests/` at 81705d9.
K2.3 Correct framing for a default-features extraction: the `iam` module is UNOBSERVED
(not compiled), so "report-rs never authorizes" is FALSE; "no `authorize_scoped` call"
needs either the iam feature extracted or a source scope check.

## Q3 — MapLog / value persistence (EXO-185 loose end C, ledger 5a/5b)

K3.1 report-rs does not depend on `lance-graph-dt64-lance` (Cargo.toml: only
`lance-graph-dt64`, line 46); no `MapLog` use in src/ or tests/.
K3.2 DR identity lives in memory: `IdentityFrame` holds a `MapTable`
(src/workbook_delta/frame.rs:56), advanced in `IdentityFrame::commit`
(frame.rs:189, `self.table.advance(` at :195).
K3.3 Correct framing: the store cannot see crates report-rs does not depend on; "no
MapLog call" is a dependency-scope fact (Cargo.toml), not a call-graph absence.
Loading
Loading