Core and desktop comments describe the code to a stranger (#6224)
Android / Build, or is the channel already serving this? (push) Successful in 2s
CI & Build / Build now, or wait for Android? (push) Successful in 2s
CI & Build / Python lint (push) Successful in 2s
CI & Build / Python tests (push) Successful in 12s
CI & Build / Web typecheck and unit tests (push) Successful in 8s
Desktop (Tauri) / Build, or is the channel already serving this? (push) Successful in 2s
Android / Core and FFI clippy and tests (push) Successful in 1m3s
CI & Build / integration (push) Successful in 1m37s
CI & Build / Build & push image (push) Skipped
Desktop (Tauri) / Web tests, clippy, Rust tests and rustfmt (push) Successful in 2m40s
Desktop (Tauri) / Windows installer (cross-compiled) (push) Successful in 3m14s
Desktop (Tauri) / Tauri desktop (Linux) (push) Successful in 4m3s
Desktop (Tauri) / Update manifest (push) Successful in 4s
Android / Kotlin + Rust (APK) (push) Successful in 8m42s
Android / Build the server image (push) Successful in 1s

Milestone 546 "Bring the repo to the comment standard (rule 32) and
compose defaults (rule 198)", step #6224 "Comment standard sweep: Rust
core and desktop client".

Doc comments and comments across inkwell-core, the Tauri app and
desktop/packaging now say what the code does and the non-obvious why in
the present tense. Gone: milestone tags (M10.x, M11.3, M13, M304, M315,
M314, milestone 325), issue and Scribe-note numbers, family-idea and
family-rule citations, the run numbers and commit hashes behind past
bugs, and the narration of what used to be (the stable channel before it
held its own bundles, CARGO_PKG_VERSION as the shown version, the
MANIFEST_TAG split, the store's missing tests, the old PKGBUILD). The
schema's migration notes keep what each step does and why, without
"until now". The forge is called the forge rather than Forgejo.

Hazards stay as facts: the dev-rolling tag that must not shadow the
branch, the manifest matched on this build's version, the APK's fixed
name surviving the prune, the LIKE guard in v9, -wal/-shm moving with
the renamed store, panic = abort ending the app.

34 files, comments only: a comment-stripping diff of every changed file
against HEAD is identical.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-21 20:30:37 -04:00
co-authored by Claude Opus 5.5
parent 0a631219ee
commit 01b53118b9
34 changed files with 300 additions and 384 deletions
+20 -27
View File
@@ -6,7 +6,7 @@
//! letters, digits, `_` and `-`. On save these become labels attached with
//! `via_tag = true`. The server and the web run the same cases
//! (core/testdata/grammar.json).
//! - `- [ ] item`: a checklist item. The body IS the checklist (M304) — there is no
//! - `- [ ] item`: a checklist item. The body IS the checklist — there is no
//! table of items beside it, so a list can sit between two paragraphs instead of
//! only after them.
//!
@@ -17,9 +17,6 @@
//! and the rewriters below are how one is edited.
//!
//! Dedupes case-insensitively, preserving first-seen order.
//!
//! Also derived `[[wiki-links]]` until they were removed (note 2897) — this is a
//! capture-and-recall surface, and a linking system is organization.
/// Every `#tag` in ONE line, as `(start, end, name)` in char indices.
///
@@ -31,10 +28,9 @@ fn line_tags(chars: &[char]) -> Vec<(usize, usize, String)> {
let mut i = 0;
while i < chars.len() {
if chars[i] == '#' {
// Start of line or after whitespace, and nothing else. Any non-tag
// character used to count, which made `(#todo)` a tag here and plain
// text on the server, and made the `/#section` of a pasted URL a label.
// Whitespace is the rule all three implementations now share (#5166).
// Start of line or after whitespace, and nothing else, so `(#todo)` and a
// pasted URL's `/#section` are not tags. All three implementations share
// this rule.
let boundary = i == 0 || chars[i - 1].is_whitespace();
// A tag must start with a letter (so "#1" or a bare "#" is not a tag).
if boundary && i + 1 < chars.len() && chars[i + 1].is_alphabetic() {
@@ -54,8 +50,8 @@ fn line_tags(chars: &[char]) -> Vec<(usize, usize, String)> {
/// One `#tag` and exactly where it sits, for a renderer drawing the body itself.
///
/// The card no longer prints a chip for a tag whose text is still in the note — it
/// colours the token where it was typed instead. To do that a renderer needs the
/// The card colours a tag where it was typed rather than repeating it as a chip.
/// To do that a renderer needs the
/// SPAN, not just the name, and asking it to find the name again would be a second
/// grammar quietly disagreeing with this one about what `##a` or `#1` is.
#[derive(Debug, Clone, PartialEq, Eq)]
@@ -142,8 +138,8 @@ fn collapse_blank_runs(text: &str) -> String {
/// else is left exactly as written.
///
/// The MIRROR of `split_body_tags` in the server's `notes/tags.py`, and it has to stay
/// one: a note lifted differently here than there would change under the operator the
/// moment it synced. Same discipline, and the same reason, as `DerivedTint`.
/// one: a note lifted differently here than there would change the moment it synced.
/// Same discipline, and the same reason, as `DerivedTint`.
///
/// The conservative reading of "standalone" is deliberate. A trailing tag is
/// ambiguous and the text does not say which it is — `buy milk #grocery` is filing,
@@ -152,8 +148,8 @@ fn collapse_blank_runs(text: &str) -> String {
///
/// `standalone` tags become ORDINARY labels (`via_tag = 0`): nothing is left to derive
/// them from, so the row becomes the record and the chip's × becomes the way to remove
/// one. `inline` tags stay derived exactly as before. That is what `via_tag` means from
/// here on — backed by text still in the body.
/// one. `inline` tags stay derived. That is what `via_tag` means: backed by text still
/// in the body.
pub fn lift_standalone_tags(body: &str) -> (Vec<String>, Vec<String>, String) {
let mut standalone: Vec<String> = Vec::new();
let mut inline: Vec<String> = Vec::new();
@@ -220,7 +216,7 @@ fn is_tag_char(c: char) -> bool {
/// How two tag names compare: equal once every letter is lowercased, accented ones
/// included, so "Café" and "CAFÉ" are one tag. The server's `labeling.named` folds
/// the same way (Postgres `lower`, Python `str.lower`), and the store's `fold` SQL
/// function is this (#5385).
/// function is this.
pub(crate) fn fold(name: &str) -> String {
name.to_lowercase()
}
@@ -248,8 +244,7 @@ fn push_unique(out: &mut Vec<String>, candidate: &str) {
// parse it would make a half-typed list stop being a list.
/// A checklist item, as found in the body. Its position in the returned vector is
/// its identity — the same thing `position` meant when these were rows, and all the
/// wire ever carried (`push.rs` sent text and checked, never an id).
/// its identity; the wire carries text and checked, never an id.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct DerivedItem {
pub text: String,
@@ -361,9 +356,8 @@ pub const DISPLAY_TITLE_CAP: usize = 200;
/// twice, and they have to agree or a synced note is called different things on either
/// side of the wire. Both run the `display_titles` cases in testdata/grammar.json.
///
/// It no longer needs the items, because the items ARE lines of the body now (M304).
/// What it needs instead is to strip the task marker off: a list-only note is still
/// named by its first item, and calling that note "- [ ] milk" would be showing
/// The items ARE lines of the body, so it strips the task marker off: a list-only
/// note is named by its first item, and calling that note "- [ ] milk" would be showing
/// someone the storage rather than the note. An empty item is skipped rather than
/// naming the note "", which is what a half-typed list would otherwise do.
pub fn display_title(body: &str) -> String {
@@ -431,9 +425,8 @@ pub fn set_item_checked(body: &str, index: usize, checked: bool) -> String {
///
/// Spaced exactly as `import_export.py:_note_markdown` writes a list — a blank line
/// between prose and the list, and nothing between consecutive items. That is not
/// cosmetic: the server migration folds existing rows into bodies using the same
/// layout, so an export taken before the migration and one taken after have to
/// agree byte for byte.
/// cosmetic: the migrations that fold checklist rows into bodies use the same layout,
/// so every surface lands on byte-identical bodies.
///
/// `checked` is a parameter rather than always false because the two migrations that
/// fold existing rows into bodies have to carry the state those rows were in. A new
@@ -513,8 +506,8 @@ mod tests {
// ── lifting standalone tags ──────────────────────────────────────────────
//
// The MIRROR of `split_body_tags` in the server's notes/tags.py, case for case.
// A note lifted differently here than there would change under the operator the
// moment it synced, so these are the cases that file agrees to.
// A note lifted differently here than there would change the moment it synced,
// so these are the cases that file agrees to.
#[test]
fn lifts_a_line_that_is_nothing_but_tags() {
@@ -662,8 +655,8 @@ mod tests {
#[test]
fn append_spaces_like_the_exporter() {
// Prose then a blank line then the list — byte-for-byte what
// import_export.py:_note_markdown writes, which is what the server
// migration will fold existing rows into.
// import_export.py:_note_markdown writes, which is the layout the server
// migration folds rows into.
assert_eq!(append_item("a note", "milk", false), "a note\n\n- [ ] milk");
// Nothing between consecutive items.
let one = "a note\n\n- [ ] milk";