Assemble chunked results, and put the documented commands under test - #36
Merged
Conversation
A result split across chunks came back as chunk zero, correctly flagged as truncated but incomplete. The flag was honest; the shortfall was still the failure people would hit first on real data. The Statement Execution contract pairs next_chunk_index with next_chunk_internal_link, documented as a workspace-relative path to be treated as opaque. Genie returns that response verbatim, so the link was already arriving and being discarded. Following it completes the result. Every way of failing to follow it still reports truncated: no link, a link that is not a workspace path, a chunk the caller may not read, or the MaxResultRows cap. A partial result is never reported as complete, which is the property that mattered before this change and still does. The link is server-supplied and the bearer token rides on every workspace request, so an absolute or protocol-relative link is refused rather than followed. It is not logged, since the case worth logging is the one where an attacker chose it.
Three things the first cut of the chunk walk got wrong or left open. A chunk that points at itself looped forever. The row cap was no backstop: a self-pointing chunk carrying no rows never grows toward it. Same failure ListAllAgentsAsync already guards with its repeated-page-token check, and now guarded the same way. Removing the guard makes the new test hang rather than fail, which is how it was confirmed. Link validation moved from the shape of the string to the resolved host. `//evil.example.com/x` looks like a path and resolves to another host -- verified, not assumed -- and no amount of prefix-checking is provably free of the next such quirk. Resolving against the workspace and comparing scheme, host and port is one mechanism instead of two heuristics, and it cannot be talked around. The documented commands now have a test. Every fenced `lakespeak ...` in the markdown is parsed against the real System.CommandLine tree, so a flag that stops existing fails the build. Program.CreateRootCommand exists to make that tree reachable from a test. The README's "89 tests" is gone rather than corrected. The real number was 175 and nobody noticed it drift, which is the argument against putting a number in prose at all.
This was referenced Aug 5, 2026
This was referenced Aug 5, 2026
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.
Two correctness gaps and one class of defect that nothing was catching.
Chunked results are assembled
A result split across chunks came back as chunk zero. It was correctly flagged as truncated — that
much was honest — but the rows were missing, and an incomplete export is the failure a first real
user meets on real data rather than a demo table.
The Genie API has no endpoint taking a chunk index. What it does have is the Statement Execution
response returned verbatim, which pairs
next_chunk_indexwithnext_chunk_internal_link—documented as an opaque path to join with the workspace host. That link was already arriving on
every chunked result and being dropped during deserialization. Following it completes the result.
The alternative — Genie's
downloadsendpoint pair — is a second workflow with its own polling andexpiry, and its response is chunked the same way, so it completes nothing on its own. It also needs
a
download_id_signaturethatdocs/planning/genie-api-surface.mddid not record; that omission iscorrected here. Reasoning in
ADR 0004.
Every way of failing to complete a result still reports truncation — no link beside the index, a
link resolving off-workspace, a chunk the caller may not read, a repeated link, or the row cap. The
property that mattered before this change is unchanged and is now enforced across five exits
instead of one.
Two defects found while reviewing the first cut
MaxResultRowswas no backstop, because aself-pointing chunk carrying no rows never grows toward it. Guarded the way
ListAllAgentsAsyncalready guards its repeated page token. Removing the guard makes the new test hang rather than
fail — that is how it was confirmed, not by reading it.
//evil.example.com/xlooks like apath and resolves to another host, which would have sent the bearer token there. Verified by
probe, not assumed. Validation now resolves the link against the workspace and compares scheme,
host and port — one mechanism that cannot be talked around, replacing two heuristics that could.
The documented commands are under test
Every fenced
lakespeak …invocation in the repository's markdown is now parsed against the realSystem.CommandLinetree. A documented command, subcommand or flag that stops existing fails thebuild and names the file it appears in.
Program.CreateRootCommandexists to make that treereachable from a test;
Mainis otherwise unchanged.This has a concrete cause.
README.mdclaimed 89 tests; a real run gives 175. The numberdrifted through several releases because prose has no owner and no compiler. It is deleted rather
than corrected, for the same reason.
Verification
dotnet format --verify-no-changesclean;dotnet restore --locked-modesucceeds.loop-guard test hangs without the guard.
Not verified live. Whether a caller may read the remaining chunks of a statement Genie executed
on their behalf is a permission question no documentation settles. If the answer is no, behaviour
is exactly what it was before this change — the first chunk, flagged.
compatibility.md,limitations.md,ROADMAP.mdand the ADR all record this as untested rather than implyingotherwise.