Repository navigation
fix: order same-second human feedback rows newest first in the Python store - #1458
Merged
jayscambler merged 1 commit intoOct 23, 2026
Conversation
…newest
SQLiteHumanFeedbackStoreMixin.get_human_feedback and get_calibration_examples
order by `created_at DESC` with no tiebreak, and human_feedback.created_at
defaults to datetime('now'), which has one-second resolution
(migrations/006_human_feedback.sql:8, and the same default in
storage/bootstrap_schema.py). Rows written in the same second share one sort
key and SQLite returns them in insert order, so the newest rows of a
same-second burst come last, and once the burst reaches the LIMIT they are cut
off: a caller asking for the newest rows gets the oldest ones.
With 12 rows inserted in one second on main:
get_human_feedback(limit=10) -> ids 1..10, not 12..3
get_calibration_examples(limit=5) -> ids 1..5, not 12..8
#1360 fixed the same two queries in the TypeScript store and recorded that the
Python side had no counterpart, but it has both queries with the same bug.
This adds the same `id DESC` tiebreak. id is the AUTOINCREMENT rowid, so it is
monotonic in insert order.
The regression tests pin every row's created_at to one value after inserting,
so they reproduce a same-second burst without depending on timing. Both fail
on main and pass with the fix.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
jayscambler
approved these changes
Oct 23, 2026
jayscambler
left a comment
Contributor
There was a problem hiding this comment.
Reviewed exact head cc9c9ba, including both parameterized queries, schema/bootstrap compatibility, calibration callers and deterministic regression tests. The id DESC tiebreak matches newest-first semantics for tied timestamps, preserves scenario/calibration filters, and changes no dependency, workflow, API or schema. Independent validation: 130 tests passed across human feedback, MCP agent tasks, rubric calibration/drift, SQLite store and bootstrap; full Ruff passed; mypy passed for all 950 source files. GitHub dependency comparison against main reports zero added dependencies. Code review approved; merge remains subject to all required GitHub Actions checks, including dependency-security.
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.
Summary
get_human_feedbackandget_calibration_examplesinautocontext/src/autocontext/storage/sqlite_store_human_feedback.pynow order bycreated_at DESC, id DESCinstead ofcreated_at DESCalone.ORDER BY created_at DESC LIMIT ?and the same one-secondcreated_atdefault (autocontext/migrations/006_human_feedback.sql:8, and the pip bootstrap schema instorage/bootstrap_schema.py).Reproduction on
main: 12 rows inserted throughinsert_human_feedbackin one second, all sharing onecreated_at:With the tiebreak:
SQLite returns the tied rows in insert order, so the newest rows of a same-second burst come last, and once the burst reaches the
LIMITthey are cut off: a caller asking for the most recent rows gets the oldest ones. In Python that affects:limit=5) passed toevaluate_outputandrun_improvement_loop(MCP tools inmcp/agent_task_tools.pyandmcp/knowledge_tools.py) and to live rubric calibration inexecution/agent_task_completion.pyget_feedback(the MCPautocontext_get_feedbacktool), and the lessons thatexport_agent_task_skillcopies into an exported skill package (limit=10)idis the AUTOINCREMENT rowid, so it is monotonic in insert order and breaks the tie the wayDESCalready intended.Surfaces Touched
Verification
cd autocontext && uv run ruff check src tests: cleancd autocontext && uv run mypy src: no issues in 950 source filescd autocontext && uv run pytest: two new regression tests intests/test_human_feedback.py. Onmainthey fail withassert [1, 2, 3, 4, 5, 6, ...] == [12, 11, 10, 9, 8, 7, ...]andassert [1, 2, 3, 4, 5] == [8, 7, 6, 5, 4]; with the fix they pass. The tests pin every row'screated_atto one value after inserting, so they reproduce a same-second burst without depending on timing. The storage, MCP and calibration test files also pass on Python 3.11, the CI version (227 passed, 1 skipped). Full suite with-m "not live"on Python 3.12: 11,339 passed, two more than onmain(the new tests). The same 166 tests fail onmainand on this branch in my sandboxed environment, mostly withIsolationUnavailableError: local child isolation is unavailable; none touch human feedback.cd ts && npm run lint: not applicable, no TypeScript changescd ts && npm test: not applicable, no TypeScript changesuv run python ../scripts/check_markdown_links.py: passedDocs And Release Impact
CHANGELOG.md(Unreleased, Fixed)Notes
created_atmillisecond precision would make ties rarer without removing them, so the tiebreak is the fix either way. The migration is left alone.🤖 Generated with Claude Code