feat(py): citation corpus, provenance marker, and turn reminders - #308
Draft
jat255 wants to merge 4 commits into
Draft
feat(py): citation corpus, provenance marker, and turn reminders#308jat255 wants to merge 4 commits into
jat255 wants to merge 4 commits into
Conversation
jat255
force-pushed
the
jat255/g9yd-agent-helpers
branch
from
September 7, 2026 17:12
9fa1391 to
cfd20c4
Compare
|
Preview deployed to Connect ( Deployed from commit f2d3745. |
|
Preview deployed to Connect ( Deployed from commit f2d3745. |
jat255
force-pushed
the
jat255/g9yd-agent-helpers
branch
from
September 7, 2026 19:42
cfd20c4 to
e10ca95
Compare
jat255
force-pushed
the
jat255/g9yd-agent-helpers
branch
from
September 7, 2026 19:59
2fbacc6 to
f6f6665
Compare
The four agent helpers that no milestone owned, ahead of the Commons class that assembles them (kata g9yd, under M5). build_citation_corpus() collects the text a citation can be verified against: each measure's search_pool block, each source's dictionary prose and per-table entries, then the context layer's documents. Order is the contract, since matching returns the first entry holding the quote, so prose that is both a dictionary's and a document's keeps the dictionary's label. Python keys its sources, so every dictionary has a name to be labelled with and R's unnamed "data dictionary" fallback has no counterpart here. collect_appended_tags() reads back the tags tool results set, and provenance_aside() renders the marker for the outcomes that show one. The marker names no icon: that URL comes from the served asset bundle, as citation_aside_html already records. The reminders travel as their own content type, so a UI can leave them out. The restored-conversation reminder names Python and run_python where R's names R and run_r; the shared fixture holds the wording once and each package renders it with its own two values. Nothing constructs any of this yet, as planned: that wiring is kata pvrd.
The contract was hand-written in both suites: tags gather only from turns at or after the index, content without a tag is skipped. A per-language copy of a shared behavior drifts, so provenance.json gains a collect_appended_tags section both suites run. The fixture's skip counts the turns present when the exchange began, since from_index is 0-based in Python and 1-based in R. A tag value outside A, B, and C stays deliberately unpinned: Python drops it at collection, R returns it, and derive_provenance_tag ignores anything but A and B either way.
Every other public function in _citations.py was exported; the corpus builder was the one omission. escape_attr gained a docstring when it stopped being private.
turn-reminders.json had no bullet, and the provenance bullet now names collect_appended_tags alongside the truth table.
jat255
force-pushed
the
jat255/g9yd-agent-helpers
branch
from
September 7, 2026 20:05
f6f6665 to
f2d3745
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The four agent helpers that no milestone owned, ahead of the
Commonsclass that assembles them. Tracked as katag9ydunder M5, stacked on #306.build_citation_corpus()collects the text an answer's citations are verified against: each measure'ssearch_poolblock, each source's dictionary prose and per-table entries, then the context layer's documents. The order is part of the contract, because matching returns the first entry holding the quote, so prose that is both a dictionary's and a document's keeps the dictionary's label.collect_appended_tags()reads back the tags tool results set, andprovenance_aside()renders the marker for the outcomes that show one. The marker names no icon: that URL comes from the served asset bundle which arrives with the Python UI, the same reasoncitation_aside_html()already omits one.The reminders travel as their own content type so a UI can leave them out. Python's restored-conversation reminder names Python and
run_pythonwhere R's names R andrun_r, so the shared fixture holds the wording once as a template plus each package's two substitutions rather than two copies of the sentence.One deliberate difference from R: Python keys its data sources, so every dictionary has a name to be labelled with and R's unnamed "data dictionary" fallback has no counterpart here. R's own test for that label stays.
Nothing constructs any of this yet, which is planned. That wiring is kata
pvrd, blocked until the prompt data and the tools land.Python: 1028 tests pass,
ruffandpyreflyclean. R:test-provenance.R,test-citations.R,test-turn-reminder.Randtest-context-layer.Rpass with no failures and no skips.R-side changes
No R source changed. The R suite gains fixture runners and loses the hand-written tests those runners replace, so R behaviour is identical before and after.
test-provenance.Rdrivesprovenance_aside()from a new section ofprovenance.json, which pins which outcomes render a marker and that a rendered one carries its tag's label and body. The icon assertions stayed hand-written and moved into their own test, because the URL comes from this package's own html dependency and the Python renderer emits none until its UI ships one.test-citations.Rloses three hand-written corpus tests in favour of a runner over the newcitation-corpus.json: six cases covering labels and kinds, entry order, thesources:line only multi-source agents see, and precedence when dictionary prose is also a document. The test for an unnamed source's generic label stays hand-written, since Python has no equivalent. Each case builds real measures throughmeasure()and real sources throughdata_source(), so the runner enters through the same front door the agent will.test-turn-reminder.Ris new and is new coverage:turn-reminder.Rhad no tests of its own, only the agent-level assertions intest-commons.R, which are untouched. It pinsclaude_5_turn_reminderverbatim, the model ids that do and do not earn it, andrestored_conversation_turn_reminderagainst the fixture's template rendered with R's values.Blast radius is the test suite only.