Server comments describe the code to a stranger (#6221)
CI & Build / Python lint (push) Successful in 2s
CI & Build / Build now, or wait for Android? (push) Successful in 2s
Android / Build, or is the channel already serving this? (push) Successful in 3s
Android / Core and FFI clippy and tests (push) Skipped
Android / Kotlin + Rust (APK) (push) Skipped
Desktop (Tauri) / Build, or is the channel already serving this? (push) Successful in 2s
CI & Build / Web typecheck and unit tests (push) Successful in 9s
CI & Build / Python tests (push) Successful in 13s
Android / Build the server image (push) Skipped
Desktop (Tauri) / Web tests, clippy, Rust tests and rustfmt (push) Skipped
Desktop (Tauri) / Tauri desktop (Linux) (push) Skipped
Desktop (Tauri) / Windows installer (cross-compiled) (push) Skipped
Desktop (Tauri) / Update manifest (push) Skipped
CI & Build / integration (push) Successful in 1m30s
CI & Build / Build & push image (push) Successful in 32s
CI & Build / Python lint (push) Successful in 2s
CI & Build / Build now, or wait for Android? (push) Successful in 2s
Android / Build, or is the channel already serving this? (push) Successful in 3s
Android / Core and FFI clippy and tests (push) Skipped
Android / Kotlin + Rust (APK) (push) Skipped
Desktop (Tauri) / Build, or is the channel already serving this? (push) Successful in 2s
CI & Build / Web typecheck and unit tests (push) Successful in 9s
CI & Build / Python tests (push) Successful in 13s
Android / Build the server image (push) Skipped
Desktop (Tauri) / Web tests, clippy, Rust tests and rustfmt (push) Skipped
Desktop (Tauri) / Tauri desktop (Linux) (push) Skipped
Desktop (Tauri) / Windows installer (cross-compiled) (push) Skipped
Desktop (Tauri) / Update manifest (push) Skipped
CI & Build / integration (push) Successful in 1m30s
CI & Build / Build & push image (push) Successful in 32s
Rule 32 "Comments describe the product to a stranger" sweep over src/, alembic/ and tests/. Comments and docstrings now say what the code does and the reason as a present-tense constraint, briefly. Removed: - issue, task, note, rule, milestone and family-idea references - "used to" / before-and-after narration - quotes of decisions and incident stories from the deploying instance - paragraph-length arguments, where a line or two carries the fact Kept every hazard as a present-tense fact, e.g. timing oracles, the proxy hop direction, and migrations that must stay frozen. Also: - Three test names lose "still"/"used to"/"pre_m304" phrasing. - pyproject's description drops "FabledSword family". The history these comments carried stays in Scribe and in git log. A comment-stripping diff (Scribe snippet #6226 "codeonly.py — prove a diff changed only comments") shows no code changed apart from the renamed tests and the description string. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
+29
-56
@@ -58,8 +58,8 @@ def test_all_note_routes_registered(app):
|
||||
)
|
||||
}
|
||||
assert expected <= registered, f"unregistered note routes: {expected - registered}"
|
||||
# Removed in #5178: an item is added, reworded and removed by editing the body,
|
||||
# and previews arrive in the background after a save. Saved views went in #5180.
|
||||
# Items are edited in the body, previews arrive after a save, and there are no
|
||||
# saved views.
|
||||
gone = {"notes.add_item", "notes.delete_item", "notes.unfurl_link", "saved_filters.list_saved"}
|
||||
assert not gone & registered, f"removed note routes are back: {gone & registered}"
|
||||
|
||||
@@ -80,7 +80,7 @@ def test_normalize_color():
|
||||
|
||||
|
||||
def test_palette_has_core_colors():
|
||||
# A LABEL's vocabulary since M315 — a note has no colour to be one of these.
|
||||
# A label's vocabulary; a note has no colour.
|
||||
for c in ("default", "red", "orange", "yellow", "green", "teal", "blue", "purple", "pink", "gray"):
|
||||
assert c in NOTE_COLORS
|
||||
|
||||
@@ -88,7 +88,7 @@ def test_palette_has_core_colors():
|
||||
def test_serialize_shape():
|
||||
n = Note(body="b", pinned=True, archived=False)
|
||||
s = n.serialize()
|
||||
assert "title" not in s # there is no title field any more (M13 step 3)
|
||||
assert "title" not in s # a note's name is its first line, not a field
|
||||
assert s["body"] == "b"
|
||||
assert s["pinned"] is True
|
||||
assert s["archived"] is False
|
||||
@@ -131,13 +131,6 @@ async def test_reorder_requires_auth(app):
|
||||
assert resp.status_code == 401
|
||||
|
||||
|
||||
# [[wiki-links]] are gone entirely (note 2897), and with them backlinks, the graph,
|
||||
# the name index and the `[[` autocomplete. So are the two helpers that used to keep
|
||||
# links alive across a rename, and the id-binding that briefly replaced them. Nothing
|
||||
# here asserts their absence — `test_all_note_routes_registered` below is what would
|
||||
# notice a route coming back, and the removal is one commit rather than a fossil.
|
||||
|
||||
|
||||
def test_derive_display_title_is_the_first_body_line():
|
||||
assert derive_display_title("first line\nsecond line") == "first line"
|
||||
assert derive_display_title(" spaced first \nnext") == "spaced first"
|
||||
@@ -146,10 +139,7 @@ def test_derive_display_title_is_the_first_body_line():
|
||||
|
||||
|
||||
def test_derive_display_title_names_a_list_only_note():
|
||||
# The same property the old `first_item` fallback protected — a note that is only
|
||||
# a checklist still has a name — reached a different way. Items ARE body lines now
|
||||
# (M304), so the first one is simply the first line, with its marker stripped:
|
||||
# calling the note "- [ ] milk" would show someone the storage instead of the note.
|
||||
# A checklist-only note is named by its first item, without the marker.
|
||||
assert derive_display_title("- [ ] milk\n- [ ] eggs") == "milk"
|
||||
assert derive_display_title(" * [x] eggs ") == "eggs"
|
||||
# Prose still wins when it comes first, because it IS the first line.
|
||||
@@ -177,11 +167,8 @@ def test_split_body_tags_lifts_only_a_line_that_is_nothing_else():
|
||||
"""The rule, in the cases it exists to get right.
|
||||
|
||||
A tag on a line of its own is filing and the line can go. A tag sharing a line
|
||||
with words is part of what was written, and taking it out would leave "remember to
|
||||
call" — so the line is left exactly as typed. The trailing-tag case (`buy milk
|
||||
#grocery`) is deliberately on the conservative side of the line: it reads like
|
||||
filing, but nothing in the text distinguishes it from `remember to call #mom`, and
|
||||
guessing wrong mangles a sentence to save a duplicate chip.
|
||||
with words is left as typed, including `buy milk #grocery`: nothing distinguishes
|
||||
it from `remember to call #mom`.
|
||||
"""
|
||||
assert split_body_tags("#todo\nreorganize the homepage") == (["todo"], [], "reorganize the homepage")
|
||||
assert split_body_tags("needs a tauri app\n#todo") == (["todo"], [], "needs a tauri app")
|
||||
@@ -224,14 +211,11 @@ def test_split_body_tags_keeps_a_tag_derived_when_prose_still_carries_it():
|
||||
assert body == "remember the #todo list"
|
||||
|
||||
|
||||
def test_migration_0028_lifts_exactly_what_the_app_lifts_today():
|
||||
def test_migration_0028_lifts_exactly_what_the_app_lifts():
|
||||
"""The 0028 data migration rewrites note bodies, and that is not undoable.
|
||||
|
||||
It carries its OWN frozen copy of the rule rather than importing
|
||||
`split_body_tags`, on 0027's principle that a migration must keep producing what
|
||||
it produced the day it ran. This does not assert the two agree — they are allowed
|
||||
to diverge later, which is the entire point of freezing one. It pins the frozen
|
||||
copy against fixed expectations, so nobody can "tidy" it into eating prose.
|
||||
It carries its own frozen copy of the rule, which may diverge from
|
||||
`split_body_tags` later. This pins the frozen copy against fixed expectations.
|
||||
"""
|
||||
import importlib.util
|
||||
from pathlib import Path
|
||||
@@ -286,7 +270,7 @@ def test_parse_list_items():
|
||||
|
||||
|
||||
def test_parse_dt():
|
||||
# A full ISO instant round-trips (used to validate the Timeline date range).
|
||||
# A full ISO instant round-trips (validates the creation-date range).
|
||||
d = parse_dt("2026-07-19T12:30:00+00:00")
|
||||
assert (d.year, d.month, d.day, d.hour, d.minute) == (2026, 7, 19, 12, 30)
|
||||
assert d.tzinfo is not None
|
||||
@@ -440,9 +424,7 @@ def test_usec_to_dt():
|
||||
|
||||
|
||||
def test_keep_spec_list_note_keeps_its_text_too():
|
||||
# Keep's own notes carry one or the other, but its textContent used to be
|
||||
# DISCARDED whenever a note also had listContent, because a note could only be
|
||||
# one kind. A note holds both now, so nothing is dropped on the way in.
|
||||
# A Keep note with both textContent and listContent keeps both.
|
||||
kn = {
|
||||
"title": "Groceries",
|
||||
"textContent": "for the weekend",
|
||||
@@ -477,8 +459,7 @@ def test_keep_spec_text_note_folds_annotation_urls_and_drops_color():
|
||||
}
|
||||
spec = _keep_spec(kn, "Takeout/Keep")
|
||||
assert "https://example.com" in spec["body"]
|
||||
# BROWN used to map to the nearest hue we had. There is no hue to map TO now, so a
|
||||
# Keep import brings across everything except the one thing this app stopped having.
|
||||
# A note has no colour, so a Keep note's colour is not imported.
|
||||
assert "color" not in spec
|
||||
# attachment path is resolved relative to the note JSON's folder
|
||||
assert spec["attachments"] == [{"file": "Takeout/Keep/img.jpg", "mime": "image/jpeg"}]
|
||||
@@ -488,8 +469,7 @@ def test_native_spec_roundtrip_fields():
|
||||
n = {
|
||||
"title": "T",
|
||||
"body": "b",
|
||||
# An export taken before M315 still carries this. Reading past it rather than
|
||||
# rejecting the file is the whole point — old exports must still import.
|
||||
# Older exports carry a note colour; reading past it keeps them importable.
|
||||
"color": "blue",
|
||||
"pinned": True,
|
||||
"archived": False,
|
||||
@@ -499,8 +479,8 @@ def test_native_spec_roundtrip_fields():
|
||||
"attachments": [{"file": "attachments/ab/img.png", "mime": "image/png"}],
|
||||
}
|
||||
spec = _native_spec(n)
|
||||
# The spec still CARRIES a title — an export taken before M13 has one, and
|
||||
# _create_imported_note folds it into the body rather than dropping it.
|
||||
# The spec carries a title (Keep notes and older exports have one), which
|
||||
# _create_imported_note folds into the body.
|
||||
assert spec["title"] == "T"
|
||||
assert spec["body"] == "b"
|
||||
assert "color" not in spec
|
||||
@@ -530,12 +510,10 @@ def test_detect_urls_ignores_non_http():
|
||||
assert detect_urls("") == []
|
||||
|
||||
|
||||
# --- checklist items: the body IS the checklist (M304) -----------------------
|
||||
# --- checklist items: the body is the checklist ------------------------------
|
||||
#
|
||||
# The same table of cases as core/src/local/derive.rs. Deliberately duplicated
|
||||
# rather than shared: the point of three implementations is that each is checked
|
||||
# against the same grammar, and a test that only ran once would not catch the two
|
||||
# drifting apart.
|
||||
# The same cases as core/src/local/derive.rs, duplicated so each implementation is
|
||||
# checked against the grammar.
|
||||
|
||||
|
||||
def test_parse_items_reads_a_list_out_of_prose():
|
||||
@@ -544,7 +522,7 @@ def test_parse_items_reads_a_list_out_of_prose():
|
||||
|
||||
|
||||
def test_parse_items_between_paragraphs():
|
||||
# The case a side table could not express, which is the whole reason for M304.
|
||||
# A list between two paragraphs.
|
||||
assert [i.text for i in parse_items("before\n- [ ] middle\nafter")] == ["middle"]
|
||||
|
||||
|
||||
@@ -603,9 +581,8 @@ def test_strip_marker():
|
||||
|
||||
|
||||
def test_the_migration_folds_exactly_like_the_app():
|
||||
"""0027 inlines its own copy of append_item, deliberately — a migration has to keep
|
||||
producing what it produced the day it ran, so it must not follow the app if the
|
||||
app's spacing ever changes. This is what keeps the copy honest until then."""
|
||||
"""0027 inlines its own copy of append_item, frozen; this keeps the two in step
|
||||
while the app's spacing is unchanged."""
|
||||
import importlib.util
|
||||
from pathlib import Path
|
||||
|
||||
@@ -628,9 +605,8 @@ def test_the_migration_folds_exactly_like_the_app():
|
||||
|
||||
|
||||
def test_note_markdown_writes_a_checklist_once():
|
||||
"""The export used to append the items after the body. The body IS them now
|
||||
(M304), so the old branch would have doubled every checklist in an export — and
|
||||
doubled it again on the next re-import."""
|
||||
"""The checklist is written once, as part of the body, so a re-import doesn't
|
||||
double it."""
|
||||
note = Note(
|
||||
display_title="shopping",
|
||||
body="shopping\n\n- [ ] milk\n- [x] eggs",
|
||||
@@ -650,11 +626,9 @@ def test_native_spec_of_a_current_export_folds_nothing():
|
||||
assert _native_spec({"body": "a\n\n- [ ] milk"})["items"] == []
|
||||
|
||||
|
||||
def test_native_spec_of_a_pre_m304_export_still_carries_its_items():
|
||||
# An export taken BEFORE this milestone has a body with no task lines and a
|
||||
# separate items array. Importing one has to put the checklist back — which is
|
||||
# the same fold the Keep importer does, and the reason _insert_note still accepts
|
||||
# items at all.
|
||||
def test_native_spec_of_an_export_with_separate_items_folds_them():
|
||||
# An older export has a separate items array; importing folds it into the body,
|
||||
# as the Keep importer does.
|
||||
old = {"body": "shopping", "items": [{"text": "milk", "checked": True}]}
|
||||
assert _native_spec(old)["items"] == [{"text": "milk", "checked": True}]
|
||||
|
||||
@@ -668,9 +642,8 @@ def _export_zip(app_marker: str) -> zipfile.ZipFile:
|
||||
|
||||
@pytest.mark.parametrize("marker", ["inkwell", "thoughtsync"])
|
||||
def test_an_export_imports_under_either_name(marker):
|
||||
# "thoughtsync" is what every export written before the rename to Inkwell says.
|
||||
# Those zips are backups, so they have to keep restoring as native exports rather
|
||||
# than falling through to the Keep importer, which would find nothing in them.
|
||||
# Exports from when the app was called ThoughtSync say "thoughtsync", and must
|
||||
# import as native exports rather than fall through to the Keep importer.
|
||||
specs, source = _read_import_specs(_export_zip(marker), _ImportBudget())
|
||||
assert source == "inkwell"
|
||||
assert [s["body"] for s in specs] == ["kept"]
|
||||
|
||||
Reference in New Issue
Block a user