Skip to content

Evaluate a saved query in a note and render its table #275

Description

@BattermanZ

This was generated by AI during triage.

Part of #272

Agent Brief

Category: enhancement
Summary: Read saved queries from base blocks in a note, evaluate them against that note's Vault, and draw the resulting tables in place

Current behavior:
A fenced ```base block in a note renders as an opaque code block. Nothing parses it and nothing evaluates it.

Desired behavior:
A note may carry one or more saved queries. A saved query is a query definition stored in a fenced base block, written in a documented subset of the Obsidian Bases syntax. When the note is read, Hatchdoor evaluates each one against the Vault the note lives in and draws its table where its block sits. A note with three blocks renders three tables, each independent of the others.

The supported subset for this ticket:

  • filters over tags, frontmatter properties, and note path
  • equality and ordered comparison, boolean and / or / not, emptiness checks
  • the current date and time as a value in comparisons
  • column selection and left-to-right column order
  • a row limit set by the definition

Rows link to the notes they came from. The default row order is note title, ascending, and it must be stable: identical Vault state produces an identical order on every evaluation.

Naming a saved query. A saved query may carry a name, supplied by an HTML comment immediately preceding its block:

<!-- hatchdoor-query: active-subscriptions -->
```base
...
```

The marker sits outside the base block on purpose. Anything inside the block changes what Obsidian is asked to parse, and there is no published specification to check that against (ADR-21). Only blank lines may separate a marker from the block it names. A name is a slug of lowercase letters, digits and hyphens. The marker is an identifier, never displayed: it is parsed out, and raw HTML is not rendered in note bodies in any case.

Names exist for addressing a saved query from outside the note, which is #277's concern. This ticket only has to parse them, hold them, and keep them out of the rendered output.

Two hard rules that outrank convenience:

  1. A query result is never content. It is recomputed on every read, never written into the Markdown, and search, backlinks, statistics and the graph stay blind to it. The file on disk remains the whole truth about the note.
  2. A saved query sees only the Vault its note lives in. Not widenable by the definition, not widenable by the caller.

Evaluation happens on demand. Do not precompute and store results: a filter comparing against the current time changes its answer with no file change at all, so a stored result is wrong on a schedule.

Two ceilings apply. The definition's own row limit, which the author controls, and a limit Hatchdoor enforces regardless on how many notes one saved query may scan and how many rows it may return. A definition with no filters is an easy thing to write by accident and must not be able to hang the page. The enforced ceiling applies per saved query, and a note holding several must not be able to multiply its way past the intent of that limit.

Key interfaces:

  • A saved query type carrying its optional name and the definition parsed from the YAML inside its base block, covering the subset above
  • A condition model shared with the query capability from the regression fix, rather than a second engine. This ticket is blocked on that work for exactly that reason.
  • An evaluation entry point taking a definition plus the note's Vault, returning Vault-qualified rows with their selected properties in a stable order
  • A renderer for the note page that replaces each block with its table, scrollable horizontally rather than widening the page

Acceptance criteria:

  • A base block using only the supported subset renders as a table on the note page
  • The reporter's subscriptions example in Feature request: Obsidian Bases-compatible live query views inside notes #272 renders correctly against a fixture Vault
  • A note holding two base blocks renders two tables, each in its own position, evaluated independently
  • A hatchdoor-query marker preceding a block is parsed as that saved query's name and does not appear in the rendered note
  • A block with no marker is still evaluated and rendered; the name is optional
  • A filter comparing a date property against the current time gives a different answer as time passes, with no file change
  • Column selection and column order follow the definition
  • The definition's row limit is respected
  • Rows link to their notes
  • Identical Vault state produces an identical row order across repeated reads
  • The note's Markdown on disk is byte-for-byte unchanged by any number of evaluations
  • Searching for text that appears only in a computed row does not return the note holding the saved query
  • A note holding a saved query gains no backlinks or graph edges from its rows
  • A definition scanning beyond the enforced ceiling stops and says so rather than truncating silently
  • Anything outside the supported subset is refused rather than partially applied

Out of scope:

  • Standalone .base files. Only definitions embedded in a note are read; .base files stay unindexed as they are today.
  • Addressing a saved query by name from outside the note, which is Agent access to saved query results #277
  • The quality of refusal, empty and truncation messages, and click-to-sort. Refusal must be safe and visible here; making it informative is Saved query states: refusal, empty, truncation, and presentation gaps #276.
  • Grouping, cards, list, map or kanban views, formulas, summaries, and inline editing of computed values
  • A sort key in the definition. Row sorting is not part of the Bases format and no Hatchdoor-only key may be invented for it.
  • Cross-vault queries

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

enhancementNew feature or requestready-for-agentImplementation-ready for an engineering agent

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions