docs(design): page-preserving structure tree and reasoning-based retrieval#123
Merged
Conversation
Add contexts/design/mind/navigation.md defining how QuantMind builds a page-preserving, independently versioned TreeKnowledge from a source-first paper and how a reasoning agent navigates it. Bakes in two requirements: a single provider-agnostic model-resolution seam (multi-model) and a hybrid mode that seeds agentic navigation from library per-node semantic hits. Reconciles issue #95 with the post-#120 source-first Paper Flow V1 model (the navigation tree is a new derived artifact, not a revived PaperTree), and resolves the prior rag-vs-mind ownership tension: rag hosts only a stateless document-local draft helper, while flows builds the canonical tree and mind owns library-backed agentic navigation. Cross-links the existing library and rag PageIndex boundary sections and adds the Mind row to the global design index. Refs #122, #95, #71. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…seam Revise the navigation design to close the review blockers on PR #123: - Add a PaperNavigationArtifact envelope (new PaperArtifactKind) with source_revision_id, producer config hash, content hash, chunk-set lineage, and a stable content-derived id, persisted through the paper artifact tables instead of generic knowledge_items. Reuses TreeKnowledge/TreeNode as payload; no second tree schema. - Make the model emit only a private draft; code owns node ids, links, content, and citations, and runs a full integrity gate (acyclic, single reachable root, bidirectional parent/child, unique sibling positions, citation-in-source, child-span-in-parent). Title sampling is a quality signal, not the gate. - Constrain Citation.page (>= 1) and end_page (>= page, no end-without-start, within source page count). - Give navigation an explicit page_resolver and rename to get_node_content / add get_children; single-pass is one model call; whole-tree serialization is bounded by a structure token budget, not depth alone. - Resolve the mind/flows contradiction: move the shared run wrapper + model seam below flows (quantmind.mind.runtime or quantmind.runtime); flows depends down. - Rephase so P0 build+persist and P1 navigation are truly vectorless; embeddings arrive only in P2 with hybrid. - Hybrid seeds are validated ArtifactLocators (tree_id-constrained single-tree, full (artifact_id, node_id) for corpus), never bare node ids. - Drop the bespoke provider-resolution wrapper: rely on the Agents SDK litellm/ routing and define a capability contract + provider test matrix. - Add an Acceptance and Evaluation section (fixtures, citation accuracy, evidence recall, cost/latency, pure/hybrid/vector comparison). Refs #122, #95, #71. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Independent no-context review found the v2 design multiplied entities. Cuts: - Drop the shared runtime module / flows._runner move. mind.navigation calls agents.Runner.run directly; the flows<->mind dependency is never inverted. - Flatten PaperNavigationArtifact into a flat PaperNavigationTree sibling of PaperChunkSet/PaperGlobalSummary (root_node_id + nodes as own fields, no nested TreeKnowledge), removing the latent dual-identity (as_of/source/uuid) problem. from_draft mints ids + runs the integrity gate. - Drop Citation.end_page: a page range is already expressible as multiple Citation(page=n) entries on TreeNode.citations. No canonical base-type change. - Drop the rag stateless draft-helper allowance from Ownership and both edited boundary docs; rag stays deterministic chunking + BM25 with no LLM. - Fold get_node_content into the existing LocalKnowledgeLibrary.resolve() (extended to the new kind); drop the separate page_resolver and get_children. - Leaves do not copy chunk text into the tree; content is resolved on demand, so source text is never duplicated. - Compress the capability-contract / provider-matrix / acceptance sections and the P0-P3 taxonomy into the corpus's Verification Slice + prose style. Kept as necessary: code-owned integrity gate, producer/hash/lineage identity, mind as the new traversal owner, single-pass vs agentic split, embeddings deferred until the explicit hybrid step. Net new surface: one package (quantmind.mind) and one sibling knowledge class; everything else reuses TreeNode, Citation, ArtifactLocator, the paper artifact tables, resolve(), from_draft(), and flows._runner unchanged. Refs #122, #95, #71. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Other long documents beyond papers will need navigation trees, so consolidate the tree mechanics into one implementation instead of a paper-only type: - NavigationTree: a structural base (BaseModel, no BaseKnowledge identity) owning root_node_id/nodes, the navigation surface (root/children_of/walk_dfs/ find_path), and the validate() integrity gate. No id/as_of/source, so a subclass adds identity without a second competing identity. - TreeKnowledge is refactored to TreeKnowledge(BaseKnowledge, NavigationTree), reusing the same nodes/helpers/gate — one tree in the codebase, not two. - PaperNavigationTree(NavigationTree) is the paper binding (a derived paper artifact: source_revision_id, producer/hash, chunk-set lineage), because a navigation tree is rebuildable, not canonical knowledge. - navigate(tree: NavigationTree, ...) is written against the base, so a future document type reuses navigation unchanged. Cross-links knowledge/paper.md's PaperTree note to the accepted design. Refs #122, #95, #71. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Two single-purpose diagrams, each answering one reader question: - classDiagram in "Navigation Tree Base and Paper Binding": the type model — NavigationTree base, TreeKnowledge/PaperNavigationTree subclasses, TreeNode/ Citation composition, and lineage to PaperSourceRevision/PaperChunkSet. - flowchart in a new "Design at a Glance": the cross-package spine (preprocess -> flows -> knowledge -> library -> mind) with a dotted hybrid branch, distinguishing deterministic/code stages from the model stage and marking where embeddings enter. Theme-neutral (no hardcoded colors), labels match the prose identifiers, and package boundaries use subgraphs. First exemplar toward a shared Mermaid convention for contexts/design. Refs #122, #95, #71. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
wanghaoxue0
self-requested a review
July 19, 2026 09:26
The artifact is the document's structure; navigation is only one operation over it (it is also seeded as context, queried, and used as reference), so naming the type after one verb was too narrow. This also matches upstream PageIndex, whose code calls the tree `structure` and exposes `get_document_structure()`. - Base: NavigationTree -> StructureTree - Paper artifact: PaperNavigationTree -> PaperStructureTree - PaperArtifactKind.NAVIGATION_TREE -> STRUCTURE_TREE - navigate() keeps its name (the traversal operation); its parameter is renamed tree -> structure; NavigationEvidence and the "Navigation Retrieval" operation section keep their operation-flavored names. - Updates the class + flow Mermaid diagrams and the knowledge/library/rag/README cross-links to the new type name and doc title. Refs #122, #95, #71. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ion.md -> retrieval.md PageIndex names the query path "reasoning-based retrieval" / "tree search" and its code module is retrieve.py; "navigate" appears only as a human metaphor, never as an operation name. A function should name the caller's intent (retrieve, like a dictionary lookup), not the internal tree-walk mechanism. - navigate() -> retrieve(); parameter tree -> structure - NavigationEvidence -> RetrievalEvidence - "## Navigation Retrieval" -> "## Retrieval"; quantmind.mind.navigation -> quantmind.mind.retrieval - git mv contexts/design/mind/navigation.md -> retrieval.md; title -> "Build and retrieve from a page-preserving structure tree" - Updates the flow Mermaid node and the knowledge/library/rag/preprocess/README cross-links to the new operation name, doc path, and title. "artifact" is kept deliberately: it is the existing master term (349 uses: PaperArtifactKind, paper_artifacts, ArtifactLocator, PaperChunkSet/-Summary) and standard in build/CI/ML tooling; renaming it is out of scope for a design PR. Refs #122, #95, #71. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.
What this is
A design-only PR. It adds
contexts/design/mind/retrieval.md, the accepted design for PageIndex-style, vectorless / reasoning-based retrieval over page-preserving document structure trees, and cross-links the existing knowledge, library, and RAG boundary sections. No implementation and noquantmindcode changes.Context and investigation are in #122.
Decisions
StructureTree(notNavigationTree) and the operation isretrieve()(notnavigate()). PageIndex's own code calls the treestructure(exposed asget_document_structure()) and frames the query path as reasoning-based retrieval / tree search; it uses "navigate" only as a human metaphor. The type names what the thing is (a structure); the operation names the caller's intent (retrieve). "artifact" is kept — it is the existing master term (PaperArtifactKind,paper_artifacts,ArtifactLocator,PaperChunkSet/PaperGlobalSummary) and standard in build/CI/ML tooling.StructureTreestructural base (a plainBaseModelwith noBaseKnowledgeidentity) ownsroot_node_id/nodes, the traversal surface (root/children_of/walk_dfs/find_path), and thevalidate()integrity gate. The existingTreeKnowledgeis refactored toTreeKnowledge(BaseKnowledge, StructureTree)so the codebase keeps one tree, not two. Other long-document types will subclass the same base.PaperChunkSet), soPaperStructureTree(StructureTree)is a paper artifact —source_revision_id,producer+producer_config_hash,content_hash, and chunk-set lineage — with afrom_draftconstructor that mints identity and runs the shared gate. It is not aTreeKnowledgestored as a knowledge item, and it is not a nestedTreeKnowledge(which would create a second competing identity).Citation. A node spanning pages 5-8 carries fourCitation(page=5..8)entries onTreeNode.citations; noCitation.end_pagefield is added. Leaves do not copy chunk text into the tree — content is resolved on demand, so source text is never duplicated.retrieve()is written against the base.retrieve(structure, question, *, library, cfg, seed_locators=None)reasons over titles and summaries and resolves leaf content through the existingLocalKnowledgeLibrary.resolve()(extended to the new kind) — no separate page-resolver, and no shared-runtime module:mind.retrievalcallsagents.Runner.rundirectly rather than importingflows._runner.preprocessemits deterministic outline signals (no LLM);knowledgeowns theStructureTreebase +PaperStructureTree;flowsruns one draft-structuring agent and calls the knowledge constructor (reusingflows._runnerunchanged);librarypersists the artifact and extendsresolve();mindowns agentic retrieval.ragstays deterministic chunking + BM25 and hosts no PageIndex draft producer.Requirements baked in
cfg.model(including alitellm/<provider>/<model>value) flows unchanged into the SDKRunner, which already routes providers — no bespoke resolver wrapper. Draft structuring needs structured output and agentic retrieval needs tool-calling; the provider test matrix covers at least one non-OpenAI model across both stages. Embeddings stay behind the library's existing_EmbeddingProviderseam.search()returnsSemanticHitvalues that keep a fullArtifactLocator.retrieve(..., seed_locators=...)seeds agentic retrieval from validated locators (single-tree mode constrainstree_idand rejects mismatched artifacts; cross-artifact mode keys by(artifact_id, node_id)). Embeddings stay a coarse pre-filter, never a replacement. Build and pure-agentic retrieval need no embedding provider.Diagrams
Two single-purpose Mermaid diagrams demonstrate a convention for
contexts/design: aclassDiagramfor the type model (theStructureTreebase and its subclasses) and aflowchartfor the cross-package build-to-retrieve spine with a dotted hybrid branch. Both are theme-neutral and label edges with meaning.Occam pass
An independent no-context review flagged an earlier draft for multiplying entities. This version drops a shared-runtime module and the
flows._runnermove, dropsCitation.end_page, drops aragdraft-helper allowance, folds a separate page-resolver intoresolve(), and compresses the process sections to the corpus'sVerification Slicestyle. Net new surface is one package (quantmind.mind) and one knowledge base + subclass; everything else reusesTreeNode,Citation,ArtifactLocator, the paper artifact tables,resolve(), thefrom_draftpattern, andflows._runnerunchanged.Not in this PR
quantmind.mindpackage, no code, no tests, no dependency changes.mind -> library -> knowledgeimport-linter contract lands with the implementation (depends on Tracking: Migrate Agent layer to OpenAI Agents SDK #71).Closes #122. Refines #95. Depends on #71.