fix: make the knowledge bundle's rules enforceable, and its claims true#3603
Conversation
…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.
|
Caution The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased. |
📝 WalkthroughWalkthroughThis 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. ChangesKnowledge validation and documentation
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
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Comment |
Codecov Report✅ All modified and coverable lines are covered by tests. 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
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
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 winCorrect 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
⛔ Files ignored due to path filters (1)
tool/okf/package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (165)
.github/workflows/okf-validate.ymlAGENTS.mdCONTRIBUTING.mdMakefileREADME.mdknowledge/architecture/bootstrap-and-di.mdknowledge/architecture/index.mdknowledge/architecture/logging-and-diagnostics.mdknowledge/architecture/navigation.mdknowledge/architecture/overview.mdknowledge/architecture/persistence.mdknowledge/architecture/platform-and-release.mdknowledge/architecture/security-and-privacy.mdknowledge/architecture/shared-widgets.mdknowledge/conventions/code-style.mdknowledge/conventions/index.mdknowledge/conventions/knowledge-bundle.mdknowledge/conventions/localization.mdknowledge/conventions/screenshots.mdknowledge/conventions/testing.mdknowledge/domain/entity-definitions.mdknowledge/domain/entry-links.mdknowledge/domain/index.mdknowledge/domain/journal-entity.mdknowledge/features/agents/index.mdknowledge/features/agents/memory-and-compaction.mdknowledge/features/agents/overview.mdknowledge/features/agents/persistence-and-sync.mdknowledge/features/agents/project-and-event-agents.mdknowledge/features/agents/projection.mdknowledge/features/agents/task-agents.mdknowledge/features/agents/templates-souls-evolution.mdknowledge/features/agents/ui-surfaces.mdknowledge/features/agents/wake-orchestration.mdknowledge/features/agents_projection/index.mdknowledge/features/agents_projection/overview.mdknowledge/features/ai/activity-visualization.mdknowledge/features/ai/attribution.mdknowledge/features/ai/conversations-and-tools.mdknowledge/features/ai/embeddings-and-search.mdknowledge/features/ai/execution-paths.mdknowledge/features/ai/model-evaluation.mdknowledge/features/ai/overview.mdknowledge/features/ai/profile-resolution.mdknowledge/features/ai/provider-routing.mdknowledge/features/ai/seeding-and-lifecycle.mdknowledge/features/ai/settings-ui.mdknowledge/features/ai_chat.mdknowledge/features/ai_chat/index.mdknowledge/features/ai_consumption.mdknowledge/features/ai_consumption/index.mdknowledge/features/categories.mdknowledge/features/categories/index.mdknowledge/features/character.mdknowledge/features/character/index.mdknowledge/features/checklist.mdknowledge/features/checklist/index.mdknowledge/features/daily_os_next/agent-identities.mdknowledge/features/daily_os_next/capture-and-planning.mdknowledge/features/daily_os_next/coordination-protocol.mdknowledge/features/daily_os_next/dependency-aware-planning.mdknowledge/features/daily_os_next/evaluation.mdknowledge/features/daily_os_next/overview.mdknowledge/features/daily_os_next/processing-outbox.mdknowledge/features/daily_os_next/ui-surfaces.mdknowledge/features/daily_os_next/wake-prompt.mdknowledge/features/dashboards.mdknowledge/features/dashboards/index.mdknowledge/features/design_system/celebration.mdknowledge/features/design_system/component-contracts.mdknowledge/features/design_system/tokens-and-theming.mdknowledge/features/events.mdknowledge/features/events/index.mdknowledge/features/habits.mdknowledge/features/habits/index.mdknowledge/features/index.mdknowledge/features/insights.mdknowledge/features/insights/index.mdknowledge/features/journal/browse-and-linking.mdknowledge/features/journal/detail-and-saving.mdknowledge/features/journal/overview.mdknowledge/features/keyboard.mdknowledge/features/keyboard/index.mdknowledge/features/knowledge_graph_poc.mdknowledge/features/knowledge_graph_poc/index.mdknowledge/features/labels.mdknowledge/features/labels/index.mdknowledge/features/notifications.mdknowledge/features/notifications/index.mdknowledge/features/onboarding.mdknowledge/features/onboarding/index.mdknowledge/features/projects.mdknowledge/features/projects/index.mdknowledge/features/ratings.mdknowledge/features/ratings/index.mdknowledge/features/settings.mdknowledge/features/settings/index.mdknowledge/features/settings_v2.mdknowledge/features/settings_v2/index.mdknowledge/features/settings_v2/overview.mdknowledge/features/speech/overview.mdknowledge/features/speech/recording-ui.mdknowledge/features/surveys.mdknowledge/features/surveys/index.mdknowledge/features/sync/index.mdknowledge/features/sync/message-model.mdknowledge/features/sync/node-profiles-and-auto-trigger.mdknowledge/features/sync/overview.mdknowledge/features/sync/receive-path.mdknowledge/features/sync/send-path.mdknowledge/features/sync/sequence-and-backfill.mdknowledge/features/sync/vector-clocks-and-conflicts.mdknowledge/features/tasks/checklists.mdknowledge/features/tasks/data-model.mdknowledge/features/tasks/detail-composition.mdknowledge/features/tasks/filtering.mdknowledge/features/tasks/index.mdknowledge/features/tasks/overview.mdknowledge/features/tasks/relationships.mdknowledge/features/theming.mdknowledge/features/theming/index.mdknowledge/features/tts.mdknowledge/features/tts/index.mdknowledge/features/user_activity.mdknowledge/features/user_activity/index.mdknowledge/features/whats_new.mdknowledge/features/whats_new/index.mdknowledge/index.mdknowledge/log.mdlib/database/database_config_flags.dartlib/features/agents/README.mdlib/features/agents/projection/README.mdlib/features/ai_chat/README.mdlib/features/ai_consumption/README.mdlib/features/categories/README.mdlib/features/character/README.mdlib/features/checklist/README.mdlib/features/dashboards/README.mdlib/features/design_system/components/celebration/README.mdlib/features/events/README.mdlib/features/habits/README.mdlib/features/insights/README.mdlib/features/keyboard/README.mdlib/features/knowledge_graph_poc/README.mdlib/features/labels/README.mdlib/features/notifications/README.mdlib/features/onboarding/README.mdlib/features/projects/README.mdlib/features/ratings/README.mdlib/features/settings/README.mdlib/features/settings_v2/README.mdlib/features/surveys/README.mdlib/features/theming/README.mdlib/features/tts/README.mdlib/features/user_activity/README.mdlib/features/whats_new/README.mdtest/features/ai/database/TEST_REVIEW.mdtest/features/journal/state/TEST_REVIEW.mdtest/features/sync/matrix/TEST_REVIEW.part2.mdtest/tool/okf/okf_validator_test.darttool/okf/check_mermaid.mjstool/okf/check_mermaid_test.mjstool/okf/okf_validator.darttool/okf/package.jsontool/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
| - An actor outside the `<producer>/<version>` / `human:<id>` / `process:<id>` | ||
| convention — in `generated.by`, in `verified[].by`, or in the optional | ||
| `sources[].author`. |
There was a problem hiding this comment.
🗄️ 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.
| - 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.
| **`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. | ||
|
|
There was a problem hiding this comment.
🎯 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.
| **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, |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
rg -n '^\s*matrix:' pubspec.yaml pubspec.lockRepository: 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.mdRepository: 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.
| **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. |
There was a problem hiding this comment.
📐 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
| * **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. |
There was a problem hiding this comment.
🔒 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.
| 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. |
There was a problem hiding this comment.
🎯 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.
| * **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. |
There was a problem hiding this comment.
🎯 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.
There was a problem hiding this comment.
💡 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*)/; |
There was a problem hiding this comment.
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); |
There was a problem hiding this comment.
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 👍 / 👎.
| **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 |
There was a problem hiding this comment.
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 👍 / 👎.
| 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 |
There was a problem hiding this comment.
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 👍 / 👎.
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
description, a freshness date or code provenance failed nothing. Neithermake okf_checknor CI passed--warnings-as-errors, so the rules that keep themap 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 Computationfields nothing here uses.resourceandtagsare required and non-empty. Two architecture conceptshad no
resourceat all and validated clean;resource: ""andtags: []alsopassed. Requiring
resourcesurfaced a validator bug: a reference landing on therepository root normalises to the empty string, and neither
File('')norDirectory('')exists, so../..read as a dangling pointer.stale_afterfails the build when it passes, and warns for the fortnightbefore, 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.
is not a close under CommonMark, so the tail of one concept had been rendering as
code — and the link scanner missed it because
stripCodeSpansis looser aboutwhere a block ends.
tool/okf/check_mermaid.mjsruns mermaid itself under jsdom, wired as amermaidjob and intomake knowledge_check— one target, because two meant thesecond was skipped. It also inspects the built diagram: a
;in an unquotedlabel parses clean while rendering phantom nodes, and two live diagrams were
doing exactly that. 15 tests of its own.
--flagis rejected rather than ignored, which is how--warnings-as-errorcould 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:
an order of magnitude, and the first correction then overshot in both directions.
The accurate account: nine of ten query-bearing mixins gate on
privatethroughthree mechanisms — the helper,
privateStatusespassed by the caller, andraw SQL reading
config_flagsininsights_queries— and what skips filtering issingle-entity journal reads, not by-id reads as a class. The stale comment in
database_config_flags.dartthat seeded the original error is corrected too, socode and concept now agree.
PROPAGATED::was documented inverted. Every emitter sends the bare token inthe same set, deliberately, so matching it alone is complete; the prefix exists
for the wake orchestrator, whose deferral is opt-in per subscription.
DerivedAgentStatedrives no production read — its own header says so.very_good testkeeps its optimizeron, 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.
TaskStatushas seven variants, not five;blockedandonHoldcarry areason; the live/terminal split is duplicated across six sites with no sharedconstant.
git statusstays clean. Generated files aretracked, so the deletions do show —
git statusis the only signal there is.silently; the runtime-topology diagram was missing five root nodes and invented
one child.
sources[].last_modifiedwas fabricated at scale — 162 of 229 disagreed withgit log, some by six weeks. All 238 match now.Structure and coverage
features/<name>.md; the projectionkernel moved under the agents tree. 24 index files gone, all inbound links and
24
lib/READMEs retargeted.three pre-existing diagrams that never rendered are fixed. 69 of 89 concepts
carry one.
privateread gate, theUpdateNotificationstokenvocabulary and its
PROPAGATED::semantics,DerivedAgentStateand the shadowcomparison, the error-log mirrors including the PII-safe sink, the slow-query
second tier,
TaskStatus, and whatshared-widgetsomits.(where captured images live —
lotti-docs, never here — the three destinationsthere, and the before/after pair a UI PR carries), and the contribution policy.
Contribution policy
CONTRIBUTING.mdinvited "pull requests for fixes and features" and the READMEwelcomed "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.mdis kept rather than folded into the README because GitHubsurfaces 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 validatortests, 15 mermaid-checker tests, analyzer, formatter,
git diff --check, zerodangling links from
lib/READMEs, zero orphaned concepts, and all 238sources[].last_modifiedmatchinggit log -1.Summary by CodeRabbit
New Features
Bug Fixes
Validation