Skip to content

reconcile: two facts on every card, the result and the fix (ACE-127) - #309

Open
sandeep-agami wants to merge 4 commits into
ACE-126-reconcile-diff-cardsfrom
ACE-127-reconcile-result-and-fix
Open

sandeep-agami wants to merge 4 commits into
ACE-126-reconcile-diff-cardsfrom
ACE-127-reconcile-result-and-fix

Conversation

@sandeep-agami

@sandeep-agami sandeep-agami commented Sep 13, 2026

Copy link
Copy Markdown
Collaborator

Spec: ACE-127 (agami-sdlc main, projects/agami-core-extension/specs/reconcile-evidence/ACE-127-result-and-fix.md)

Do not merge without manual review. Stacked on #307 (ACE-126); merge bottom-up: #288 → … → #305#307 → this.

Why

Sandeep: "if the data matches, but query is different - should we show as match but have a tag as different query?" and then: "There are two dimensions - 1/ result of reconciliation - Should we distinguish between Data and SQL Match, Data Match+SQL mismatch, Partial Data Mismatch (missing columns), Data and SQL mismatch, 2/ suggested fix - query fix, semantic model fix, prompt fix examples fix etc." One pill mixed "did the data match" with "can we keep it", the owner tag mixed "who acts" with "what kind of fix", and a query written differently from agami's made a matching row read "matches, unverified" and blocked the keep offer.

What changes

result, two facts read by code on every item

  • data: matches, partly, differs, could_not_compare. From the number diff or the table comparison; partly when rows and values agree on the shared columns and only the column sets differ.
  • query: same, different, not_comparable. From the seven claims, plus the projection: two queries that return different columns are different queries.
  • label, plain words from the pair: match; same answer, different query; same rows, different columns; different answer; same query, different answer; could not run. unchecked counts the checks on your query that could not run and is shown as a tag, not a status. differs_in names the claims that differ.

fix, in order of precedence

fix when
your query the ledger proved a part wrong, or your query returns columns the question did not ask for
the semantic model a measured gap: value list, filter, relationship, metric
the question a doubtful fit (a query that may not answer its question is never the example to teach), or the two queries read the question differently with nothing behind it
the examples your query passed every check, no gap, and agami still wrote a different query; a prompt example is the lever
agami again a failed run, or the same query giving a different answer
nothing both facts match, or a cosmetic difference (ordering, limit)

The ledger. A claim that differs between the two queries is noted (kind different_query), never unresolved: a matching answer with a different query stays match and reaches the keep offer. It is the best test the run can write: two independent formulations vouch for the answer key.

The page. The result label is the pill, colored by the data fact (amber for a match by a different query), with an "n checks not run" tag; the fix sits on the action line and as filter chips; a row of result counts under the status chips; the suggested decision follows the fix (examples → keep where allowed, else change). Older items files without the two fields render as before.

Second commit (0e07e92). A doubtful fit outranks the examples fix: a query that may not answer its question is never the example to teach, however the data fell; the fix is the question. The precedence in the spec is updated to match.

Third commit. The result chips are filters (toggles that narrow the cards) and replace the older status chips when result labels exist; each filter row is labelled Result, Fix, Find; the reset reads "Clear filters"; the examples fix reads "add an example". After Sandeep: "these pill filters dont' seem to be working" and "should there be labels for each row of filters".

Fourth commit (bdf0edc). The third commit's result-chips block read a variable before its declaration and left the page blank on load; fixed, and tests/test_reconcile_pages_load_in_node.py now runs every page's script to the end of its load path under Node with a stub document (skipped where Node is not installed), so a load-time reference error becomes a test failure. That closes the gap the review round named: the page JavaScript had no behavioural test.

Unchanged. The five internal status words keep driving the chat counts, the chunk progress line and the keep gate; the parser is untouched.

Tests

  • New tests/test_reconcile_result_and_fix.py: every result label with its fix over ten records, the sentence clauses, keep on a cosmetic difference, the unchecked count, and the ledger's noted claim. Renderer tests for the two fields' validation, the pills and the fallback. Pins on the ledger rule, the skill's items step and the status table. 369 tests green across the reconcile suites.
  • Full uv run dev.py check on the final commit (bdf0edc): ruff clean, vendored library in sync, 5873 passed, 12 skipped, 1 failed, the failure being tests/test_golden_run.py::test_a_client_that_cannot_be_found_still_fails_as_a_generation, the known local failure on this machine. The Node smoke test ran (Node is installed here).

History note (review round). The gallery's staging folder (.artifact-stage/, generated pages over synthetic data) had been committed into the second commit by mistake, 2,881 lines that do not belong in the repo. Removed from that commit and the branch force-pushed with lease; every other commit is unchanged in content. #310 was replayed on top.

Rebase note (2026-09-13). Replayed onto main at 99e44a8 with every branch below it; content unchanged, force-pushed with lease.

🤖 Generated with Claude Code

sandeep-agami and others added 4 commits September 13, 2026 16:33
Spec: ACE-127

Sandeep: "if the data matches, but query is different - should we show as match but have a tag as
different query?" and "There are two dimensions - 1/ result of reconciliation ... 2/ suggested fix".

`result`, read by code on every report item: data in matches, partly, differs, could_not_compare
(the number diff or the table comparison; partly when rows and values agree on the shared columns
and only the column sets differ); query in same, different, not_comparable (the seven claims, plus
the projection: different columns are a different query); a plain-word label (match; same answer,
different query; same rows, different columns; different answer; same query, different answer; could
not run); unchecked, the checks on your query that could not run, shown as a tag; differs_in.

`fix`, in order of precedence: your query (a part the ledger proved wrong, or extra columns of yours);
the semantic model (a measured gap); the examples (your query passed every check, no gap, and agami
still wrote a different query, so a prompt example is the lever); the question (a doubtful fit, or
read differently with nothing behind it); agami again (a failed run, or the same query giving a
different answer); nothing. Templated change words per fix.

The ledger: a claim that differs is noted (kind different_query), never unresolved, so a matching
answer with a different query stays match and reaches the keep offer; a cosmetic difference does not
block keep. The page: the result label as the pill, colored by the data fact (amber for a match by a
different query), an "n checks not run" tag, the fix on the action line and as filter chips, a row of
result counts; the suggested decision follows the fix. The five internal status words are unchanged.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Spec: ACE-127

A query that may not answer its question is never the example to teach, however the data fell; the
fix is the question. Row 4 of the sample run now reads "same answer, different query" with the fix
"reword the question".

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…is labelled

Spec: ACE-127

Sandeep: "these pill filters dont' seem to be working" and "should there be labels for each row of
filters, they are not self explanatory". The result chips (match; same answer, different query; same
rows, different columns; different answer; same query, different answer; could not run) are toggles
that narrow the cards, like every other chip, and when the items carry result labels they replace the
older status chips as the one result row. Each filter row carries its label: Result, Fix, Find. The
reset reads "Clear filters". The examples fix reads "add an example", the action rather than the noun.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…oad; every page's script now loads under Node in a test

Spec: ACE-127

The result-chips block read `root` before the line that declares it, a temporal dead zone error that
left the page blank. It reaches the element by id now. tests/test_reconcile_pages_load_in_node.py
runs each page's script to the end of its load path under Node with a stub document (skipped where
Node is not installed), so a reference used before it is declared, a missing function or a typo
surfaces as a test failure rather than a blank page.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@sandeep-agami
sandeep-agami force-pushed the ACE-126-reconcile-diff-cards branch from 8a85a94 to 32fcec3 Compare September 13, 2026 23:36
@sandeep-agami
sandeep-agami force-pushed the ACE-127-reconcile-result-and-fix branch from d6f5d9b to 91bb785 Compare September 13, 2026 23:36
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