4.8 KiB
id, title, parent, depends_on, created, claimed_by, claimed_at, blocked
| id | title | parent | depends_on | created | claimed_by | claimed_at | blocked | |
|---|---|---|---|---|---|---|---|---|
| T01.i | Record the failure-reads-as-an-absence chain, and clear two leftovers | T01 |
|
2026-09-21 | null | null | false |
Description
Three leftovers from T01.f. The first is the substantial one; the other two are mechanical.
1. Open a bug_ leaf for a read that answers empty where it should fail
This repo has closed the "failure disguised as an absence" family repeatedly and it has two open bug_ leaves on it already (bug_a-lost-inbox-watch-is-never-retried, bug_an-empty-inbox-list-can-mean-a-failure). This is another member, and it spans three layers. Write ONE leaf in .project/concepts/app-contract/, naming the chain rather than any single symptom.
The upstream fact that makes it a divergence and not a heritage - VERIFIED, do not re-derive it, and do NOT go read nextgraph-rs for it. An anchored SPARQL query on a repo the verifier does not know REJECTS. The deciding line is engine/verifier/src/request_processor.rs:269: let repo = self.repos.get(repo_id).ok_or(NgError::RepoNotFound)?; inside resolve_target_for_sparql. It crosses into JS as a REJECTED PROMISE carrying the string "RepoNotFound" (sdk/js/lib-wasm/src/lib.rs:403 for nodejs, :606 for browser). Upstream's observable partition is "in self.repos" vs "not in self.repos": "does not exist" and "exists but my session does not know it" are INDISTINGUISHABLE, while "known but unsynced" collides with "genuinely empty". No read-capability check exists anywhere on that path - resolve_target_for_sparql reads only nuri.target.
The three layers of our chain, each VERIFIED by reading the code in this working copy:
fetchReadCap(packages/polyfill/src/emulated-verifier/public-store.ts:190) collapses three unrelated situations into onefalse: the emulation is not in force (:196), the network could not be asked (:223), and the document exposes no cap (:225). Its own comment at:220states the collapse out loud. The function BELOW it,downloadReadCap, deliberately distinguishes resolving from rejecting and documents why - so the distinction exists and is destroyed one line later. Worse, NO caller reads the boolean at all:ensureRepoOpen:208,docs.sparqlQuery:155,branch-registers.ts:316andfetchReadCaps:277all call it as a bare statement. The information is not merely flattened, it is unrecoverable.- The read then proceeds on a document that was never opened.
useShapeQueryanswers a SUCCESS holding zero objects.
What the target says the answer should be. useShapeQuery's return type is modelled on TanStack Query's useQuery, which distinguishes purely by whether the query function REJECTS: a rejection gives isError with the error, a resolution gives isSuccess with whatever data, empty included. That maps exactly onto upstream's RepoNotFound. So "the document is not reachable" must surface as isError, and isSuccess with zero objects must mean "it is there and holds nothing".
Also record, because it is the same family and currently unowned: useShapeQuery never opens the documents named in scope.graphs, so an application that names an unopened document gets an empty success with no error. The ensureReposOpen barrier was removed from that path by T01.d. A fix for it was written during T01.f and REVERTED on instruction, because it was justified by a misdiagnosis (see the parent's digest); the defect itself is real and stands.
Severity is yours to argue in the leaf, from the two existing bug leaves' bar. State what an application observes, not what the code does.
Explicitly OUT OF SCOPE - do not implement a fix. Changing fetchReadCap's return type to name the three cases, or making a read fail where it currently answers empty, is a DESIGN CHANGE the owner has not arbitrated. This task RECORDS the defect. It does not repair it.
2. Remove ensureReposOpen, now dead
T01.f removed its last caller. Verify that claim with a grep before deleting - if a caller survives, say so and leave it. ensureRepoOpen (singular) is NOT dead and must stay.
3. The example's typecheck
examples/notebook/tsconfig.json fails typecheck. T01.f reports this as pre-existing and verified as such. The owner has asked for the example to be repaired. Make it typecheck, without weakening the config - if the only way through is to loosen a compiler option, stop and report instead.
Hard gate: bun test -> 0 fail; bunx tsc --noEmit -p packages/polyfill/tsconfig.json -> exit 0; bunx tsc --noEmit -p packages/polyfill/e2e/tsconfig.json -> exit 0; the example's own typecheck -> exit 0; python3 ~/.claude/skills/concept/lint.py -> 0 ERROR. Anti-cheat: no any, no @ts-ignore, no as unknown as, no deleted or skipped test, no weakened assertion, no loosened compiler option.