generated from coulomb/repo-seed
research: TiddlyWiki deep dive (single-file wiki, write-granularity extreme); UC-78
SHARD-WP-0003 T3. Whole-file write-granularity anchor: an entire wiki (content + app engine) in one self-contained HTML file -> save rewrites the whole file, no per-page atomicity. Node .tid file-per-tiddler substrate is git-diffable/ fine-grained, so the same engine spans the granularity spectrum by substrate (cf. Logseq file/DB UC-62, backend-swap UC-43). Tiddler = flexible-field record (UC-34); filter expressions = native-query tier (UC-52). UC-78 (single-file container-format attach). Enriched UC-35/40/34/52/43. Marks T3 done. Feeds SHARD-WP-0002 T11/T14. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
16
research/260614-tiddlywiki-deep-dive/README.md
Normal file
16
research/260614-tiddlywiki-deep-dive/README.md
Normal file
@@ -0,0 +1,16 @@
|
||||
# 260614 — TiddlyWiki deep dive
|
||||
|
||||
Deep dive on **TiddlyWiki** (TW5): an entire wiki — tiddlers **plus** the app engine — in
|
||||
**one self-contained HTML file**, the **whole-file write-granularity** anchor of the
|
||||
synthesis matrix, with a Node.js **file-per-tiddler** (`.tid`) substrate as the git-diffable
|
||||
alternative, a tiddler/field record model, and **filter expressions** as the native query
|
||||
language.
|
||||
|
||||
- `findings.md` — the single-file model, tiddler data model, dual substrate, filters,
|
||||
capability profile, INTENT mapping, UC seed (UC-78), architecture notes for SHARD-WP-0002,
|
||||
open questions, sources, traceability.
|
||||
|
||||
Catalog yield: UC-78 (attach a single-file self-contained wiki as one shard — parse tiddlers
|
||||
out, project; write = rewrite the whole file, the coarsest write-granularity anchor).
|
||||
Enriched UC-35/40/34/52/43. Feeds SHARD-WP-0002 T11 (write-granularity extreme) and T14
|
||||
(single-file vs file-per-tiddler binding).
|
||||
164
research/260614-tiddlywiki-deep-dive/findings.md
Normal file
164
research/260614-tiddlywiki-deep-dive/findings.md
Normal file
@@ -0,0 +1,164 @@
|
||||
# TiddlyWiki — deep dive (findings)
|
||||
|
||||
**Date:** 2026-06-14 · **Source:** SHARD-WP-0003 T3 · **Subject:** TiddlyWiki / TiddlyWiki5
|
||||
(TW5), Jeremy Ruston's self-contained personal wiki.
|
||||
|
||||
## Why this dive
|
||||
|
||||
The synthesis matrix names **whole-file write granularity** as one extreme of the
|
||||
write-granularity spectrum, anchored by TiddlyWiki. This dive confirms the anchor and the
|
||||
*portability extreme* it implies — a wiki that is **a single HTML file you can email** — and
|
||||
finds the twist: TiddlyWiki also has a **Node.js file-per-tiddler** substrate, so it spans
|
||||
the granularity spectrum the way Logseq spans file/DB (UC-62). The question: how does
|
||||
shard-wiki attach a backend whose *entire content is one file*?
|
||||
|
||||
## 1. The single-file model
|
||||
|
||||
Classic TiddlyWiki ships as **one `.html` file** that contains **both**:
|
||||
|
||||
1. the **TiddlyWiki core** (the JavaScript engine, parser, renderer, UI), and
|
||||
2. **every tiddler** (all content), serialized into the file.
|
||||
|
||||
Open it in a browser and the file *is* the running application. There is **no server and no
|
||||
build step** — the app reconstitutes itself from the file it was loaded from. This is the
|
||||
portability extreme: a complete, self-hosting wiki in a single, emailable, USB-stick-able
|
||||
artifact that runs offline anywhere.
|
||||
|
||||
**Saving** is the catch: a browser page cannot normally overwrite the file it came from, so
|
||||
TiddlyWiki uses **"savers"** — TiddlyFox/browser extension, the File System Access API, a
|
||||
Node.js server, TiddlySpot/put-savers, or "download a new copy." Crucially, **a save
|
||||
rewrites the *entire* HTML file** (core + all tiddlers re-serialized). Hence **whole-file
|
||||
write granularity**: there is no concept of writing one page in isolation in the
|
||||
single-file mode — every save touches the whole artifact.
|
||||
|
||||
## 2. The tiddler data model
|
||||
|
||||
The atomic unit is the **tiddler** — a named record with **fields**:
|
||||
|
||||
- Core fields: **`title`** (the identity), **`text`** (the body), **`tags`**, **`created`**,
|
||||
**`modified`**, **`type`** (content type, e.g. `text/vnd.tiddlywiki`, `text/markdown`),
|
||||
plus **arbitrary custom fields** (any key→value). A tiddler is effectively a **flexible
|
||||
flat record** — closer to a typed-field record (UC-34) than to prose-with-frontmatter.
|
||||
- **Everything is a tiddler**: not just pages, but tags, macros, templates, themes, plugins,
|
||||
and the wiki's own configuration are all tiddlers. A **plugin is a bundle of tiddlers**.
|
||||
- Content markup is **WikiText** (TW5's own), though `type` can mark a tiddler as Markdown,
|
||||
JSON, image, etc. **Transclusion** is native: `{{SomeTiddler}}` embeds another tiddler;
|
||||
`{{SomeTiddler!!field}}` embeds a field.
|
||||
|
||||
## 3. The dual substrate — single-file vs file-per-tiddler
|
||||
|
||||
TiddlyWiki on **Node.js** stores each tiddler as a **separate `.tid` file** on disk: a small
|
||||
text file with a header of `field: value` lines, a blank line, then the body. The Node
|
||||
server assembles these into the same wiki at serve time. This substrate is:
|
||||
|
||||
- **git-diffable and fine-grained** — one file per tiddler, line-level diffs, per-tiddler
|
||||
history — the *opposite* end of the granularity spectrum from the single HTML file.
|
||||
- the natural attach surface for a *versioned, multi-author* TiddlyWiki.
|
||||
|
||||
So TiddlyWiki **spans the write-granularity spectrum by substrate** (single-file = whole-file
|
||||
write; Node = file-per-tiddler write), exactly as Logseq spans file/DB (UC-62) and as the
|
||||
backend-swap question (UC-43) anticipates.
|
||||
|
||||
## 4. Native query — filter expressions
|
||||
|
||||
TiddlyWiki's query language is **filter expressions** over tiddler fields, e.g.
|
||||
`[tag[todo]!tag[done]sort[modified]]` — a compact DSL that selects/orders tiddlers by field
|
||||
and tag. Lists, tables, and dynamic views are built from filters. This is a **native-query
|
||||
capability** (UC-52 tier) — less expressive than SPARQL/datalog but real, and computed over
|
||||
the tiddler store.
|
||||
|
||||
## 5. Capability profile
|
||||
|
||||
| Dimension (synthesis spectrum) | TiddlyWiki (single-file) | TiddlyWiki (Node `.tid`) |
|
||||
|--------------------------------|--------------------------|--------------------------|
|
||||
| Attachment mode | **file-store: one HTML file** | **file-store: dir of `.tid` files** |
|
||||
| Addressing granularity | tiddler (`title`) within the file | tiddler = one file |
|
||||
| Content identity | **`title`** (placement-bound) | title ↔ filename |
|
||||
| Structure | flat record store w/ arbitrary **fields** + tags | same |
|
||||
| History | none in-file (whole-file save) | **per-file git history** |
|
||||
| Merge model | whole-file replace (no merge) | git 3-way per tiddler |
|
||||
| Native query | **filter expressions** | filter expressions |
|
||||
| Translation | WikiText (or per-tiddler `type`: markdown/json/…) | same |
|
||||
| **Write granularity** | **whole file** (the anchor) | **file per tiddler** |
|
||||
| Operational envelope | trivial — a browser; no server | a Node server |
|
||||
| Access grant | file access = full access | server/file perms |
|
||||
| Content opacity | transparent (parse the HTML store) | transparent text |
|
||||
| Provenance | created/modified fields | git + fields |
|
||||
|
||||
## 6. INTENT mapping
|
||||
|
||||
### Reinforcements
|
||||
|
||||
- **Graceful degradation**: a single-file TiddlyWiki is a *trivial* read-only / projection /
|
||||
backup shard — parse the tiddlers out of the HTML, project pages; no server needed. The
|
||||
limited-backend-still-usable principle at its simplest.
|
||||
- **Markdown-first but backend-neutral**: tiddlers carry a `type`, so Markdown tiddlers
|
||||
coexist with WikiText — the page model's content-type field maps directly.
|
||||
- **Typed fields** (UC-34): arbitrary tiddler fields are a flexible record model the page
|
||||
model already accommodates.
|
||||
- **Backend-swap under stable identity** (UC-43): single-file ↔ Node `.tid` is the same
|
||||
logical wiki on two substrates — the migration UC-43 anticipates, within one engine.
|
||||
|
||||
### Divergences (boundaries / notes)
|
||||
|
||||
- **Whole-file write granularity** is a real constraint: in single-file mode shard-wiki
|
||||
cannot write one page atomically — an overlay applied "to one page" still **rewrites the
|
||||
whole file** (T11). This is the coarsest write tier; model it explicitly so overlays/locks
|
||||
account for it (a write to any page conflicts with any concurrent write).
|
||||
- **Identity = title**, file-local; cross-shard identity (T16) layered above.
|
||||
- **The app is in the file**: when parsing a single-file TiddlyWiki, shard-wiki must extract
|
||||
the **tiddler store** and ignore the embedded engine — i.e. treat the HTML as a *container
|
||||
format*, not as page content (don't mistake the app for content).
|
||||
|
||||
### What to keep
|
||||
|
||||
1. **Single-file self-contained wiki as a first-class file-store shard** — container-format
|
||||
parse, whole-file write granularity (UC-78); the portability/granularity extreme.
|
||||
2. **Whole-file write granularity as a named tier** (T11) with overlay/lock implications.
|
||||
3. **Dual-substrate binding** (single-file vs `.tid` dir) as another instance of
|
||||
substrate-choice under one identity (UC-43/UC-62).
|
||||
|
||||
## 7. UC seed
|
||||
|
||||
| # | Seed | Disposition |
|
||||
|---|------|-------------|
|
||||
| UC-78 | Attach a **single-file self-contained wiki** (TiddlyWiki HTML) as one shard — parse tiddlers out of the container, project pages; **write = rewrite the whole file** (whole-file write granularity, the coarsest tier) | **new** |
|
||||
| — | whole-file write granularity anchor + overlay/lock implications | enrich **UC-35** |
|
||||
| — | single HTML file as a file-store shard (container format) | enrich **UC-40** |
|
||||
| — | tiddler arbitrary fields = flexible record | enrich **UC-34** |
|
||||
| — | filter expressions as a native-query tier | enrich **UC-52** |
|
||||
| — | single-file ↔ Node `.tid` substrate swap | enrich **UC-43** |
|
||||
|
||||
## 8. Architecture notes for SHARD-WP-0002
|
||||
|
||||
- **T11 (capability / write granularity):** confirm **whole-file** as the coarsest named
|
||||
write tier (anchored by single-file TiddlyWiki), with the implication that an overlay to
|
||||
*any* page conflicts with concurrent writes (no per-page atomicity). File-per-tiddler is
|
||||
the fine tier on the same engine.
|
||||
- **T14 (attach binding):** a single-file wiki binds as a **container-format file-store**
|
||||
(parse tiddler store, ignore embedded engine); a Node TiddlyWiki binds as a **dir of
|
||||
`.tid` files** (git-diffable). One engine, two bindings — parameterize like UC-43.
|
||||
- **Native query:** filter expressions are a low-mid native-query tier between "none" and
|
||||
datalog/SPARQL — delegate where present (UC-52).
|
||||
|
||||
## 9. Open questions
|
||||
|
||||
1. In single-file mode, how does shard-wiki represent **per-page overlays** when writes are
|
||||
whole-file — buffer overlays and re-serialize, or require the Node `.tid` substrate for
|
||||
write-through and treat single-file as read/projection/backup only?
|
||||
2. Is a single-file TiddlyWiki's **embedded plugins/config** ever relevant to the union, or
|
||||
strictly ignored as app-internals (parse only content tiddlers)?
|
||||
3. Does shard-wiki expose tiddler **filter expressions** as a delegated query, or only its
|
||||
own union query over projected tiddlers?
|
||||
|
||||
## 10. Sources
|
||||
|
||||
- TiddlyWiki.com — *Tiddlers*, *TiddlerFields*, *Filters*, *Saving*, *Node.js* docs
|
||||
- *TiddlyWiki5* GitHub (Jermolene/TiddlyWiki5) — `.tid` file format, store structure
|
||||
- prior: `research/260614-logseq-deep-dive/` (file/DB dual substrate, UC-62)
|
||||
|
||||
## 11. Traceability
|
||||
|
||||
New UC **UC-78** carries the marker **⊡** in the wikiengines column of
|
||||
`spec/UseCaseCatalog.md`. Enriched: UC-35, UC-40, UC-34, UC-52, UC-43. Architecture
|
||||
cross-refs: SHARD-WP-0002 T11 (whole-file tier), T14 (dual binding).
|
||||
@@ -30,4 +30,5 @@ when multiple files or sources are involved. Findings here inform `spec/` and
|
||||
| 2026-06-14 | `260614-wikijs-deep-dive/` | Wiki.js — storage-module engine (DB↔Git Markdown), GraphQL API, pluggable modules ≈ adapter-contract prior art; UC-68/69 |
|
||||
| 2026-06-14 | `260614-federated-wiki-deep-dive/` | Federated Wiki — fork-with-provenance, per-page semantic-action journal (story=replay), neighborhood/roster + chorus; prior art for our coordination journal / overlay / union pillars; UC-70/71/72 |
|
||||
| 2026-06-14 | `260614-wikibase-deep-dive/` | Wikibase/Wikidata — typed entity-statement knowledge graph (claim+qualifiers+refs+rank), SPARQL/RDF + federated SERVICE, opaque stable IDs, statement-level provenance; structure & query far-end; UC-73/74/75 |
|
||||
| 2026-06-14 | `260614-forge-wikis-deep-dive/` | Gitea · GitLab · GitHub wikis — a wiki is a separate `.wiki.git` of Markdown; git-clone universal, wiki API capability-varying (GitHub git-only); git IS the store (resolves UC-68 race); the home case; UC-76/77 |
|
||||
| 2026-06-14 | `260614-forge-wikis-deep-dive/` | Gitea · GitLab · GitHub wikis — a wiki is a separate `.wiki.git` of Markdown; git-clone universal, wiki API capability-varying (GitHub git-only); git IS the store (resolves UC-68 race); the home case; UC-76/77 |
|
||||
| 2026-06-14 | `260614-tiddlywiki-deep-dive/` | TiddlyWiki — entire wiki (content + app) in one self-contained HTML file = whole-file write-granularity extreme; Node `.tid` file-per-tiddler substrate (git-diffable); tiddler/field records, filter-expression query; UC-78 |
|
||||
Reference in New Issue
Block a user