Skip to content

fix: make the knowledge bundle's rules enforceable, and its claims true#3603

Merged
matthiasn merged 18 commits into
mainfrom
docs/knowledge-onboarding-fixes
Jul 26, 2026
Merged

fix: make the knowledge bundle's rules enforceable, and its claims true#3603
matthiasn merged 18 commits into
mainfrom
docs/knowledge-onboarding-fixes

Conversation

@matthiasn

@matthiasn matthiasn commented Jul 26, 2026

Copy link
Copy Markdown
Owner

Follow-up to #3600. The knowledge bundle shipped with rules it did not enforce and
claims that did not match the code; this makes the rules enforceable, corrects the
claims, and writes down two conventions that existed only as practice.

Docs and tooling only — no runtime change, so no CHANGELOG entry.

Rules the bundle documented but did not enforce

  • House metadata is now an error, not a warning. A concept missing a
    description, a freshness date or code provenance failed nothing. Neither
    make okf_check nor CI passed --warnings-as-errors, so the rules that keep the
    map honest were the only ones nothing checked. What stays advisory is the narrow
    set OKF is deliberately permissive about — a link to knowledge not written yet
    (§6.1) — plus the Attested Computation fields nothing here uses.
  • resource and tags are required and non-empty. Two architecture concepts
    had no resource at all and validated clean; resource: "" and tags: [] also
    passed. Requiring resource surfaced a validator bug: a reference landing on the
    repository root normalises to the empty string, and neither File('') nor
    Directory('') exists, so ../.. read as a dangling pointer.
  • stale_after fails the build when it passes, and warns for the fortnight
    before, so a batch coming due is never first heard about as a red push. Dates are
    staggered by subsystem — 15 review dates instead of 3, at most eleven concepts
    each — so a re-read is a coherent sitting rather than a 48-concept burst.
  • An unclosed fenced block is an error. A closing fence with prose welded to it
    is not a close under CommonMark, so the tail of one concept had been rendering as
    code — and the link scanner missed it because stripCodeSpans is looser about
    where a block ends.
  • Mermaid is parsed in CI. There is no Dart mermaid parser, so
    tool/okf/check_mermaid.mjs runs mermaid itself under jsdom, wired as a
    mermaid job and into make knowledge_check — one target, because two meant the
    second was skipped. It also inspects the built diagram: a ; in an unquoted
    label parses clean while rendering phantom nodes, and two live diagrams were
    doing exactly that. 15 tests of its own.
  • An unrecognised --flag is rejected rather than ignored, which is how
    --warnings-as-error could report a clean bundle it had never checked strictly.

Claims that did not match the code

Roughly thirty corrections, each checked against source. The ones that mattered
most:

  • The privacy claim. "Every read passes a private-visibility gate" was wrong by
    an order of magnitude, and the first correction then overshot in both directions.
    The accurate account: nine of ten query-bearing mixins gate on private through
    three mechanisms — the helper, privateStatuses passed by the caller, and
    raw SQL reading config_flags in insights_queries — and what skips filtering is
    single-entity journal reads, not by-id reads as a class. The stale comment in
    database_config_flags.dart that seeded the original error is corrected too, so
    code and concept now agree.
  • PROPAGATED:: was documented inverted. Every emitter sends the bare token in
    the same set, deliberately, so matching it alone is complete; the prefix exists
    for the wake orchestrator, whose deferral is opt-in per subscription.
  • DerivedAgentState drives no production read — its own header says so.
  • CI does not run tests single-threaded. very_good test keeps its optimizer
    on, so one generated entry point is sharded ten ways: a leak reaches unrelated
    files in the same shard, which is the real reason for teardown discipline.
  • TaskStatus has seven variants, not five; blocked and onHold carry a
    reason; the live/terminal split is duplicated across six sites with no shared
    constant.
  • The build-runner trap claimed git status stays clean. Generated files are
    tracked, so the deletions do show — git status is the only signal there is.
  • Adding a settings page touches six places, not five, four of them failing
    silently; the runtime-topology diagram was missing five root nodes and invented
    one child.
  • sources[].last_modified was fabricated at scale — 162 of 229 disagreed with
    git log, some by six weeks. All 238 match now.

Structure and coverage

  • 23 single-concept directories collapsed to features/<name>.md; the projection
    kernel moved under the agents tree. 24 index files gone, all inbound links and
    24 lib/ READMEs retargeted.
  • Diagrams added to seven concepts whose subject has a shape prose cannot carry;
    three pre-existing diagrams that never rendered are fixed. 69 of 89 concepts
    carry one.
  • Newly documented: the private read gate, the UpdateNotifications token
    vocabulary and its PROPAGATED:: semantics, DerivedAgentState and the shadow
    comparison, the error-log mirrors including the PII-safe sink, the slow-query
    second tier, TaskStatus, and what shared-widgets omits.
  • Two conventions written down that existed only as practice: screenshots
    (where captured images live — lotti-docs, never here — the three destinations
    there, and the before/after pair a UI PR carries), and the contribution policy.

Contribution policy

CONTRIBUTING.md invited "pull requests for fixes and features" and the README
welcomed "small, focused PRs ... without prior discussion". Neither reflects the
policy: code contributions are not accepted, and the two things that help are issue
reports and translations. Both files now say that, with the reasons stated once.
CONTRIBUTING.md is kept rather than folded into the README because GitHub
surfaces it in the pull-request form — the one place the message reaches someone at
the moment they are about to open a PR.

Verification

make knowledge_check (89 concepts, 131 diagrams), strict mode, 92 validator
tests, 15 mermaid-checker tests, analyzer, formatter, git diff --check, zero
dangling links from lib/ READMEs, zero orphaned concepts, and all 238
sources[].last_modified matching git log -1.

Summary by CodeRabbit

  • New Features

    • Added comprehensive knowledge documentation for settings, agents, privacy, synchronization, tasks, and other core features.
    • Documented a new projection-kernel concept and expanded diagrams throughout the knowledge bundle.
    • Clarified that the knowledge-graph explorer is available from task app bars.
  • Bug Fixes

    • Corrected documentation links, navigation references, metadata, and behavioral descriptions.
  • Validation

    • Added automated Mermaid diagram parsing and rendering checks.
    • Strengthened knowledge-bundle validation for required metadata, links, dates, and unfinished code blocks.

matthiasn added 18 commits July 26, 2026 15:36
…ed agents

Four problems where the agent-facing docs either contradicted the code or
under-specified the gate that fails CI.

The validator reported this repo's own metadata rules as warnings, and neither
`make okf_check` nor CI ran with `--warnings-as-errors` — so the rules that keep
the map honest, including the requirement that at least one source points at
code outside the bundle, were the only ones nothing enforced. They are errors
now. What stays a warning is the narrow set OKF is deliberately permissive about
(a link to knowledge not written yet, §6.1) plus a newly reported signal no
edit caused: a concept whose `stale_after` has passed. Blanket strictness would
have forbidden the forward links the spec blesses, which is why the split is in
the severities rather than in a CLI flag.

`knowledge/conventions/knowledge-bundle.md` documented about half the enforced
rules, credited the 60-line CLI wrapper with implementing them, defined neither
`resource`, `tags`, `sources[].id` nor `sources[].last_modified`, and described a
two-audience documentation split that has three homes. It now matches the
validator rule for rule.

`AGENTS.md` told agents to add new labels to six ARB catalogs; twelve ship, and
`conventions/localization.md` documented the discrepancy instead of resolving
it. The policy is now stated once, in the concept: every new label goes into all
twelve, translated. AGENTS.md links it rather than carrying a copy that goes
stale — and now links `knowledge/index.md`, which it never did.

Nothing said which source wins when they disagree. `knowledge/index.md` gains a
reading order, an authority hierarchy that puts the code above the prose, the
consequence (a concept that contradicts the code is the defect), what an unset
`verified` means, and a code-to-concept map for the shared trees under `lib/`
that have no README to link from.
…an something

24 of 32 feature entries were a five-line index.md wrapping one overview.md of
31–197 lines, while the convention says a feature earns a directory only once its
knowledge outgrows a couple of hundred lines. The structure contradicted the rule
and charged every reader an extra hop to be told where the file was, so those
concepts are now `features/<name>.md` and 24 index files are gone. The projection
kernel moves from `features/agents_projection/` to `features/agents/projection.md`
— it documents `lib/features/agents/projection`, so it belonged inside the
feature that owns it rather than beside it. All 24 feature READMEs under `lib/`
and every inbound link in the bundle were retargeted; the strict validator
resolves every one.

`stale_after` was 2027-01-31 on all 88 concepts: one cliff, no signal. Windows
now come from how fast the subject moves — three months for `agents`, `ai`,
`daily_os_next` and `sync`, twelve for domain models and settled exploratory
work, six for the rest — and the validator reports a concept that has passed its
date.

`settings` and `settings_v2` were both `status: stable`, both described as "the
declarative settings tree", and both explained that the two surfaces cannot
disagree in near-identical prose, while the index gave no clue which to read.
`settings_v2` now owns the tree and the argument for having one; `settings` owns
the shell that renders it, and says so in its first paragraph. The v2 name is
explicitly not a migration in progress, with the three places a new settings page
touches spelled out — verified against `settingsNodeUrls` and
`SettingsLocation.pathPatterns` rather than inferred.

Reserved index.md files carry no frontmatter, so nothing tracks their freshness —
yet they quoted inventories that grow: eleven databases, eight Beamer stacks,
twenty-four logging domains, seven release pipelines, twenty SyncMessage
families. Those counts now live only in sourced concepts. `features/index.md`
also loses its one-item groups, and the vacuous domain bullets ("how these are
stored") say something. The root README finally points at the bundle.
Adds a Mermaid diagram to each concept whose subject has a shape prose cannot
carry, verified against the code rather than the surrounding text: the
JournalEntity union and its Metadata envelope, the linked_entries row, the
projection kernel's permutation invariance, the idle gate's state machine, the
wake prompt's stability bands, dashboard item dispatch, and theming's
arrival-based sync guard. 69 of 88 concepts now carry at least one.

Reading the code to draw them turned up four things the prose had wrong or
missing:

- wake-prompt listed twelve sections; DayAgentContextBuilder renders sixteen. The
  omitted `day_directive` and `day_entries` both sit in the byte-stable prefix,
  and `day_entries` is capped at 32 with the remainder marked — a constraint
  worth knowing before adding to it. (DayAgentPromptTags.all, which does list all
  sixteen, is a registry for neutralizePromptTags, not the render order — it does
  not document the sequence.)
- entry-links said the shape lives in the type column but not that only eight
  columns are queryable. A soft-deleted link cannot be excluded in SQL, and
  TaskDependencyResolver, TaskBlockersController and TaskLinkGroupsController each
  filter deletedAt in Dart because of it.
- dashboards described the chart keys as `survey:$type` "and friends"; two of the
  five carry a second discriminator, and dropping it would render a new
  aggregation against the previous one's retained data.
- user_activity credited SyncTuning.outboxIdleThreshold without its value. It is
  1200 ms; the 1 s constructor default is dead in the app.

Then, because the validator does not parse Mermaid, three diagrams that never
rendered: `;` ends a statement in every diagram type, and a second `:` breaks a
stateDiagram transition label. Both traps are now written down.

The fourth was worse and is now machine-checked: a closing fence with a sentence
welded to it, which CommonMark does not accept as a close, so the rest of that
concept rendered as code. The validator fails on an unclosed fence — confirmed by
reverting the fix and watching CI's check catch it. The link scanner had missed it
because stripCodeSpans is deliberately looser about where a block ends.
AGENTS.md carries nine bullets of mandatory design-system rules and never once
linked the 334 lines of design-system concepts — the same gap as the stale ARB
list, and the reason an agent can follow the token rules without ever seeing the
pipeline they come from. The Implementation-discipline section now opens by
pointing at the concept tree.

The Figma → tokens.json → Dart naming path moves into the concept, where the
pipeline it belongs to is already documented, and AGENTS.md links it. Writing it
down against `generate_tokens.dart` showed the rule is narrower than the
instruction implied: `levelNN` applies only under `background` and `decorative`,
while any other digit-leading name gets a `value` prefix — so a numeric leaf
elsewhere is `value02`, and predicting `level02` there would send you looking for
a token that does not exist. The Figma-inspect workflow hint stays in AGENTS.md,
which is where a workflow step belongs.

The conventions index now cross-references it too: its rules bind every UI change,
so an agent scanning "the rules this repository holds itself to" should not have to
already know the design system is filed as a feature.
…e mermaid in CI

The convention said every key in the template was required and malformed values
failed the build. `resource` and `tags` were not in the validator's required set
at all — two architecture concepts carried no `resource` and validated clean —
and `type` is checked only for non-emptiness, against no allowlist. Rather than
soften the doc, `resource` and `tags` are now required; the two gaps declare
`resource: ../..`, which is the honest answer for a concept whose subject is the
repository. `type` is documented as convention rather than enforcement, since an
allowlist would fight §4.1 and the validator's own `Attested Computation`
support.

Requiring `resource` surfaced a validator bug: a reference landing exactly on the
repository root normalizes to the empty string, and neither `File('')` nor
`Directory('')` exists, so `../..` read as a dangling pointer.

The frontmatter template now annotates each key with how far its check goes,
because presence and correctness are not the same thing, and the rule list gained
the checks it had been missing — the actor convention in `sources[].author`, a
missing `at`, the root-index parse errors, the `computation` path shape. One
entry was not merely missing but wrong: a source that fails to resolve is an
error only when it points *outside* the bundle; a bundle-internal one warns,
because §6.1 permits a pointer to knowledge not written yet.

`stale_after` now fails the build when it passes, per maintainer decision, and
`make okf_check` matches CI. A reminder nothing ever fails on is not a reminder.
The dates are also staggered a week apart per subsystem — 15 review dates instead
of 3 — so re-reads arrive as coherent batches of at most eleven concepts rather
than one 48-concept burst. An unrecognised `--flag` is now rejected instead of
silently ignored, which is how `--warnings-as-error` could report a clean bundle
it had never checked strictly.

Mermaid is validated in CI: `tool/okf/check_mermaid.mjs` parses every block with
mermaid itself under jsdom, wired as `make mermaid_check` and a `mermaid` job.
The Dart validator cannot do this — there is no Dart parser — which is how three
unrenderable diagrams shipped.

Two tests were asserting the wrong thing. The provenance rule's severity *is* the
rule, but three tests checked severity-blind `issues`, so a silent downgrade to a
warning would have passed; and the assertion pinning bundle-internal resources as
warnings had been broadened away. Both are restored, and verified by flipping the
severity back and watching three tests fail.

Also scoped the authority table in the root index: instructions govern how work is
done, code governs what runs, and a descriptive claim that drifts into AGENTS.md
carries less weight than the code it describes — not more, as one ranked list
implied.
… the code

Every one of these was asserted confidently and was wrong:

- `habits` gave the content-width cap as 820 px; `_maxContentWidth` is 1100.
- `knowledge_graph_poc` said it is "not wired into the shipping navigation". Both
  task-detail app bars push `TaskKnowledgeGraphPage`, and the gate in front of it
  is `Provider<bool>((_) => true)` with no flag behind it. It ships to every user
  with a task open.
- `settings` said mobile pushes a branch hub for two pure-navigation branches,
  definitions and advanced, and that Sync has its own landing page. The code
  pushes `SettingsMobileBranchPage` for definitions, advanced *and* sync — the
  class doc says so in its own words — and `navigation.md` already listed three
  hubs, so the bundle contradicted itself.
- `sync/receive-path` pinned a behaviour to "Matrix SDK 7.0.0"; the app is on
  `^8.1.0`.
- The build-runner trap claimed `git status` stays clean. Generated files are
  tracked and not ignored, so the deletions do show up — `git status` is the only
  signal there is, since the build itself succeeds. The claim inverted the one
  thing that saves you, and it lived in two homes; `platform-and-release` now
  links `code-style` instead of repeating it.
- `platform-and-release` said `python-tools-ci.yml` runs on pull requests only.
  It is path-filtered on both pushes and PRs.
- Both `testing` and `platform-and-release` said CI runs tests "in a single
  thread", and drew the teardown discipline from a leak reaching another file.
  `very_good test` defaults to `--concurrency 4` and CI passes no `-j`, so suites
  run four-up in separate processes: a leak reaches later tests *in the same
  file*, which is still the reason for the rule but not the reason given.

Also applies the one-authoritative-home rule to the two places that still broke
it. AGENTS.md's 35 lines of testing rules were a near-verbatim copy of the
testing concept, which covers all of it; they collapse to seven guardrails plus a
link. Its localization bullet had told agents not to trust a list pasted
elsewhere, one line above pasting the register table and the catalog count.

The code-to-concept map opened on a false premise — `lib/services` and
`lib/widgets` both have READMEs — and three rows overstated their coverage.
Rows now say what the concept actually covers, and where it is one seam rather
than a tree, it says so.

Documents the local test policy: run what your change touches, and let CI's
ten-way shard run the rest instead of stalling on it locally.
`sources[].last_modified` was fabricated at scale: 162 of 229 repo-path sources
disagreed with `git log`, most written as "roughly today" when the file had not
been touched in six weeks. All 229 now match history, which is what the
convention had just started mandating.

Corrections, each checked against code:

- `persistence` credited `maintenance.dart` with purging deleted entries.
  `purgeDeleted` is in `database_entity_ops.dart`; maintenance.dart does re-sync
  and whole-database deletion.
- `journal-entity` presented the soft-delete tombstone as permanent. A user-run
  maintenance purge hard-deletes every flagged row and its files, after which the
  device cannot tell "deleted" from "never existed" — so no sync or backup
  invariant may assume the tombstone survives.
- `tasks/relationships` headed a three-row table "Two resolvers". Two resolve
  blockedness; the third only groups links for display.
- `settings`'s runtime topology omitted five root nodes (onboarding, daily-os,
  recording-style, keyboard-shortcuts, speech), invented an Agents → Stats child
  and missed AI → Usage. Regenerated from `buildSettingsTree`.
- `settings_v2` said adding a page touches three places. It touches five, and
  three of the five fail *silently* — an unregistered panel renders
  `DefaultPanel`, a missing label renders the raw node id, a missing URL cannot
  beam. `settingsNodeUrls` is also not universal: `whats-new` is deliberately
  absent.
- Four `lib/` READMEs contradicted their concepts: celebration claimed "haptics
  always fire" when a separate preference silences them, user_activity listed day
  recordings as waiting on the idle gate when Daily OS does not use it, ai_chat
  described a `state/` directory it does not have, and agents attributed the event
  log and compaction to `memory/`, which holds one file about something else.
  `memory-and-compaction` pointed its own `resource` at that directory; it now
  names `projection/`, where the fold actually lives.

Also: the two `draft` concepts had landed in the twelve-month "settled" tier —
a draft is not settled by definition — and the reading order in the root index
never routed through `conventions/`, so nothing told a reader to check the testing
or localization rules before writing code that they govern.

Test policy is now explicit in both homes: run the test files for the source files
you touched, not the whole suite and not a whole feature's suite either — `agents`
alone costs minutes locally, worse in a VM, while CI shards it ten ways for free.
…gets omits

Three coverage gaps, picked because each one can mislead rather than merely
missing detail.

The `private` visibility gate was undocumented anywhere, despite every `JournalDb`
read routing through `_queryWithPrivateFilter`. It is now in `persistence`, with
the two things a reader needs: it is a **read filter, not encryption**, and a new
query that hits the journal tables directly bypasses it silently — nothing obliges
a caller to use it, and a leaked private entry looks like a working query.
`security-and-privacy` points at it rather than restating it, and says plainly that
"private" is a shoulder-surfing affordance, not a security boundary.

`TaskStatus` was named nowhere in the bundle. Its five variants are now listed —
with the finding that **nothing in the code restricts which status follows which**.
That is also why there is deliberately no state diagram: drawing one would invent a
machine the code does not implement, which the diagram rule forbids. Blockedness,
by contrast, is derived from live links at read time and can disagree with the
`blocked` status.

`shared-widgets` described seven of the sixteen groups under `lib/widgets/` as
though the table were the directory listing. It now names the nine it omits, so
absence from the concept is not read as absence of a shared home.
The concept described the 10 ms threshold as if it were the whole mechanism. A
query crossing 200 ms also gets its `EXPLAIN QUERY PLAN` captured and is written
to a separate `super_slow_queries` file — so the first tier says *that* something
is slow and the second says *why*. Anyone debugging should start with the
super-slow file, because it is the only one carrying a plan.
… mermaid gate

All three were introduced or missed by earlier commits on this branch.

**`TaskStatus` has seven variants, not five.** `done` and `rejected` sit at
task.dart:114 and appear in `allTaskStatuses`; I read a truncated line range and
asserted the count from what the window happened to show. The concept now names all
seven, splits live from terminal, and records that the split lives in
`openTaskStatuses` rather than in the union.

**A leak can cross test files on CI.** The previous commit replaced a vague
"single thread" claim with a confident false one: that concurrency 4 means
file-isolated processes, so a leak cannot reach another file. `very_good test`
keeps its **optimizer on by default** and CI does not disable it, so one generated
`.test_optimizer.dart` imports every test file and `package:test` shards *that*
single suite — one isolate per shard, unrelated files sharing it. `test/README.md`
documented this correctly all along; the concept now states the model, notes that
the victim depends on bundle order and that passing locally proves less than it
looks, and defers to `test/README.md` for the Mocktail case.

**`:=` is not a Mermaid trap.** Bisecting against the real parser: `A --> B: id :=
joinId` parses fine, and `;` alone in a state label parses too. What broke the
three diagrams was `;` *whose remainder is not a valid statement*. The
documentation now carries the mechanism and, more importantly, the quiet failure
mode it had missed — in a `stateDiagram`, `x; y` silently renders **a stray state
node named `y`** and the parse check passes.

The gate had two false-green paths, both now closed:

- `AGENTS.md` told agents to run `make okf_check`, while Mermaid parsing sat in a
  separate target — so the check most likely to catch a bad diagram was the one
  nobody ran. `make knowledge_check` is now the single target, and every
  instruction points at it.
- `check_mermaid.mjs` matched only an exact triple-backtick fence, so `~~~mermaid`
  and longer backtick runs were skipped **in silence** while the CI step claimed to
  parse every block. It now handles all CommonMark fence forms, and only the
  outermost fence counts — a mermaid example inside a ````markdown block is
  documentation, not a diagram. Verified against fixtures for each form.

Also drops the trailing blank line `git diff --check` flagged in the workflow.
…antom nodes

The privacy claim was the worst of these. "Every read passes a private-visibility
gate" is wrong by an order of magnitude: `_queryWithPrivateFilter` is **opt-in**,
with thirteen call sites across five files, and the reads that skip it include
`journalEntityById` — the one behind every detail page — plus
`getDayAudioEntries`, `journalAudioByRecordingSessionId` and
`countAllJournalEntries`. Four mixins never call it and
`_JournalDbTaskQueriesBuilders` delegates the decision to its callers. The section
also contradicted itself, saying a new query "bypasses the gate silently" two
paragraphs after claiming every read passes it. It now says which reads filter,
states that by-id reads deliberately do not, and `security-and-privacy` calls
"private" a partial read filter that a deep link defeats.

The mermaid gate documented a quiet failure it could not see, and the bundle
contained two instances of it. `memory-and-compaction` and `detail-and-saving`
each had a `;` in an unquoted state label; measured against the pinned mermaid,
one of them renders **six nodes instead of one** — `Capturing`, `;`, `append`,
`link;`, `retract`, `sources`. Both labels are fixed, and the checker now inspects
the built diagram and fails any node id containing `;`, since nothing legitimate
produces one. The script header also still asserted the `:=` trap that the
convention retracted in the same commit.

`check_mermaid.mjs` now has thirteen tests — fence forms, nesting, unclosed
fences, the semicolon split, and the safe cases (quoted labels, note bodies) —
wired into `npm test`, `make mermaid_check` and CI. The previous commit claimed
"verified against fixtures" while committing none, which is the exact
unverifiable-check problem this tool exists to prevent.

Content corrections, each checked against code:

- `TaskStatus.blocked` and `.onHold` require a `reason`; "every variant carries the
  same fields" was wrong. The live/terminal split is duplicated across six
  independent sites with no shared constant, now tabulated.
- Two of sixteen diagram nodes named classes that do not exist: `JournalEvent` and
  `QuantitativeEntry`, not `Event` and `Quantitative`.
- "A soft-deleted link cannot be excluded in SQL" overstated it — it cannot be
  excluded by a *column* predicate, and this codebase does use `json_extract`
  elsewhere. The Dart-side wording also read inverted: the readers keep
  `deletedAt == null` rows.
- Adding a settings page touches six places, not five: `pathPatterns` and
  `buildPages` are separate silently-failing sites, as `/settings/maintenance`
  proved by shipping a pattern with no page. And `whats-new` is absent from
  `settingsNodeUrls` *not* because it is an in-pane panel — `kSettingsPanels` has
  no entry for it at all, so desktop would fall to `DefaultPanel`. Three AI tab
  leaves are absent by accident.
- `manual.yml` has four triggers, not "pull requests only"; the ten-way shard
  belongs to the GitHub lane, not Buildkite, which runs a bare `flutter test`.
- AGENTS.md pointed at three headings a previous commit deleted; three
  TEST_REVIEW docs cited them too.
- The Matrix zero-cache-limit workaround was established on 7.0.0 and never
  re-verified; the doc no longer implies 8.1.0 confirmation, and names the four
  code comments that still say 7.0.0.
- Smaller: an invented `stale_after` replaced with the batch its siblings use, a
  code-map row that promised prose which does not exist, a duplicated `ui/` I
  introduced in the ai_chat README, `day_entries` described as ahead of everything
  when five sections precede it, and two conditional settings nodes missing their
  gating annotations.
…d gaps

Content the bundle had been missing across three reviews:

- **Category-default agent assignment has five paths, not four**, and the shared
  `assignCategoryDefaultTaskAgent` is not "every UI creation path" — the day
  agent's capture tools call it too.
- **The agent entity and link lists were incomplete**: `DayDirectiveEntity`,
  `DayStatusEventEntity` and `WeekRollupEntity` were missing, as were four link
  kinds including `agent_event` and the `message_prev` chain the fold walks. All
  eighteen kinds are now grouped by what they connect.
- **`DerivedAgentState` and `ShadowProjection` had zero mentions bundle-wide**
  despite being 543 lines and the composite production actually reads. The
  concept now says the kernel is the small part, that the composite extends the
  convergence property to watermarks and slots, and that the shadow comparison
  never drives a production read.
- **The logging sink diagram undercounted the files on disk.** Every error is
  mirrored in full to `error-<date>.log`, force-flushed; and the slow-query
  section still described 10 ms as the whole mechanism after `persistence` had
  documented both tiers.
- **The `UpdateNotifications` token vocabulary** — the last round-one gap with no
  home — is now in `persistence`, all 24 tokens grouped, with the finding that
  matters: `PROPAGATED::` is not cosmetic. A propagated match defers an agent wake
  to the next morning while a direct match keeps the fast throttle, so a consumer
  that only cares about reactivity **must match both forms** or silently miss
  fan-out emissions.

Validator gaps where the convention promised more than the code enforced:

- `resource: ""` and `tags: []` validated clean — the required-key check stopped at
  presence, and both reference checks skip an empty target. Both now fail, with
  tests.
- Nothing warned before a `stale_after` arrived, so the first signal would have
  been a red push on one morning for a whole subsystem at once. It now warns for
  fourteen days beforehand.
- `--help` exited 1, a side effect of rejecting unknown flags. It prints usage.
- The Attested-Computation warnings were asserted severity-blind, so an accidental
  promotion to error would have passed; they are the only checks deliberately left
  advisory, and that is now pinned.

Documentation corrections, all cases of claiming more than is true:
`resource` "must resolve in the repo" (only if it leaves the bundle), `../..` as
generic repo-root advice (correct only one directory deep), `type` described three
different ways in one document, the missing `verified[].at` and top-level-`resource`
rules, and the "inherits its directory's date" rule that does not hold for the 23
flat features — those are batched alphabetically, which the doc now says.

The mermaid gate's scope is now stated rather than implied: it covers `knowledge/`,
and pointing it at `docs/` reports 14 broken diagrams (8 parse failures, 5
phantom-node splits) across ADRs and implementation plans, which are outside this
bundle's contract and not fixed here.
…ctice

`AGENTS.md` and `CONTRIBUTING.md` each said "screenshots/GIFs for UI changes" and
nothing else. Meanwhile the sibling `lotti-docs` repo holds ~1,100 images across
~37 topics under `pr-screenshots/`, and *nothing* documented it — not this repo,
not `lotti-docs`'s own README, which covers only the generated manual catalog.

The new convention records what the practice actually is:

- **Images never live in this repository.** `assets/` is what the app ships;
  everything captured for humans goes to `lotti-docs` and is referenced by raw
  URL, which is why README and GETTING_STARTED embed remote images. The only
  enforcement is `.gitignore` ignoring any `screenshots` directory — which happens
  to be the harness's default output — so an image saved elsewhere will be
  committed if you add it.
- **Three destinations, three lifecycles**: `manual/screenshots/` is generated by
  `make manual_screenshots` and never hand-edited, `images/<version>/` is written
  once per release, `pr-screenshots/<topic>/` is review evidence written by hand.
- **A UI pull request carries before *and* after**, per surface and variant, with
  matching filenames so a reviewer can flip between them. Capture `before/` from
  the base commit first — reconstructing it means stashing the work, which is the
  step people skip, and is why the pairs go missing.
- **An outside contributor cannot push to `lotti-docs`**, so they attach images to
  the PR through GitHub instead. Both are acceptable evidence; committing to this
  repo or omitting the before is not. CONTRIBUTING says this in the contributor's
  terms rather than pointing at a workflow they have no access to.

The concept is honest about the tree it describes: 24 topics have an `after/` and
only 14 a `before/`, some put files at the topic root, and one-off subdirectory
names appear where a pair was not the shape of the question. That is the convention
arriving after the practice, not licence to skip the pair.
… not code

`CONTRIBUTING.md` said "submit pull requests for fixes and features" and invited
drive-by test-coverage work. README went further, explicitly welcoming "small,
focused PRs that fix a clear bug ... without prior discussion" and soliciting a
whole Python image-generation service. None of that reflects the policy: code
contributions are not accepted, and the two things that help are issue reports and
translations.

Both files now say that. The reasons are stated once, briefly, and without
implying anything about a given contributor's work: review capacity is the binding
limit, the app holds personal data on people's own devices, and AI-generated code
arrives faster than it can be reviewed carefully. An unsolicited code PR is closed
unmerged — said here rather than after someone has written it.

`CONTRIBUTING.md` is kept rather than folded into the README because GitHub
surfaces it in the pull-request form. It is the only document placed in front of
someone at the moment they are about to open a PR, which is exactly where this
message has to land. It is now short, and the README carries a condensed version
plus a link rather than a second, drifting copy of the policy.

Translations are treated as the real contribution path they are: which catalogs,
the informal register with Romanian as the exception, never editing the generated
Dart, `make l10n` and `make sort_arb_files`, and the real-name requirement for
AI-assisted work — with the detail linked to `conventions/localization.md` rather
than duplicated. Bug reports get what actually makes them useful, including that
nothing reaches us unless the reporter sends it, since there is no telemetry.

Also removed the stale roadmap ("Current Focus Areas", "Future Improvements") that
had drifted, and fixed a cross-reference in README that pointed at the
contribution call this change removes.
…defects

Each of the three was written confidently while documenting something else.

**A notification payload is not token-only.** `affectedIds` seeds the set with the
written entity's **own id**, adds linked ids (a habit completion adds its
`habitId`), *then* adds a static type token — and task-agent notifications carry
`agentId` and `taskId` the same way. The vocabulary table also omitted the dynamic
`PROJECT_ENTITY_UPDATE:<projectId>` keys. It now describes five kinds of routing
key across three categories — ids, static tokens, and computed/prefixed ones — and
keeps only the part that was true: no entity *data* travels, so a listener always
re-reads. Two of the five kinds are built at emit time, which is exactly what a
consumer must not assume away.

**`DerivedAgentState` drives no production read.** Its own source says so —
"Drives no production read; B6 flips reads onto this fold" — and it has no external
call sites. Calling it "the composite production reads go through" inverted the
one fact that matters about it: reads still come from the mutable cache, and the
fold's job today is to make a drifted cache *detectable* via `ShadowProjection`,
not to serve reads.

**An error reaches two to four files, not two.** Beyond the routed file and the
full `error-<date>.log` mirror, `DomainLogger.error` also writes
`error-safe-<date>.log` — recording only the error's **runtime type**, never the
raw string, so it can be shared without leaking user content — and, for any domain
that does not route to the sync file, a per-domain `<domain>-<date>.log`. The
PII-safe sink is the operationally important one and was missing entirely.

Two defects in the gate added yesterday:

- **The tests leaked a temp directory per invocation** — 234 `/tmp/mermaid-gate-*`
  had accumulated — and inherited the checker's stderr, so expected negative cases
  printed prominent `FAIL` banners into a *passing* `make knowledge_check`. A green
  run that looks broken trains people to ignore it. Directories are removed in
  `finally` and stderr is piped.
- **Both fence scanners accepted four-space-indented fences.** CommonMark allows at
  most three; at four it is an indented code block, which is how a document *shows*
  a mermaid fence as an example. Trimming the indent away made those literals open
  and close real blocks — so a doc demonstrating the syntax could be parsed as a
  diagram, or rejected as unclosed. Both now preserve the indent and accept 0–3
  spaces, on the opener and the closer, with tests for the literal, the three-space
  fence that is still real, and an indented closing fence.
…directions

The pattern in the review is fair: new prose about a subsystem kept asserting the
opposite of what the code says. Two instances, plus the source comment that seeded
one of them.

**`PROPAGATED::` — inverted.** I wrote that a consumer must match both forms or
silently miss fan-out emissions. The opposite is true: every emitter puts the bare
token *and* the prefixed one in the same set, and the bare one is kept deliberately
so legacy consumers keep refreshing — `project_repository.dart` says so in a
comment. So matching the bare token alone is correct and complete. I verified this
across all four emitters rather than the one cited: `project_repository`,
`persistence_updates` and `skill_inference_runner` all emit both;
`wake_batch_router` is the consumer that tells them apart.

That consumer's behaviour was overstated too. The deferral is **opt-in per
subscription** — `WakeOrchestrator` defaults `deferPropagatedMatches` to true, and
task agents and the sync event handlers pass false. And the payload table labelled
twelve tokens as "one per variant" when there are sixteen variants: `checklist`,
`checklistItem`, `measurement` and `quantitative` have none of their own.

**The privacy narrowing overshot in both directions.** "Most query mixins never
consult the gate" is false — nine of the ten query-bearing mixins gate on private,
through *three* mechanisms I had collapsed into one: `_queryWithPrivateFilter`,
`privateStatuses` passed by the caller, and raw SQL reading `config_flags` directly
in `insights_queries`. Only `_JournalDbEntityOps` ignores it, and that is
maintenance rather than a read path. "By-id reads ignore the flag entirely" is also
false: `getDayPlanById`, `getLabelDefinitionById` and the id-*batch* journal reads
all filter. The true statement is narrower — single-entity journal reads
(`journalEntityById`, `getDayAudioEntries`,
`journalAudioByRecordingSessionId`) and `countAllJournalEntries`.

I had also read `getJournalEntitiesForIds` as unfiltered from a grep window too
small to show the call. It filters.

**Fixed the comment that seeded it.** `database_config_flags.dart` still claimed
the gate is what "every query mixin routes through" — the sentence the first
version of this section trusted. It now names all three mechanisms and says
single-entity reads do not filter, so the code and the concept agree.

`ShadowProjection` is not a symbol either: the pieces are
`compareShadowProjection`, `ShadowProjectionReport` and `ShadowProjectionStatus`.
Rebasing onto #3602 moved the last-commit date of `tokens.json`, the
design-system theme directory and `database_config_flags.dart` — the last of
those because this branch edited its comment. Two entries inherited from main
were also a day ahead of the files they cite. All 238 repo-path sources match
`git log -1` again.
@gemini-code-assist

Copy link
Copy Markdown
Contributor

Caution

The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased.

@coderabbitai

coderabbitai Bot commented Jul 26, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

This change adds Mermaid parsing and rendering checks to knowledge validation, strengthens OKF metadata and fence validation, updates CI and Makefile targets, reorganizes knowledge documentation, refreshes metadata and links, and revises repository contribution and testing guidance.

Changes

Knowledge validation and documentation

Layer / File(s) Summary
Validator and Mermaid gate
.github/workflows/okf-validate.yml, Makefile, tool/okf/*, test/tool/okf/*
Adds Node.js Mermaid parsing/rendering checks, stricter OKF errors, fenced-block validation, deterministic stale-date testing, unknown-flag rejection, and expanded validator tests.
Repository workflow guidance
AGENTS.md, CONTRIBUTING.md, README.md, knowledge/conventions/*
Updates testing, localization, screenshots, design-system, contribution, and knowledge-validation instructions.
Knowledge bundle restructuring
knowledge/index.md, knowledge/log.md, knowledge/architecture/*, knowledge/domain/*, knowledge/features/*
Reorganizes indexes, consolidates feature documentation, corrects links and claims, adds diagrams, and refreshes frontmatter/source metadata.
Feature documentation references
lib/features/*/README.md, lib/database/database_config_flags.dart, test/features/**/TEST_REVIEW*
Points feature READMEs to consolidated Markdown knowledge pages and updates related documentation references.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant CI
  participant Makefile
  participant OKFValidator
  participant MermaidChecker
  participant KnowledgeBundle
  CI->>Makefile: run knowledge_check
  Makefile->>OKFValidator: run okf_check
  Makefile->>MermaidChecker: run npm test and npm run check
  OKFValidator->>KnowledgeBundle: validate metadata and fenced blocks
  MermaidChecker->>KnowledgeBundle: parse and render Mermaid blocks
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: enforcing knowledge bundle rules and correcting documentation claims.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch docs/knowledge-onboarding-fixes

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@codecov

codecov Bot commented Jul 26, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 99.15%. Comparing base (78aaad9) to head (1b0d5da).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #3603   +/-   ##
=======================================
  Coverage   99.15%   99.15%           
=======================================
  Files        1785     1785           
  Lines      131174   131174           
=======================================
  Hits       130062   130062           
  Misses       1112     1112           
Flag Coverage Δ
glados 14.08% <ø> (ø)
standard 98.90% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@matthiasn
matthiasn merged commit 351ac3b into main Jul 26, 2026
31 of 33 checks passed
@matthiasn
matthiasn deleted the docs/knowledge-onboarding-fixes branch July 26, 2026 13:54

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
knowledge/features/agents/task-agents.md (1)

84-88: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Correct the non-helper path count.

This section lists four non-helper paths, not three. Update both references so future category-default changes are applied to all four paths.

Proposed wording
-The three non-helper paths deliberately do not route through
+The four non-helper paths deliberately do not route through
...
-Any new category default has to be added to all three.
+Any new category default has to be added to all four.

As per coding guidelines, knowledge concepts must remain accurate architectural maps.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@knowledge/features/agents/task-agents.md` around lines 84 - 88, Update the
documentation section describing category default handling to state that there
are four non-helper paths rather than three, and update the corresponding
instruction so new category defaults are added to all four paths. Preserve the
existing explanation about avoiding assignCategoryDefaultTaskAgent and its
setupOrigin behavior.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@knowledge/conventions/knowledge-bundle.md`:
- Around line 214-216: Update the actor convention reference in the
knowledge-bundle documentation to use verified.by instead of verified[].by,
matching the documented mapping shape while leaving the generated.by and
sources[].author references unchanged.

In `@knowledge/features/daily_os_next/wake-prompt.md`:
- Around line 106-112: Clarify the day_entries contract consistently across the
document: distinguish the bounded newest-32 recording receipt index from any
metadata loaded for every persisted day recording, or revise the bounded-index
description to match the implementation. Update the related later section so
both descriptions define the same data and retention behavior.

In `@knowledge/features/sync/receive-path.md`:
- Around line 91-96: Update the zero cache limit heading in receive-path.md to
scope the requirement to the Matrix SDK 7.0.0 finding, rather than presenting it
as a current 8.1.0 requirement. Preserve the note that the workaround remains
load-bearing until it is re-verified against the pinned version.

In `@knowledge/features/tasks/data-model.md`:
- Around line 42-53: Correct the duplicated-site count in the documentation to
“Seven places,” or explicitly clarify that the grouped database entries
represent one conceptual site while preserving the accurate list of affected
files and symbols.

In `@knowledge/log.md`:
- Around line 62-64: Update the TaskStatus reference in this bullet to state
seven variants, matching the corrected count documented near Lines 39–44, rather
than claiming it has five states.
- Around line 31-34: Update the privacy discussion in knowledge/log.md to narrow
both claims: state that only some browsing queries opt into the private
visibility gate, while single-entity reads such as journalEntityById bypass it;
remove or revise any wording that says every JournalDb read routes through the
gate or that all by-id reads never filter.
- Around line 74-78: Update the documentation in knowledge/log.md to state that
concepts with expired stale_after dates are recorded as errors and fail CI,
while only the pre-expiry warning window remains a warning. Keep the distinction
from unwritten knowledge links clear and align the summary with the validator
contract described earlier in the document.

---

Outside diff comments:
In `@knowledge/features/agents/task-agents.md`:
- Around line 84-88: Update the documentation section describing category
default handling to state that there are four non-helper paths rather than
three, and update the corresponding instruction so new category defaults are
added to all four paths. Preserve the existing explanation about avoiding
assignCategoryDefaultTaskAgent and its setupOrigin behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 0519505d-068e-4cde-ae73-6157bbdf6e65

📥 Commits

Reviewing files that changed from the base of the PR and between 78aaad9 and 1b0d5da.

⛔ Files ignored due to path filters (1)
  • tool/okf/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (165)
  • .github/workflows/okf-validate.yml
  • AGENTS.md
  • CONTRIBUTING.md
  • Makefile
  • README.md
  • knowledge/architecture/bootstrap-and-di.md
  • knowledge/architecture/index.md
  • knowledge/architecture/logging-and-diagnostics.md
  • knowledge/architecture/navigation.md
  • knowledge/architecture/overview.md
  • knowledge/architecture/persistence.md
  • knowledge/architecture/platform-and-release.md
  • knowledge/architecture/security-and-privacy.md
  • knowledge/architecture/shared-widgets.md
  • knowledge/conventions/code-style.md
  • knowledge/conventions/index.md
  • knowledge/conventions/knowledge-bundle.md
  • knowledge/conventions/localization.md
  • knowledge/conventions/screenshots.md
  • knowledge/conventions/testing.md
  • knowledge/domain/entity-definitions.md
  • knowledge/domain/entry-links.md
  • knowledge/domain/index.md
  • knowledge/domain/journal-entity.md
  • knowledge/features/agents/index.md
  • knowledge/features/agents/memory-and-compaction.md
  • knowledge/features/agents/overview.md
  • knowledge/features/agents/persistence-and-sync.md
  • knowledge/features/agents/project-and-event-agents.md
  • knowledge/features/agents/projection.md
  • knowledge/features/agents/task-agents.md
  • knowledge/features/agents/templates-souls-evolution.md
  • knowledge/features/agents/ui-surfaces.md
  • knowledge/features/agents/wake-orchestration.md
  • knowledge/features/agents_projection/index.md
  • knowledge/features/agents_projection/overview.md
  • knowledge/features/ai/activity-visualization.md
  • knowledge/features/ai/attribution.md
  • knowledge/features/ai/conversations-and-tools.md
  • knowledge/features/ai/embeddings-and-search.md
  • knowledge/features/ai/execution-paths.md
  • knowledge/features/ai/model-evaluation.md
  • knowledge/features/ai/overview.md
  • knowledge/features/ai/profile-resolution.md
  • knowledge/features/ai/provider-routing.md
  • knowledge/features/ai/seeding-and-lifecycle.md
  • knowledge/features/ai/settings-ui.md
  • knowledge/features/ai_chat.md
  • knowledge/features/ai_chat/index.md
  • knowledge/features/ai_consumption.md
  • knowledge/features/ai_consumption/index.md
  • knowledge/features/categories.md
  • knowledge/features/categories/index.md
  • knowledge/features/character.md
  • knowledge/features/character/index.md
  • knowledge/features/checklist.md
  • knowledge/features/checklist/index.md
  • knowledge/features/daily_os_next/agent-identities.md
  • knowledge/features/daily_os_next/capture-and-planning.md
  • knowledge/features/daily_os_next/coordination-protocol.md
  • knowledge/features/daily_os_next/dependency-aware-planning.md
  • knowledge/features/daily_os_next/evaluation.md
  • knowledge/features/daily_os_next/overview.md
  • knowledge/features/daily_os_next/processing-outbox.md
  • knowledge/features/daily_os_next/ui-surfaces.md
  • knowledge/features/daily_os_next/wake-prompt.md
  • knowledge/features/dashboards.md
  • knowledge/features/dashboards/index.md
  • knowledge/features/design_system/celebration.md
  • knowledge/features/design_system/component-contracts.md
  • knowledge/features/design_system/tokens-and-theming.md
  • knowledge/features/events.md
  • knowledge/features/events/index.md
  • knowledge/features/habits.md
  • knowledge/features/habits/index.md
  • knowledge/features/index.md
  • knowledge/features/insights.md
  • knowledge/features/insights/index.md
  • knowledge/features/journal/browse-and-linking.md
  • knowledge/features/journal/detail-and-saving.md
  • knowledge/features/journal/overview.md
  • knowledge/features/keyboard.md
  • knowledge/features/keyboard/index.md
  • knowledge/features/knowledge_graph_poc.md
  • knowledge/features/knowledge_graph_poc/index.md
  • knowledge/features/labels.md
  • knowledge/features/labels/index.md
  • knowledge/features/notifications.md
  • knowledge/features/notifications/index.md
  • knowledge/features/onboarding.md
  • knowledge/features/onboarding/index.md
  • knowledge/features/projects.md
  • knowledge/features/projects/index.md
  • knowledge/features/ratings.md
  • knowledge/features/ratings/index.md
  • knowledge/features/settings.md
  • knowledge/features/settings/index.md
  • knowledge/features/settings_v2.md
  • knowledge/features/settings_v2/index.md
  • knowledge/features/settings_v2/overview.md
  • knowledge/features/speech/overview.md
  • knowledge/features/speech/recording-ui.md
  • knowledge/features/surveys.md
  • knowledge/features/surveys/index.md
  • knowledge/features/sync/index.md
  • knowledge/features/sync/message-model.md
  • knowledge/features/sync/node-profiles-and-auto-trigger.md
  • knowledge/features/sync/overview.md
  • knowledge/features/sync/receive-path.md
  • knowledge/features/sync/send-path.md
  • knowledge/features/sync/sequence-and-backfill.md
  • knowledge/features/sync/vector-clocks-and-conflicts.md
  • knowledge/features/tasks/checklists.md
  • knowledge/features/tasks/data-model.md
  • knowledge/features/tasks/detail-composition.md
  • knowledge/features/tasks/filtering.md
  • knowledge/features/tasks/index.md
  • knowledge/features/tasks/overview.md
  • knowledge/features/tasks/relationships.md
  • knowledge/features/theming.md
  • knowledge/features/theming/index.md
  • knowledge/features/tts.md
  • knowledge/features/tts/index.md
  • knowledge/features/user_activity.md
  • knowledge/features/user_activity/index.md
  • knowledge/features/whats_new.md
  • knowledge/features/whats_new/index.md
  • knowledge/index.md
  • knowledge/log.md
  • lib/database/database_config_flags.dart
  • lib/features/agents/README.md
  • lib/features/agents/projection/README.md
  • lib/features/ai_chat/README.md
  • lib/features/ai_consumption/README.md
  • lib/features/categories/README.md
  • lib/features/character/README.md
  • lib/features/checklist/README.md
  • lib/features/dashboards/README.md
  • lib/features/design_system/components/celebration/README.md
  • lib/features/events/README.md
  • lib/features/habits/README.md
  • lib/features/insights/README.md
  • lib/features/keyboard/README.md
  • lib/features/knowledge_graph_poc/README.md
  • lib/features/labels/README.md
  • lib/features/notifications/README.md
  • lib/features/onboarding/README.md
  • lib/features/projects/README.md
  • lib/features/ratings/README.md
  • lib/features/settings/README.md
  • lib/features/settings_v2/README.md
  • lib/features/surveys/README.md
  • lib/features/theming/README.md
  • lib/features/tts/README.md
  • lib/features/user_activity/README.md
  • lib/features/whats_new/README.md
  • test/features/ai/database/TEST_REVIEW.md
  • test/features/journal/state/TEST_REVIEW.md
  • test/features/sync/matrix/TEST_REVIEW.part2.md
  • test/tool/okf/okf_validator_test.dart
  • tool/okf/check_mermaid.mjs
  • tool/okf/check_mermaid_test.mjs
  • tool/okf/okf_validator.dart
  • tool/okf/package.json
  • tool/okf/validate.dart
💤 Files with no reviewable changes (26)
  • knowledge/features/agents_projection/index.md
  • knowledge/features/theming/index.md
  • knowledge/features/settings/index.md
  • knowledge/features/projects/index.md
  • knowledge/features/checklist/index.md
  • knowledge/features/agents_projection/overview.md
  • knowledge/features/knowledge_graph_poc/index.md
  • knowledge/features/labels/index.md
  • knowledge/features/notifications/index.md
  • knowledge/features/keyboard/index.md
  • knowledge/features/user_activity/index.md
  • knowledge/features/ai_consumption/index.md
  • knowledge/features/ai_chat/index.md
  • knowledge/features/surveys/index.md
  • knowledge/features/categories/index.md
  • knowledge/features/settings_v2/overview.md
  • knowledge/features/character/index.md
  • knowledge/features/whats_new/index.md
  • knowledge/features/tts/index.md
  • knowledge/features/insights/index.md
  • knowledge/features/dashboards/index.md
  • knowledge/features/onboarding/index.md
  • knowledge/features/ratings/index.md
  • knowledge/features/events/index.md
  • knowledge/features/habits/index.md
  • knowledge/features/settings_v2/index.md

Comment on lines +214 to +216
- An actor outside the `<producer>/<version>` / `human:<id>` / `process:<id>`
convention — in `generated.by`, in `verified[].by`, or in the optional
`sources[].author`.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

Use the correct verified shape in the actor rule.

The document defines verified as a mapping (verified: { by, at }), so verified[].by is misleading and may cause authors to create an invalid list. Use verified.by here.

Proposed correction
-  convention — in `generated.by`, in `verified[].by`, or in the optional
+  convention — in `generated.by`, in `verified.by`, or in the optional
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- An actor outside the `<producer>/<version>` / `human:<id>` / `process:<id>`
convention — in `generated.by`, in `verified[].by`, or in the optional
`sources[].author`.
- An actor outside the `<producer>/<version>` / `human:<id>` / `process:<id>`
convention — in `generated.by`, in `verified.by`, or in the optional
`sources[].author`.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@knowledge/conventions/knowledge-bundle.md` around lines 214 - 216, Update the
actor convention reference in the knowledge-bundle documentation to use
verified.by instead of verified[].by, matching the documented mapping shape
while leaving the generated.by and sources[].author references unchanged.

Comment on lines +106 to +112
**`day_entries` is a bounded index, not a log.** It carries recording receipts so
a later wake can recover a completed offline check-in immediately, capped at the
newest 32 with the omitted count rendered explicitly rather than silently. It
closes the byte-stable prefix — five sections precede it, twelve follow — so a
heavy capture day must not be allowed to inflate it. Anything that grows this section pushes the whole
per-wake band out of cache.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Make day_entries semantics consistent.

These lines define day_entries as capped to the newest 32 recordings, but the later section at Lines 246-249 says metadata for every persisted day recording is loaded into <day_entries>. Clarify whether all-recording metadata is separate from the bounded index, or update one description to match the implementation.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@knowledge/features/daily_os_next/wake-prompt.md` around lines 106 - 112,
Clarify the day_entries contract consistently across the document: distinguish
the bounded newest-32 recording receipt index from any metadata loaded for every
persisted day recording, or revise the bounded-index description to match the
implementation. Update the related later section so both descriptions define the
same data and retention behavior.

Comment on lines +91 to +96
**The zero cache limit is required by the Matrix SDK.** This was established
against **7.0.0 and has not been re-verified since**; `pubspec.yaml` now pins
`matrix: ^8.1.0`, and four in-code comments still name 7.0.0
(`bootstrap_forward_strategy.dart`, `bootstrap_backward_strategy.dart`, and twice
in `queue_pipeline_coordinator.dart`). Treat the workaround as load-bearing until
someone re-checks it on 8.x — not as a fact about the pinned version. Without it,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

rg -n '^\s*matrix:' pubspec.yaml pubspec.lock

Repository: matthiasn/lotti

Length of output: 214


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "## pubspec.yaml matrix line"
sed -n '88,94p' pubspec.yaml

echo
echo "## pubspec.lock matrix entry"
sed -n '1764,1782p' pubspec.lock

echo
echo "## knowledge excerpt"
sed -n '80,105p' knowledge/features/sync/receive-path.md

echo
echo "## related comment search"
rg -n '7\.0\.0|zero cache limit|cache limit|matrix:' bootstrap_forward_strategy.dart bootstrap_backward_strategy.dart queue_pipeline_coordinator.dart knowledge/features/sync/receive-path.md

Repository: matthiasn/lotti

Length of output: 3025


Keep the zero-cache-limit note scoped to 7.0.0 until it’s rechecked on 8.1.0.

pubspec.lock resolves matrix to 8.1.0, but the heading still asserts this as the current Matrix SDK requirement. Reword it to label the finding as from 7.0.0, or update it to the resolved 8.1.0 version after rechecking.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@knowledge/features/sync/receive-path.md` around lines 91 - 96, Update the
zero cache limit heading in receive-path.md to scope the requirement to the
Matrix SDK 7.0.0 finding, rather than presenting it as a current 8.1.0
requirement. Preserve the note that the workaround remains load-bearing until it
is re-verified against the pinned version.

Comment on lines +42 to +53
**The live/terminal split is not in the union at all, and it is duplicated.** Six
places re-state "DONE and REJECTED are the closed ones" independently:

| Site | Form |
|------|------|
| `tasks/ui/utils.dart` `openTaskStatuses` | the five live labels — what the linking UI filters on |
| `day_agent_capture_helpers.dart` `isClosedTask` / `closedTaskStatuses` | `{'DONE', 'REJECTED'}` |
| `agents/tools/task_status_handler.dart` `terminalStatuses` | `{'DONE', 'REJECTED'}` |
| `database.dart`, `database_task_due_queries.dart`, `database_migration.dart`, `database.drift` | `AND task_status NOT IN ('DONE', 'REJECTED')` in raw SQL |

Adding an eighth status means finding every one of them. There is no shared
constant to change.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Correct the duplicated-site count.

The table names seven distinct files/sites, not six. Either change “Six places” to “Seven places” or explicitly describe the grouped database row as one conceptual site.

As per coding guidelines, knowledge concepts must remain accurate architectural maps.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@knowledge/features/tasks/data-model.md` around lines 42 - 53, Correct the
duplicated-site count in the documentation to “Seven places,” or explicitly
clarify that the grouped database entries represent one conceptual site while
preserving the accurate list of affected files and symbols.

Source: Coding guidelines

Comment thread knowledge/log.md
Comment on lines +31 to +34
* **Fix**: Narrowed the privacy claim that mattered most: the `private` gate is
**opt-in and most reads skip it** — thirteen call sites in five files, and
by-id reads including `journalEntityById` never filter. "Every read passes a
private-visibility gate" was wrong by an order of magnitude.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Keep the privacy-gate exception narrow.

“By-id reads … never filter” and “every JournalDb read routes through” overstate the behavior. lib/database/database_config_flags.dart Lines 6-12 explicitly says only some browsing queries gate on private, while single-entity reads such as journalEntityById bypass filtering. Rewrite both passages to describe that narrower scope.

Also applies to: 60-62

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@knowledge/log.md` around lines 31 - 34, Update the privacy discussion in
knowledge/log.md to narrow both claims: state that only some browsing queries
opt into the private visibility gate, while single-entity reads such as
journalEntityById bypass it; remove or revise any wording that says every
JournalDb read routes through the gate or that all by-id reads never filter.

Comment thread knowledge/log.md
Comment on lines +62 to +64
a protection), `TaskStatus`'s five states and the fact that *nothing* constrains
their transitions, and which nine of `lib/widgets/`'s sixteen groups the
shared-widgets concept does not cover.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Correct the obsolete TaskStatus count.

This bullet says TaskStatus has five states, but the same update log records the corrected count as seven variants at Lines 39-44. Update this entry or explicitly label “five states” as the superseded claim.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@knowledge/log.md` around lines 62 - 64, Update the TaskStatus reference in
this bullet to state seven variants, matching the corrected count documented
near Lines 39–44, rather than claiming it has five states.

Comment thread knowledge/log.md
Comment on lines +74 to +78
* **Update**: Raised the house-rule metadata checks from warnings to errors, so
a concept missing a description, a freshness date or code provenance now fails
CI rather than being reported and ignored. What stays a warning is what OKF is
deliberately permissive about — a link to knowledge not written yet — plus a
concept whose `stale_after` has passed, which is now reported.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Record expired stale_after dates as errors.

This says an expired concept remains a warning, contradicting Lines 27-30 and the PR’s validator contract. Only the pre-expiry window should warn; an expired concept must fail CI.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@knowledge/log.md` around lines 74 - 78, Update the documentation in
knowledge/log.md to state that concepts with expired stale_after dates are
recorded as errors and fail CI, while only the pre-expiry warning window remains
a warning. Keep the distinction from unwritten knowledge links clear and align
the summary with the validator contract described earlier in the document.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1b0d5da507

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

// indented by at most **three** spaces. At four it is an indented code block — a
// literal example of a fence, not a fence — so trimming the indent away made a
// documented mermaid snippet indistinguishable from a real diagram.
const FENCE = /^( {0,3})(`{3,}|~{3,})\s*(\S*)/;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Parse Mermaid fences inside Markdown containers

When a concept nests a Mermaid fence in a block quote such as > ~~~mermaid, or in a sufficiently indented list item, CommonMark strips the container prefix before recognizing the fence, but this regex accepts only zero to three literal spaces. The new CI checker therefore reports zero blocks for that content and lets malformed diagrams pass, despite knowledge_check promising to parse every Mermaid diagram; account for Markdown container prefixes before matching fences.

AGENTS.md reference: AGENTS.md:L113-L113

Useful? React with 👍 / 👎.

/// Whether `line` closes a block opened by `opener`: indented at most three
/// spaces, same delimiter character, at least as long, and nothing else on it.
function closesFence(line, opener) {
const match = /^( {0,3})([`~]+)\s*$/.exec(line);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Require a uniform closing-fence delimiter

When an unterminated backtick block is followed by a mixed run such as `~~, this character class accepts the run and closesFence checks only its first character and total length, so both the Mermaid checker and the parallel Dart fence validator treat it as a valid close. CommonMark requires every character in a closing fence to match the opener; otherwise the remainder of the concept still renders as code while knowledge_check passes, so validate the whole run rather than only run[0].

AGENTS.md reference: AGENTS.md:L113-L113

Useful? React with 👍 / 👎.

Comment on lines +73 to +75
**The PII-safe log is the one to know about.** `error-safe-<date>.log` records only
the error's **runtime type**, never the raw exception string, precisely so it can be
shared or inspected without leaking user-authored content. The full mirror is for

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Correct the safe-log content guarantee

When DomainLogger.error receives a non-null message, safeErrorDescription writes that message verbatim before errorType=...; the added documentation therefore incorrectly says the file contains only the runtime type and can be shared without leaking user-authored content. This is especially risky for future callers that trust the documented guarantee, so either omit/sanitize the message in the safe sink or document and enforce the actual caller contract.

AGENTS.md reference: AGENTS.md:L95-L97

Useful? React with 👍 / 👎.

Comment on lines +76 to +78
it *"drives no production read"* yet. Reads still come from the mutable cache; the
planned step that flips them onto this fold has not happened, and there are no
external call sites. Read it as the target shape and the comparison mechanism, not

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Document the active projection read cutover

When any task, project, event, improver, or day-agent wake starts, its workflow calls AgentSyncService.reconciledAgentState, which invokes reconcileAgentState, derives fields from the log, persists a healed cache row when needed, and returns that reconciled value. The new concept therefore states the opposite of the production wake-critical read path by claiming the fold drives no production read and has no external call sites; document the live cutover and the narrower fact that UI/service reads still use the raw cache.

AGENTS.md reference: AGENTS.md:L95-L97

Useful? React with 👍 / 👎.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant