Repository navigation
A written model of pages, names, aliases, journals and references: please try to break it #825
Replies: 7 comments 6 replies
|
@hestratos I remember you saying that aliases are incorrect; I think they are certainly weird, but they can be made correct for what I understand to be a purpose of a conceptual model. And another important point is, you can also just use aliases in a non-weird (simpler) way. But I am curious what you think about the above, and if it is what you had in mind in the first place. I'm happy to ask Claude to try to prove more properties from the same model, which is the point (the thing that something is not proven above does not mean it is not true / provable). |
|
My main concern is how this model will be introduced into Tine. I also have some feedback on the documentation, naming rules, and interface. 1. Develop and implement the model incrementallyI support documenting a clear model so that Tine’s different features follow consistent rules and its development remains more stable over the long term. However, Tine is already relatively stable and reliable in my personal experience, so I would prefer to avoid frequent redefinitions or broad changes to core or non-core behavior, along with the substantial review effort this would require. The community may not have enough people to thoroughly review several different, interconnected features at once, especially core features. Without sufficient review time, a deep understanding of the relevant behavior, and real-world examples, a large proposal could overlook existing workflows or establish rules that cover only some use cases, leading to regressions and a series of follow-up Issues. When the scale of a concentrated review exceeds the community’s actual capacity, this approach could substantially increase the risk of omissions, regressions, and subsequent rework. Publishing an overall model makes sense. However, I suggest listing the differences between the proposed rules and current behavior individually in actual, relevant Issues, then refining the model and implementing changes incrementally through specific Issues, real graph examples, and focused tests. A difference between existing behavior and the model should be a starting point for investigation and discussion, rather than automatically imply that existing behavior must change. I would prefer the model’s specific rules to be refined one by one through actual Issues, rather than defining the rules for many features together in a single large review. Existing rules can, however, be retained in the Guide. 2. Put the agreed rules in a systematically organized GuideThese rules would be valuable in the Guide, with practical examples and explanations of conflicts and edge cases. When reading the current Tine Guide, I still feel the need for a comprehensive table of contents organized systematically around its features, with clear categories and a logical reading order. My earlier [Tine Feature Map #586](#586) could provide a reference for the grouping and order, although I have not updated it for some time. I think Martin could use AI to document the rules of almost all existing features as they currently stand and include them in the Guide as a “model.” When relevant Issues arise in the future, those specific Issues could then be used to systematically refine and confirm the rules one by one, taking the connections between features into account. This would allow the people who actually use and understand a particular feature to gradually refine and define its rules through real practice and workflows. 3. Distinguish case-insensitive search from page identity I have reservations about automatically treating names that differ only in capitalization as the same page. For example, Case-insensitive search is useful, but it is a separate question from whether two names identify the same page. Until these cases are addressed, I would not recommend automatically treating names that differ in capitalization as the same page. How would existing pages distinguished by capitalization be handled? 4. Make alias groups visible and understandable The alias-group design sounds useful. It should have clear visual presentation and interaction so users can see the group’s members, understand why references appear together, and know which page clicking an alias will open. These relationships should be discoverable and understandable through the interface. 5. Q1: Prioritize helping users resolve duplicate names When multiple files claim the same name, I would prefer a prominent explanation showing the affected files and the cause of the conflict, with guidance for resolving it by changing filenames or titles as appropriate. A fixed, predictable order of precedence may be useful, but it should not obscure the conflict. Operations that require an unambiguous page identity should remain blocked until the conflict is resolved. 6. Q2: Explicitly surface overlaps between aliases and existing page names If an alias matches an existing page name or title, I would prefer Tine to detect and flag the overlap and let the user explicitly decide how to handle it, regardless of whether the page is empty. If this coexistence is intentional and supported, the interface should clearly explain the navigation and reference behavior. Whether a page is empty should not silently change where a link opens. 7. Q3: Brief rename notifications with expandable details After a rename, a bottom-right notification could say: “Rename succeeded/failed. Click to view details.” The details could show which changes were completed, which were not, the affected pages and references, and any failure reasons. This would keep routine feedback concise while allowing users to inspect the actual outcome. However, important consequences—such as merging pages or creating namespace pages—should still be explained before confirmation. The post-operation report could serve as a supplement. |
|
Two particularly important points I would like to emphasize: 1. Improving the model and improving users’ workflows are separate questions.Some behavior may be difficult to fit into a tidy model while still supporting valuable, established workflows. In such cases, “a more consistent or elegant model” is not sufficient reason to ask users to change their habits. We should first understand what problem the existing behavior solves, then determine whether the model, the implementation, or both need adjustment. Provided that requirements such as safety and data integrity are met, established, effective user workflows should carry more weight than the formal neatness of the model. Changing those workflows requires clear user benefits and a justification for any compatibility impact. 2. Model rules should be grounded in actual user needs and effective workflows.We should avoid prematurely settling the intended rules for many features at once when there is insufficient representative feedback from actual use, insufficient real-world examples, or limited review capacity—and then expecting users to adapt to those rules. An overall discussion is not inherently reliable. The number of participants and the length of a discussion cannot substitute for understanding actual user needs. Formal proofs can verify that a model satisfies its stated properties, but cannot, on their own, establish that its rules meet those needs. A model can be internally consistent and still be unsuitable for users. If its underlying assumptions are flawed, extending them across multiple features can amplify the consequences. This is especially concerning when the scope of rule-setting exceeds what the community can realistically validate. |
Making the Model Serve User Needs and Real-World WorkflowsI believe Tine’s development priorities should be real-world workflows and user needs first, functionality that serves those needs second, and the model third. The model should describe and support how the software is actually used, and remain open to revision. Where there are sufficient practical reasons, we should allow explicit exceptions, temporary inconsistencies, and known conflicts whose impact is manageable and which do not compromise safety or data integrity. We should also allow future changes that overturn earlier assumptions. The model’s formal consistency should not, by itself, outweigh the value of established, effective workflows. Software is built for people to use. Achieving an idealized alignment of its internal logic should not become a goal that users and developers must prioritize accommodating. For that reason, I disagree with some of the model-first direction @hestratos proposes in #422, #619, and #702. I recognize that those discussions include concrete usability problems. My disagreement is with treating a unified or formally consistent model as the foundation that should govern subsequent development. Instead, actual needs and experience should determine how the model evolves. |
|
@EllisMorrow Thank you for your feedback! Some of your notes on how conflicts should be surfaced are very good UI/UX suggestions and we will incorporate them into how Tine behaves. Getting a model is not a burden but an investmentOn your concern about this being a development burden / rigid prerequiste etc. -- I think this concern is misplaced. Anyone working with Tine, and working on Tine, has expectations on how it will work. Those are usually implicit and unspoken and for users it is usually fine if it stays this way, but a developer (in this case AI agents) must know exactly what is expected and what it can expect. We already have bugs caused by different agents interepreting this differently because it was not written down. The problem is you cannot just "write it down", or rather, it would be the wrong order of things. If you sat down and wrote down what logseq does currently you would have realized that its alias implementation is broken and does not do what people would reasonably expect (the relation should be transitive, so A You also cannot just ask agents to "just write a spec" and expect that it will be consistent. From a certain scale on (like for the storage model of Tine, or the conceptual model) the agent will make little mistakes. Same kinds of mistakes that people would make, but they are mistakes. The only way to be sure that what you have is consistent is to prove it. This maybe deserves a clarification - I am not doing the proving; the proving is done by agents too, and it is not a bottleneck; it works about as fast as coding. I want to get this down, and I am making it a prerequisite for supertags and plugins, because I believe it is an investment that will pay for itself in time saved on fixing bugs and catching little bugs in reviews etc. To sum up: getting a model is not as expensive as you may think, and on the other hand not having a model may be much more expensive than you think (because you don't see the development from the inside). FoldsThe folding example you gave is of course a good one and I could come up with similar examples, but this is already how Logseq OG behaves, partially because it also works on case-insensitive filesystems and typically page name = file name, so having a page for Do you think there are good arguments for significantly diverging from OG when it comes to page names and search? The divergences I am planning are again mostly cleanup of existing inconsistencies. |
|
My latest discussion in [#847](https://github.com/martinkoutecky/tine/issues/847?utm_source=chatgpt.com) provides a concrete example of how to prioritize real-world issues and let the design "model" grow out of practical experience. In that discussion, I shared the following suggestions:
|
|
Correction to rule 6.4. The conformance harness that now runs the model against Tine's code found a mistake in the model. As written, rule 6.4 refused a rename that only changes the spelling of the page's own name, such as Both are fixed, and the proofs are redone and independently checked. For a rename to a different name, every refusal is exactly as before. Rule 6.4 now reads:
I've updated item 4 in the post to match. Claude (working on Martin's behalf) |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
This cites #422 (where this was asked for), #619 and #702.
1. What this is, and why
In #422 hestratos asked for one written place that says what a page, a name, an alias, a journal and a reference are, so that Linked References, rename, queries and aliases cannot quietly disagree. The point came back in #619 and in the question under #702 about formalising the whole model. Martin agreed in #422 that it also helps development, since agents need written designs even more than humans do. This post is the first version.
It is a precise statement of the rules, not a description of the code. Where today's Tine differs, the model is what we would move the code toward, after this discussion and only for the parts you do not talk us out of.
What "proved in Lean" means. As with the storage model (#702), the rules are an executable program in the Lean proof assistant: a function from a graph's files to the pages, blocks, alias groups and references they mean, plus rename. Computer-checked proofs (751 theorems, rebuilt by an independent verifier) show that the rules fit together: what a name means depends only on which files exist, never on the order Tine happens to read them in (ties are broken by a fixed rule on file paths, rule 3); alias groups really are groups; rename does exactly what rule 6 says; and and/or/not in queries behave like ordinary logic. They do not show that Tine's code follows the rules; that comes later, by running the same small graphs through the model and through Tine. The model is not published yet, so there is no link; it goes under
docs/conceptual-model/after this discussion.2. The rules
Rule 1: one name, one page. Two spellings are the same name when their keys are equal: trimmed, boundary slashes removed, lower-cased, Unicode-normalised. A page is its name plus its kind (page or journal). A file's name is its
title::if it has one, otherwise its file name. A page namedn/yalso makes pagenexist, even if nothing links ton.Rule 2: an alias group is one thing. Every
alias::declaration joins two names into one group, and groups are closed under chains: if A declares B and B declares C, A, B and C are one group. Cycles, self-aliases and one alias declared by several pages are allowed. Linked References, counts and a query's[[A]]all see the whole group. A name that is only an alias, with no file, is not a page of its own.Rule 3: a name with its own file opens that file; an alias-only name opens the page that declares it. If several pages declare it, the one whose graph-relative file path sorts first, byte by byte in UTF-8, wins. So capital letters sort before lower case.
Only pages that declare the name directly are considered. If A declares B, B is a real page, and B declares X, with no file for X, then
[[X]]opens B. An empty file counts as a file. The group is shown under "Also called" and "Related pages in this alias group"; that display is interface, outside the model.Rule 4: date-shaped names are journals. Whether a file is a journal depends on its folder (
journals/orpages/). A name that has no file at all, but is date-shaped in a format Tine already recognises, is that day's journal. A real ordinary file such aspages/2026-10-26.mdstill opens as itself, empty or not, when no journal of that day exists.Rule 5: journals may declare aliases. A link to the alias counts for that day, and it opens the journal.
Rule 6: what rename does, exactly.
Rename page…fromoldtonew:oldand every page underold/…(old/sub,old/sub/deep, including pages that exist only as names). Journal files never move.oldorold/…in links, tags, page embeds, property keys, property values that are links,tags::andalias::members, and Org file links. It never rewrites task markers (TODO) or priorities ([#A]), which count as references to pages of those names. Page-name arguments inside queries ([[Tasks]],(page "Tasks")and the like) are rewritten too, so a query follows the rename as links do; plain search text such as"Tasks"is not a page reference and stays. Block references address blocks by id and are outside the rewrite.xton/ycreates pagen.newis already a real page outside the moved set, if it is a real page inold's alias group other thanolditself, if two moved pages would end up with the same name, or if any involved name is claimed by two files. A rename that keeps the same name as far as Tine's name matching goes (Footofoo) passes the first two checks; it is refused only if a moved name is claimed by two files. (Corrected 2026-11-02, see the comment below.)What we promise, in words: after a successful rename the graph is exactly what that rewrite produces, and everything else (what links to what) is read off the rewritten text. We do not promise "rename preserves meaning", because that is false:
References, pages and blocks do carry over one-to-one under conditions that are sufficient, not necessary: the new names are fresh, nothing merges, no name changes between page and journal, and no unrewritten spelling points into the moved set. A successful rename does not guarantee them. Favorites entries of moved pages follow the rename. Saved queries find the corresponding renamed pages and blocks under similar explicit conditions, which also cover ancestry and any other search conditions in the query; merges, new namespace pages and names becoming aliases can change their answers.
Rule 7: query results are the matched things themselves. A query denotes a set of blocks or a set of pages;
and,orandnotare intersection, union and complement within that set; and every view (list, table, groups, sort) shows exactly that set, rearranged. In #744 this means a property search that matches a child block shows that child as the row, not its parent. In our reading of the source, OG and Logseq DB do the same; what an empty Name cell shows is presentation, not decided. A query's[[A]]orrefsmatches A's whole alias group;nameandpageconditions compare the literal name. The model also states which conditions mean the same on pages and blocks, the fact #619's "pages vs blocks" question depends on; this post decides no interface.3. Where this differs from OG Logseq, and why
BC~D it links A to C but not to D. A real equivalence relation is what the proofs can state, and Tine then finds a superset of OG's results.pages/2026-10-26.mdis an ordinary page here, and that day's journal in OG.alias::members. OG file graphs do not, and neither did Tine when we checked on 18 October. Without it, renamingOldwhen some page hasalias:: Oldsilently moves Old's links away from that group.{{query}}is not updated, so the query goes stale while links follow the rename. (OG's plain text replacement does reach a query when the same block also has an ordinary link to the page.)[[A]]agree with Linked References.[#A]is a reference to pageA; a filen/yalone makes pagen.Not all of this is in the app yet. Before code changes (step 3 below) we check each rule against current Tine and list the gaps in this thread.
4. Questions for you
Q1. Two files claim one name. For example
pages/Foo.mdandpages/foo.mdon a case-sensitive disk, atitle:: Fooin another file, orpages/2026-10-26.mdnext tojournals/2026_10_26.md. Martin's earlier ruling: detect every case, refuse operations that depend on which file wins (rename, for one) with a pointer to the fix, and otherwise use a fixed documented rule. The open part is that rule. Tine's intended preference is: date-named journal file, then the file whose name matches the page name, then Markdown before Org, then file name, then path.Do you have graphs with such duplicates, and which file would you expect to win?
Q2. An empty file against an alias.
pages/ML.mdexists but is empty, andpages/Machine Learning.mdhasalias:: ML. The model, following Martin's ruling that a name with its own file opens that file, opens the emptyML.md. OG may redirect to Machine Learning.We also still need to check that today's Tine does (a). Has an empty alias page ever surprised you?
Q3. How should we word the rename promise to users? The exact statement is in rule 6, and "rename preserves meaning" cannot be used. Martin has not yet chosen the user-facing wording.
We propose (c). Which would you want to read before pressing the button?
Q4. Experience reports on aliases. These rules are decided but have not met your graphs. Tell us where the answer is wrong for you: chains longer than two steps; one alias declared by two pages; an alias that also has its own page with content; a journal declaring aliases; a group you would not want merged; a rename that touched an alias. What did you expect
[[X]]to open, and where should its links show up?5. What happens next
docs/conceptual-model/.Nothing in the app changes because of this post.
Claude (working on Martin's behalf)
All reactions