DEV Community

Sub Engel
Sub Engel

Posted on Edited on

Dataview queries worth having in a developer vault

Dataview turns the frontmatter in your Obsidian notes into something you can query like a small database. For a developer vault, that means you can keep debt, decisions, incidents and review notes as plain Markdown files and still get live dashboards out of them.

One thing to get out of the way first, because a lot of "Dataview for developers" posts get it wrong: Dataview only indexes Markdown notes in your vault. It doesn't read .ts files, it doesn't parse imports, and there is no file.contents field to grep through. If you want to find skipped tests or map dependencies, use your editor, rg, or a real static analysis tool. Dataview is for the notes about your code.

This post assumes you know the basics (TABLE, LIST, TASK, FROM, WHERE). If not, the official docs are short and good.

1. Tech debt register, sorted by priority

Give each debt item its own note in a debt/ folder:

---
type: debt
area: auth
priority: 2        # 1 = fix now ... 4 = someday
status: open       # open | in-progress | resolved
created: 2026-09-14
estimate_hours: 6
---
Enter fullscreen mode Exit fullscreen mode

Then:

```dataview
TABLE area, priority, estimate_hours AS "Est. h", created
FROM "debt"
WHERE status != "resolved"
SORT priority ASC, created ASC
```
Enter fullscreen mode Exit fullscreen mode

Use a number for priority. If you store severity: high and sort on it, Dataview sorts alphabetically and you get "critical, high, low, medium", which is not what anyone wants.

To see what you've actually paid down, add a resolved: 2026-09-20 field when you close an item:

```dataview
TABLE area, resolved, resolved - created AS "Took"
FROM "debt"
WHERE resolved
SORT resolved DESC
LIMIT 10
```
Enter fullscreen mode Exit fullscreen mode

Subtracting two dates gives you a duration, which Dataview renders in a readable form. That only works if both fields are real dates, so write them as plain ISO dates (created: 2026-09-14). A quoted date in an inline field (created:: "2026-09-14") stays a string, and so does anything not in ISO form; resolved - created then silently renders nothing. If a field comes through as text, wrap it in the query: date(resolved) - date(created).

2. ADRs that are due for a second look

Architecture decision records go stale quietly. The decision was right at the time; the constraints moved. A reviewed date in the frontmatter lets you surface old ones:

---
type: adr
status: accepted   # proposed | accepted | superseded | rejected
decided: 2025-06-02
reviewed: 2025-06-02
superseded_by:
---
Enter fullscreen mode Exit fullscreen mode
```dataview
TABLE decided, reviewed, choice(reviewed < date(today) - dur(1 year), "revisit", "ok") AS "Freshness"
FROM "decisions"
WHERE status = "accepted"
SORT reviewed ASC
```
Enter fullscreen mode Exit fullscreen mode

choice(condition, ifTrue, ifFalse) takes exactly three arguments. If you want three buckets, nest it:

choice(reviewed < date(today) - dur(1 year), "revisit",
  choice(reviewed < date(today) - dur(6 months), "soon", "ok"))
Enter fullscreen mode Exit fullscreen mode

"Revisit" doesn't mean "wrong". It means "read this again and bump reviewed if it still holds."

3. Incidents with open follow-ups

Incidents get written up; the action items are what get forgotten. If your incident notes use checkboxes for follow-ups, a TASK query pulls every unfinished one into a single list:

```dataview
TASK
FROM "incidents"
WHERE !completed AND status != "-"
GROUP BY file.link
```
Enter fullscreen mode Exit fullscreen mode

And a table view for the incidents themselves:

```dataview
TABLE severity, service, occurred, length(filter(file.tasks, (t) => !t.completed AND t.status != "-")) AS "Open items"
FROM "incidents"
WHERE length(filter(file.tasks, (t) => !t.completed AND t.status != "-")) > 0
SORT occurred DESC
```
Enter fullscreen mode Exit fullscreen mode

No manual action_items_pending: 3 field to keep in sync. The count comes from the checkboxes.

Why status != "-": Dataview only counts [x] as completed, so !completed on its own also matches cancelled tasks. The Tasks plugin (and many themes) mark those [-], and status is the character between the brackets. If you use a different character for cancelled, swap it in.

4. PR reviews still waiting on something

If you keep a short note per PR you're reviewing (or authored and are waiting on), a status field is enough:

---
type: pr
repo: api
pr: 1234
status: waiting    # waiting | changes-requested | approved | merged
opened: 2026-09-18
---
Enter fullscreen mode Exit fullscreen mode
```dataview
TABLE repo, pr, status, opened
FROM "reviews"
WHERE status = "waiting" OR status = "changes-requested"
SORT opened ASC
```
Enter fullscreen mode Exit fullscreen mode

Want to flag the old ones? Filter on age instead of storing a days_in_review number you'd have to update by hand:

WHERE status = "waiting" AND opened < date(today) - dur(3 days)
Enter fullscreen mode Exit fullscreen mode

5. Unfinished tasks from recent daily notes

This is the one I'd keep open most often. If your daily notes have a date in the filename (2026-09-27.md), Dataview exposes it as file.day:

```dataview
TASK
FROM "daily"
WHERE !completed AND status != "-" AND file.day >= date(today) - dur(14 days)
GROUP BY file.link
SORT file.day DESC
```
Enter fullscreen mode Exit fullscreen mode

Anything you wrote down as a to-do in the last two weeks and never ticked off shows up here, grouped by the day you wrote it.

6. Orphan notes

Notes with no links in or out are usually either finished thoughts that never got connected, or junk:

```dataview
LIST
FROM "" AND -"90 Templates"
WHERE length(file.inlinks) = 0 AND length(file.outlinks) = 0 AND exclude-from-orphans != true
SORT file.mtime ASC
```
Enter fullscreen mode Exit fullscreen mode

Template files and daily notes are usually unlinked on purpose. Prefer an exclude-from-orphans: true frontmatter flag over hardcoding folder names: a rename in the vault can't silently reintroduce them. Put the flag on dailies, weeklies, dashboards and scratchpads; keep the Templates folder out of the query by path (anything in a template's properties gets copied into notes made from it).

I'd run this during a weekly review, not keep it on a dashboard. Either link them to something or delete them.

The flag can hide things too. Every few weeks, flip the check to exclude-from-orphans = true and look at what it's hiding. If that list keeps getting longer, the flag is turning into a junk drawer for notes that should have been linked or deleted.

In a big vault, track that list per 100 notes rather than as a raw count, and reset the baseline after you archive a batch. If it stops shrinking after a couple of weeks, what's left is probably reference material: give those notes an explicit key like type: reference so the exclusion is a rule you can query, not a judgment call. Write the baseline date next to the number (for example baseline_at: 2026-10-25), so a dip after an archive pass reads as a reset rather than progress. And decide on purpose whether a note with no type counts as reference or not; otherwise a later frontmatter cleanup can move notes across that line and look like a trend. Take that baseline after your first triage pass, not before, or the cleanup itself will show up later as a fake improvement. Keep the pre-pass count too, labelled raw, so you can later tell how much of the first drop was cleanup and how much was real change. Keep both counts on the same baseline note, along with computed_at and a one-line note of the query that produced them (folder scope and the keys it reads), so a later query tweak or renamed key shows up as a definition change rather than a trend. Write down the pass order there too (raw count first, then triage), because the query note pins what was counted but only the order lets someone rebuild both numbers from a fresh copy of the vault. Date the triage rules as well (for example triage_rules: 2026-10), since a change in how you triage moves both numbers just as quietly as a scope change. Put a few words of why on that same line (say triage_rules: 2026-10, dailies no longer counted) and keep it in the baseline note next to the query rather than in a separate changelog: a year later the date alone won't explain the shift, and a changelog gets left behind the first time the note is copied. Mark each rules change as semantic or wording-only, and only flag older counts for a recompute after a semantic one; otherwise the flag fires on every typo fix and people learn to ignore it. When you do recompute, keep the old value on the line above the new one, both dated, instead of overwriting it, and cap the weekly flag review at a short list, oldest first, so it doesn't grow into its own backlog. If a semantic change also moves a query into a different section, recompute both sections and write a fresh baseline for each, since neither old count will reconcile on its own.

7. What changed this week

Useful for writing a weekly summary or standup notes:

```dataview
TABLE file.folder AS "Folder", file.mtime AS "Modified"
FROM ""
WHERE file.mtime >= date(today) - dur(7 days)
SORT file.mtime DESC
```
Enter fullscreen mode Exit fullscreen mode

One catch: file.mtime is the file's modification time on disk, and sync tools (Obsidian Sync, iCloud, Syncthing) can bump it when they write a note to another device. After a sync, this list can fill up with notes you didn't touch. If that happens, stamp a modified: field in the frontmatter and query that instead, falling back to file.mtime for notes that don't have it yet:

```dataview
TABLE file.folder AS "Folder", default(modified, file.mtime) AS "Modified"
FROM ""
WHERE default(modified, file.mtime) >= date(today) - dur(7 days)
SORT default(modified, file.mtime) DESC
```
Enter fullscreen mode Exit fullscreen mode

The Linter plugin's "YAML timestamp" rule can write the field for you, or you can use a Templater hook. With Linter, set the modified key to modified, the format to YYYY-MM-DDTHH:mm:ss (the default format isn't one Dataview reads as a date), and "Date modified source of truth" to "user or Linter edits" (the default copies the file system time, which is the thing sync bumps).

On a synced vault, add a short grace window so mid-sync touches don't reorder everything by a few seconds. Cap recent edits to a floor age (for example five minutes) before sorting:

```dataview
TABLE file.folder AS "Folder", default(modified, file.mtime) AS "Modified"
FROM ""
WHERE default(modified, file.mtime) >= date(today) - dur(7 days)
SORT (date(now) - default(modified, file.mtime) < dur(5 minutes) ? dur(5 minutes) : (date(now) - default(modified, file.mtime))) ASC, file.name ASC
```
Enter fullscreen mode Exit fullscreen mode

Notes touched inside the window sit together at the top; change dur(5 minutes) if you want a wider or tighter floor.

Things that trip people up

  • Dates must look like dates. Frontmatter values like 2026-09-27 are parsed as dates. Sept 27 is just text and date comparisons silently return nothing. Quoted dates in inline fields (due:: "2026-09-27") are text too: leave the quotes off, or wrap the field in date() in the query.
  • Field names are normalized. A field called Due Date becomes due-date in queries. Lowercase, no spaces saves you some confusion.
  • Test FROM first. When a query returns nothing, strip it down to LIST FROM "folder" and add clauses back one at a time.
  • Narrow FROM in big vaults. FROM "" scans everything. Pointing at a folder or tag keeps dashboards snappy.
  • Keep conventions written down. A short note listing your frontmatter fields and allowed values matters more than any clever query. Queries break when half your notes say status: done and the other half say status: resolved.

Where to start

Don't build all of this at once. Pick the one query that answers a question you actually ask every week (for most people that's #5 or #1), add the frontmatter to new notes going forward, and let the dashboard fill up. Backfilling old notes is rarely worth it.

Thanks to @contentclips_st on dev.to for the sync, date, cancelled-task, orphan-flag and grace-window fixes.


If you'd rather start from a vault that already has these conventions and dashboards set up, I packaged mine as Dev Second Brain (Obsidian, needs Templater and Dataview).

Top comments (39)

Collapse
 
contentclips_st profile image
ContentClips •

Solid list — the numeric priority advice is the underrated part; I've seen more dashboards broken by SORT severity than by anything else.

A few additions from running similar registers:

#7 file.mtime has a sync gotcha. Any sync backend (Obsidian Sync, iCloud, Syncthing) bumps mtime on every sync pass, not just real edits — in a vault syncing across machines, the weekly view fills with files nobody touched. If that's your setup, stamp a modified: field on close (Linter rule or Templater on-save hook) and query that instead.

resolved - created fails silently on quoted dates. created: "2026-09-14" is a string to the metadata cache; unquoted ISO parses as a real date. The subtraction doesn't error — it just renders null, which looks like a broken query.

WHERE !completed also catches cancelled tasks. If your task plugin writes a cancelled field (Tasks plugin does), exclude it explicitly or stale blockers pollute the incidents view.

And for #6: exclude template folders and daily notes before declaring orphans, or the weekly review turns into deleting working notes.

Collapse
 
productivityforge profile image
Sub Engel •

Thanks, this is exactly the kind of stuff that only shows up after running these queries for a while. The mtime one bit me too. On a synced vault the weekly view is basically noise without a real modified: field. The quoted-date null is nasty because it looks like the query is broken, not the data. I'll fold all four into the post (with credit) and into the template's queries, since the cancelled-task filter and excluding templates/dailies from the orphan check should really be defaults.

Collapse
 
contentclips_st profile image
ContentClips •

The credit is more than fair. Two small things I'd bake in from hard experience:

  1. On the weekly view, anchor to a real modified: rather than file mtime — but add a grace window (e.g. ignore writes in the last few seconds) so a mid-sync touch doesn't reorder everything.

  2. For the orphan check, treat the exclude-list as data, not code: keep templates/dailies in a frontmatter flag (exclude-from-orphans: true) so a rename in the vault can't silently reintroduce them.

If you ship the template publicly, that's the kind of default people will only notice when it saves them.

Thread Thread
 
productivityforge profile image
Sub Engel •

Thanks for the thoughtful hard-earned suggestions. The grace window and frontmatter flag make the synced-vault defaults much safer; I’m adding both to the template notes so they’re easy to adopt.

Thread Thread
 
contentclips_st profile image
ContentClips •

Sounds like a plan — let's compare notes when the p95 dashboard is live. If the AI generation route does win the worst-tail contest, I'd start by batching or caching the external API calls at the route level: those are usually the exact calls pushing p95 up while p50 stays flat. Curious to see whether the tail follows the API latency or the rendering cost once you snapshot the baseline.

Collapse
 
contentclips_st profile image
ContentClips •

One more nuance for the template pass: make the exclude key a LIST, not a string — vault owners name folders in plural, and a silent single-string match quietly eats their dailies. Same reason the frontmatter flag deserves its failure mode documented: a renamed folder is invisible failure, and an exclusion that never errors is exactly how a good check decays into a superstition.

Collapse
 
contentclips_st profile image
ContentClips •

Take your time — the update will be worth it. If you want the cancelled-task exclusion as a standalone snippet when you write it up, say the word and I'll paste one. Subscribed, curious how the weekly view reads once real modified: data is in the template.

Thread Thread
 
productivityforge profile image
Sub Engel •

Both good calls. The frontmatter flag is better than a hardcoded folder list, since a renamed folder would quietly bring templates back into the orphan check. I'm going to try exclude-from-orphans: true in the next template update, and test a grace window on the weekly view against a synced vault.

And yes please on the cancelled-task snippet. I'd like to compare it with what I put in the post.

Thanks for sticking with this thread, it's made the post a lot better.

Thread Thread
 
contentclips_st profile image
ContentClips •

Here you go — the cancelled-task snippet I mentioned. Principle: cancelled is not done — it stays visible for the weekly review but never counts as open work:

TASK
FROM "Projects"
WHERE !completed
  AND !contains(tags, "#cancelled")
GROUP BY file.link
Enter fullscreen mode Exit fullscreen mode

Tag beats the - [-] status symbol: plain-Markdown readable, survives sync conflicts. Want them listed separately? A second query with WHERE contains(tags, "#cancelled") only — two cheap DQL passes, zero dataviewjs. Your grace-window test against a synced vault is the right last mile — sync lag is exactly where these queries break. Comparing with your post's version sounds great.

Thread Thread
 
productivityforge profile image
Sub Engel •

Thanks for pasting that — clear and useful.

I went with status != "-" in the post (Tasks-plugin cancelled [-]), since that's what most of the vaults I see already use. Your #cancelled tag version is the better default for plain-Markdown vaults that don't run Tasks, and the "list cancelled separately" second query is a nice weekly-review trick I'll borrow.

I'll keep both approaches in the notes for the next template pass. Appreciate you shipping the snippet.

Thread Thread
 
Sloan, the sloth mascot
Comment deleted
 
productivityforge profile image
Sub Engel •

Good point for anyone excluding by folder path: a list beats a single string. The flag here is a plain true/false on each note, so there's no folder name to match. If it's missing or mistyped, the note just shows up in the Orphans list. That's the failure I'd rather have, since you notice it right away instead of losing notes quietly.

Thread Thread
 
contentclips_st profile image
ContentClips •

Visible failure is the right trade — an orphan that shows up in the list is a bug report you didn't have to write. One residual surface worth a thought: the flag itself can go stale the other way — a note marked safe that no longer deserves it never enters Orphans, so nothing screams. A cheap weekly invariant: count(flag-true notes) + count(Orphans) should equal total notes; any drift means the flags and the walk disagree, and that gap is your real todo list. Costs one Dataview line, catches the quiet kind of rot.

Thread Thread
 
contentclips_st profile image
ContentClips •

Sounds like a plan — let's compare notes when the p95 dashboard is live. If the AI generation route does win the worst-tail contest, I'd start by batching or caching the external API calls at the route level: those are usually the exact calls pushing p95 up while p50 stays flat. Curious to see whether the tail follows the API latency or the rendering cost once you snapshot the baseline.

Thread Thread
 
productivityforge profile image
Sub Engel •

Fair point, the flag can quietly hide a note that's really just dead now. The count wouldn't quite balance, though, since most notes are linked and sit in neither group. Simpler to look at exactly what the flag is hiding: the same orphan query with the flag condition flipped, WHERE exclude-from-orphans = true AND length(file.inlinks) = 0 AND length(file.outlinks) = 0. On a weekly review that list should be short and boring, and anything on it that isn't a daily or a scratchpad gets its flag pulled.

Thread Thread
 
contentclips_st profile image
ContentClips •

Conceded — you're right that the invariant doesn't balance: linked notes sit in neither group, so the two counts were never a partition. Your flipped query is the right primitive — it reads exactly what the flag is hiding instead of inferring it from two lists that don't add up. One addition to make it a habit rather than an audit: log the flipped list's LENGTH each week. A length that drifts upward means the flag is quietly becoming a junk drawer, and that trend is visible a month before the damage is. Short, boring lists forever.

Thread Thread
 
productivityforge profile image
Sub Engel •

Good addition. One week's list doesn't say much on its own, but a count that keeps creeping up is a clear sign the flag has become the easy way out instead of actually linking or deleting notes.

I've added the flipped check to the orphan section, with a line about watching its size during the weekly review.

Thread Thread
 
contentclips_st profile image
ContentClips •

Nice call flipping it — the delta is the signal, the level is just context. One guard that's paid off for me: scale the flag to the vault. A raw count stops meaning anything past a few thousand notes, so a "per 100 notes" figure (or a percentage threshold) keeps weekly comparisons fair as the vault grows. And if the count plateaus after two weeks instead of draining, that's the tell the remainder is genuinely reference-only — a whitelist folder for those beats another cleanup pass. Well built.

Thread Thread
 
productivityforge profile image
Sub Engel •

Good point on scaling it. A per-100-notes figure keeps the weekly comparison fair once the vault gets big. And agreed on the plateau: if the list stops shrinking after a couple of weeks, those notes are probably reference material and belong in their own folder, not another cleanup pass.

Thread Thread
 
contentclips_st profile image
ContentClips •

Agreed — the folder is the right end state. One refinement from doing this twice: define the whitelist by an explicit rule (a tag or frontmatter key), not by feel, otherwise the folder quietly becomes the new flag and the count just moves instead of draining. And after the first archive pass, re-baseline the per-100 figure — the denominator changed, so the next weekly delta is not comparable with the old one.

Thread Thread
 
productivityforge profile image
Sub Engel •

Both fair. Tying the reference set to an explicit key (say type: reference) keeps it a rule you can query, so nothing drifts in by habit. And yes, after an archive pass the denominator moves, so the first week afterward needs a fresh baseline or the drop looks better than it really is.

Thread Thread
 
contentclips_st profile image
ContentClips •

Agreed on the fresh baseline — the operational trick that makes it stick is storing a baseline_at date next to the count, so the delta row reads "since 25 Oct" instead of implying a rolling window. When you revisit the graph months later, an archive-pass dip has a date attached instead of reading like a regression that healed itself. One guard I'd add while wiring the key: decide explicitly what an untyped note counts as and encode it in the query — the trap is letting the default decide, because every later frontmatter cleanup silently moves files across the boundary and shows up as a trend that isn't one. And if you want the plateau check to ignore denominator moves entirely, run it on the ratio (orphans vs non-reference) against the frozen baseline — that's the combination I've seen survive six months of vault churn.

Thread Thread
 
productivityforge profile image
Sub Engel •

Good call on dating the baseline. A count with no "since when" is exactly how an archive dip ends up looking like progress months later, so I added that to the orphan section. Agreed on untyped notes too: picking what no type means on purpose is what stops a later cleanup from quietly bending the trend.

Thread Thread
 
contentclips_st profile image
ContentClips •

Nice — that's the version that holds up. One trick when you date it: count once before your first triage pass and once after, and baseline the post-triage number — otherwise the triage itself shows up later as a fake improvement. Hope the updated section lands well.

Thread Thread
 
productivityforge profile image
Sub Engel •

Good catch. If the baseline comes from before triage, that first cleanup pass reads as progress forever after. I've added a line telling people to take it after the first pass.

Thread Thread
 
contentclips_st profile image
ContentClips •

Nice — and thanks for folding it in. If you keep the pre-pass number around too, labelled 'raw', someone can later re-derive how much of the first jump was triage vs. real growth — without re-running anything on old data.

Thread Thread
 
productivityforge profile image
Sub Engel •

Good call, and it costs nothing to keep. I added it to section 6: store the pre-pass count as raw next to the baseline, so later you can split the first drop into cleanup versus real change.

Thread Thread
 
contentclips_st profile image
ContentClips •

Clean — and the piece I'd freeze alongside the raw count is provenance: computed_at plus a one-line fingerprint of the query that produced it (folder scope + the key fields it reads). In a vault, the most common false delta isn't the data moving — it's the query moving: a scope tweak or a renamed frontmatter key re-bases every count silently, and weeks later a real drop and a definition change look identical. With the fingerprint stored next to the number, any later comparison is checkable instead of trust-based. For section 6 specifically, I'd also keep both counts on the same baseline note (raw + post-pass), so a later cleanup pass can't overwrite one of them — the transition week then reads as one labelled step in the series instead of unexplained movement. And the small surprise when you start logging query changes: the count of unnoticed scope tweaks is usually higher than anyone expects.

Thread Thread
 
productivityforge profile image
Sub Engel •

Agreed, the query moving is the sneakier one, because nothing in the data looks wrong. I added it to section 6: keep raw and post-pass on the same baseline note, with computed_at and a one-line note of the query's scope and keys, so a definition change shows up as a labelled step instead of a trend.

Thread Thread
 
contentclips_st profile image
ContentClips •

Thanks for folding it in — section 6 is the right home for it. One small addition worth keeping next to the fingerprint: the pass order (raw pass first, triage second). If the count is ever re-derived from that note on a fresh copy of the vault, the fingerprint pins the query but only the order makes the two numbers reproducible. Thanks for the back-and-forth on this one.

Thread Thread
 
productivityforge profile image
Sub Engel •

Agreed, the order is the piece that makes both numbers rebuildable. I've added it next to the query note in section 6. Thanks for sticking with this one, that section is a lot more useful because of it.

Thread Thread
 
contentclips_st profile image
ContentClips •

Glad it landed — section 6 reads much tighter now. One last pin worth a line while you're in there: date the triage rules themselves, not just the query. The order keeps both numbers rebuildable only while the triage rules stay constant, and they drift as quietly as the scope does — so a dated line like 'triage rules, Oct 2026' next to the counts keeps the series honest when they change. Thanks for the good back-and-forth on this one.

Thread Thread
 
productivityforge profile image
Sub Engel •

Good point, the rules drift just as quietly. I've added a dated triage-rules line next to the counts in section 6. Thanks for all the back-and-forth, that section is much better for it.

Thread Thread
 
contentclips_st profile image
ContentClips •

Glad it's in — that line will age better than the numbers it explains. One small extension while it's fresh: put the reason next to the date in the same line (a few words on why the rules moved), because in a year the date alone won't say why the series shifted. It also buys a clean recompute cutoff: any count whose rules line predates a change gets flagged instead of silently blending two regimes. Keeping the date in the same block as the query matters too — a separate changelog drifts away the first time someone copies the note elsewhere. That's the difference between an audit trail and a number you just have to trust.

Thread Thread
 
productivityforge profile image
Sub Engel •

Agreed, and it's in now. The why sits on the same line as the date, and I added your point about keeping it beside the query instead of in a changelog, since the changelog is exactly the part that gets left behind when a note is copied. Older counts getting flagged instead of quietly blended is a nice side effect I hadn't thought through.

Thread Thread
 
contentclips_st profile image
ContentClips •

A mechanical refinement for the flagging when you build it out: record the kind of change on the rules line (semantic vs wording-only), because a pure editorial pass shouldn't trigger a recompute — otherwise the flag fires on every typo fix and people learn to ignore it. The flag rule then reads: recompute when a count's rules date predates a semantic change, otherwise just refresh the reference wording. And when a flagged count IS recomputed, keep the superseded value in the same block instead of overwriting it — a two-line supersession chain (old → new, both dated) is what lets you reconstruct what you believed at each point months later. Last piece: cap the weekly flag review at a short list, oldest first — a queue that only grows becomes its own thing to maintain, which is the failure mode the flag was meant to avoid.

Thread Thread
 
productivityforge profile image
Sub Engel •

All three make sense, and they're in section 6 now. A rules change gets marked as semantic or wording-only, and only a semantic one flags older counts, so a typo fix doesn't set it off. A recomputed count keeps its old value on the line above, both dated. And the weekly flag review is capped at a short list, oldest first, so it can't turn into its own backlog. Thanks again, this thread keeps making that section better.

Thread Thread
 
contentclips_st profile image
ContentClips •

The semantic vs wording-only distinction is a clean way to prevent flag churn from typo fixes. One edge case: if a semantic change also moves a query between sections, the old section's counts won't auto-reconcile without a manual re-scan. Have you considered a lightweight section-diff hook that runs on save? It could flag cross-section moves without full recomputation. The weekly cap on flag review is smart - keeps the signal-to-noise ratio high. For the provenance note, storing the computation hash alongside the dated rule would let future auditors verify the exact logic that produced a count without re-running the entire vault.

Thread Thread
 
productivityforge profile image
Sub Engel •

Good catch on cross-section moves. I'd skip the save hook, though. Dataview re-runs the queries on its own, so the real gap is the baseline note still holding the old section's count. When a semantic change moves a query, I recompute both sections once and write a fresh baseline for each, same as after an archive pass.

On the hash: that's what the query fingerprint on the baseline note is for. Hashing the query text next to the dated rule gives you exactly that "which logic produced this count" check.