CI & Build / Build now, or wait for Android? (push) Successful in 2s
CI & Build / Python lint (push) Successful in 3s
CI & Build / TypeScript typecheck (push) Failing after 6s
CI & Build / Build & push image (push) Skipped
CI & Build / Python tests (push) Successful in 8s
Desktop (Tauri) / Tauri desktop (Linux) (push) Failing after 31s
Desktop (Tauri) / Windows installer (cross-compiled) (push) Failing after 37s
Desktop (Tauri) / Update manifest (push) Skipped
Android / Kotlin + Rust (APK) (push) Failing after 1m56s
Operator, 2026-08-22 (note 2897): ThoughtSync is an intermediary surface. You
write here because it's easy — a notebook in your pocket — and later you recall
the thing and go finish it somewhere else. Recall is the product; organization
is secondary. A linking system is organization, and it isn't what this is for.
So: `[[wiki-links]]`, backlinks, the `[[` autocomplete, the note_links table,
`/api/notes/link-search`, `/api/notes/<id>/backlinks`, the whole graph blueprint
and GraphView. Rust core loses `extract_links`, `backlinks`, `link_search` and
`create_titled`; the desktop loses the three Tauri commands that exposed them.
This subsumes 982d24c rather than reverting it. That commit bound links to a
note id so a rename would stop rewriting other notes' bodies — real infra, but
infra for a feature that is now gone, and nothing it added survives. Alembic
0023 stays in the chain anyway: it shipped in an image and may already be
applied, and deleting an applied revision strands a database's version pointer.
0024 drops the table and takes the column with it. The history stays honest
about the fact that it existed for a day.
Two things deliberately kept, because they were serving recall and only
incidentally serving links:
- `/api/notes/titles` and the titles store. The command palette lists them so
you can jump to a note by name. `resolve()` — the name→note lookup that only
linking needed — is gone.
- `display_title`. Every note still has a name for search results and export
filenames. What that name is FOR changed; that it exists did not.
`notes/links.py` is now `notes/tags.py`, holding the #tag→label reconciliation
it always also owned. A file called links.py with no links in it would have been
exactly the drift this removal is meant to end.
Also swept out on the way: `_escape_like`, whose only caller was link-search,
and the `graph` icon. Nothing lost that a person typed — note_links was always
derived, and the `[[text]]` is still sitting in every body it was written in.
55 lines
1.8 KiB
Python
55 lines
1.8 KiB
Python
"""drop note_links — [[wiki-links]] are removed (note 2897)
|
|
|
|
Revision ID: 0024
|
|
Revises: 0023
|
|
Create Date: 2026-08-22
|
|
|
|
ThoughtSync is an intermediary surface for capture and recall; a linking system is
|
|
organization, which is not what it is for. Backlinks, the graph and the name index
|
|
went with it.
|
|
|
|
0023 (which added `note_links.target_id`) is deliberately left in the chain rather
|
|
than deleted. It shipped in an image and may already be applied, and removing an
|
|
applied revision would strand a database's alembic_version pointer. So the column is
|
|
dropped here along with the table it lived on, and the history stays honest about the
|
|
fact that it existed for a day.
|
|
|
|
No down-migration data concern: note_links was always DERIVED from note bodies. The
|
|
`[[text]]` is still sitting in every body it was written in; nothing a person typed is
|
|
lost by this.
|
|
"""
|
|
from alembic import op
|
|
import sqlalchemy as sa
|
|
from sqlalchemy.dialects import postgresql
|
|
|
|
revision = "0024"
|
|
down_revision = "0023"
|
|
branch_labels = None
|
|
depends_on = None
|
|
|
|
|
|
def upgrade() -> None:
|
|
op.drop_table("note_links")
|
|
|
|
|
|
def downgrade() -> None:
|
|
op.create_table(
|
|
"note_links",
|
|
sa.Column("id", postgresql.UUID(as_uuid=True), primary_key=True),
|
|
sa.Column(
|
|
"source_id",
|
|
postgresql.UUID(as_uuid=True),
|
|
sa.ForeignKey("notes.id", ondelete="CASCADE"),
|
|
nullable=False,
|
|
),
|
|
sa.Column(
|
|
"target_id",
|
|
postgresql.UUID(as_uuid=True),
|
|
sa.ForeignKey("notes.id", ondelete="SET NULL"),
|
|
nullable=True,
|
|
),
|
|
sa.Column("target_norm", sa.Text(), nullable=False),
|
|
)
|
|
op.create_index("ix_note_links_target", "note_links", ["target_norm"])
|
|
op.create_index("ix_note_links_target_id", "note_links", ["target_id"])
|