Repository navigation
fix(delivery): one repository spelled two ways is one repository, across sessions too - #6450
Conversation
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
| @@ -9756,6 +9756,12 @@ def query_delivery(self, *, kind: str = "pr", runtime: str | None = None, | |||
| ``runtime`` filters server-side on the session's ``agent_type``, | |||
There was a problem hiding this comment.
The blueprint's AttributionPersistence component documents "de-duplicated per repository name" but does not specify that deduplication is case-insensitive, matching GitHub's case-insensitive repository name handling. The code implements case-insensitive folding of repository names across sessions in the query_delivery method, which is not documented in the blueprint.
✅ Drift Bot (ClawMetry): no drift detectedDrift Bot analyzed the changed files against this project's blueprints and requirements and found no drift. |
_fold_repo_case folds spellings within a session; the live tab still listed ClawMetry/clawmetry-pro beside clawmetry/clawmetry-pro, because the two spellings came from two different sessions and the read query grouped on the exact text. GitHub treats an owner and a name case-insensitively, so that is one repository shown as two. query_delivery now folds on a case-insensitive key and shows the spelling the node's own sessions used most, ties falling to the lexicographically smaller spelling so the render is deterministic. The key lowercases only the field holding a repository name (ref on a repo row, repo elsewhere): a branch name and a file path are case-sensitive, and folding those would claim work on a branch that does not exist. The pull-request title/state/URL join is matched case-insensitively too, or a session that typed another case than the local checkout gets a row with no title. Measured on the live node's 256 sessions by running both queries over the same rows: repository rows 208 -> 207, the pair becoming one row with 3 sessions; pull-request, branch, commit and file rows byte-identical; attributed money unchanged at $5408.0144. Extraction is untouched, so RULES_VERSION stays 9 and nothing needs refiling. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
bfc5a9d to
8b70ec3
Compare
|
| @@ -9756,6 +9756,12 @@ def query_delivery(self, *, kind: str = "pr", runtime: str | None = None, | |||
| ``runtime`` filters server-side on the session's ``agent_type``, | |||
There was a problem hiding this comment.
The blueprint's AttributionPersistence component specifies "de-duplicated per repository name" but the code implements case-insensitive deduplication to match GitHub's case-insensitive repository name handling. The blueprint should document that deduplication is case-insensitive, matching the repository owner and name case-insensitivity in GitHub.
Drift Bot asked the AttributionPersistence component to say that the roll-up de-duplicates case-insensitively. The blueprint now says so, including that a branch name and a file path keep their case, which is the half of the rule the code is careful about. drift-bot is an external commit status with no re-request route, so an empty commit is how it re-reads. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
✅ Drift Bot (ClawMetry): no drift detectedDrift Bot analyzed the changed files against this project's blueprints and requirements and found no drift. |
|
Release coordination from the Asimov session: 0.12.925 is published and verified. Mobile correction #6452 is now rebasing onto your merged 5f552ea and will require fresh full CI before merge. I have a separate Asimov correction [RELEASE] changelog prepared and can carry #6450 too once #6452 is green; no release branch pushed yet. Please coordinate release timing here if you are already preparing a delivery release, so we avoid duplicate package releases and repeated CI rebases. Our cloud pin/policy/renderer will ship together after a verified corrected wheel; RP1 cloud rollout remains first. |
) FLYWHEEL gains two Ruthless-verify bullets, both paid for this round: - a waiter that swallows its errors cannot succeed: a urllib poller ate a CERTIFICATE_VERIFY_FAILED for an hour and reported a timeout while the wheel had been on PyPI for 50 minutes; - a fold that runs per item leaves the cross-item case, which is #6450 itself. Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Why
#6436 folded two spellings of one repository into one row, and that fold runs inside a session. The live node then listed
ClawMetry/clawmetry-probesideclawmetry/clawmetry-pro: the two spellings arrived from two different sessions, and nothing folded them once they had become rows, because the read query grouped on the exact text. GitHub treats an owner and a name case-insensitively, so that is one repository presented as two.The same case sensitivity sat on the join that fetches a pull request's title, state and URL from the local repository scan, so a session that typed one case while the checkout reported another got a row with no title and no state: a pull request nobody can identify.
Found by auditing the live node after 0.12.924 shipped, which is the sixth time in this effort that reading the live tab after a fix found the next defect.
What
local_store.query_deliveryfolds rows on a case-insensitive key and displays the spelling the node's own sessions used most. A tie falls to the lexicographically smaller spelling rather than to row order, so the same rows always render the same name.attribution._fold_repo_casealready applies within a session, lifted to the only scope that can see across sessions.refon a repository row,repoon every other kind. A branch name and a file path are case-sensitive in git and on disk, and folding those would merge two different branches and claim work on a branch that does not exist.Verified
Against the live node's own 256 sessions, by running the old and the new query over the same rows:
Attributed money is unchanged to the cent, because a repository's name was never what the cost split was keyed on.
3 tests added (146 in the file). 2 are red against the released 0.12.924 wheel, checked by running them against the wheel's own module:
test_two_sessions_spelling_one_repository_differently_are_one_row(3 rows, not 1)test_a_pull_request_finds_its_title_despite_a_different_case(title'')test_a_branch_keeps_its_own_casepasses both ways on purpose: that is the half a fold can quietly break.285 passed / 1 skipped over the delivery, local-store, store-invariant, query-contract, local-query and snapshot-slice suites.
Extraction semantics are untouched, so
RULES_VERSIONstays at 9 and no session needs refiling.Limits
The spelling on display is the most-sighted one rather than the one GitHub would return, because nothing here asks GitHub. Where two spellings are sighted by the same number of sessions the lexicographically smaller one renders, which is deterministic but not necessarily the one its owner uses. The fold applies to the read, so stored rows keep the spelling each session saw, which is what keeps the evidence column matching the session it came from.
Product record: https://factory.8090.ai/project/b415065f-ab2f-4f53-8864-0c009fd098cb/requirements/eedac1ad-764f-4f9c-bb00-f51c8d47618d
🤖 Generated with Claude Code