50 ancestors of 69f5a86ccd538ec5
|
2026-08-24
| ||
| 19:59 |
search: forum and technote results had no link at all
They fell through hitOf's switch with no URL, so the title rendered as
— which a browser resolves to the current page. Clicking a
forum result reloaded the search. The index found them, the facet chips
offered them, and the one step that turns a hit into somewhere to go
was missing.
Their refs are not artifact hashes: searchDoc files a forum post under
its thread root and a technote under its event id, which is what a
reader wants to land on.
The test walks index.SearchKinds rather than a hand-written list, so a
kind added to the index without a link here fails instead of shipping a
dead result. | |
| 12:28 | merge timing-wall into trunk check-in: 952100a76b user: dmestas tags: trunk | |
| 12:27 |
timing: the footer reports wall time, not a sum of concurrent calls
A diff is two zit subprocesses on purpose, run at once. Adding their durations printed more time than the whole request took — "rendered in 410.1ms (zit 706.8ms×2)", and "79.94s (zit 159.05s×2)" on a cold tcl page. A number larger than the total reads as a broken page rather than as two calls overlapping. Record now takes the start instant instead of a duration, because a duration cannot say whether two calls overlapped, and the union of the spans is what a reader actually waited. closed check-in: 4aaf089616 user: dmestas tags: timing-wall | |
| 10:47 | merge people-admin into trunk check-in: f8af01dec3 user: dmestas tags: trunk | |
| 10:47 |
people: an admin sees which contributors are also accounts
A contributor is a name an author's client wrote on an artifact; an account is a login on this forge. On a mirror the two barely intersect — fossil has 151 contributors and this forge has two accounts, sharing none — so the page says so, and badges the few that are both. Read-only on purpose. A grant control here would offer to give write access to a string, and on a mirror those strings are chosen by whoever can commit upstream. The door goes to settings, where every row is a real account. account.list is forge-wide and site-admin only, so a repo admin gets the door without the badges rather than an error. closed check-in: 8fb0a669aa user: dmestas tags: people-admin | |
| 10:25 | merge repo-people into trunk check-in: 5757eeaaeb user: dmestas tags: trunk | |
| 10:25 |
people: a repository's contributors, inside the repository
"151 contributors" in fossil's About panel went to the fleet page: 481 names across 25 repositories, repo nav gone, search rescoped to the whole forge. people.list has taken a repo parameter all along and nothing in the UI reached it. The per-person line differs from the fleet's on purpose. Counting repositories inside one repository always says 1, so the span of somebody's work here is the fact worth carrying instead. Contributors(0) meant a hundred, silently, which is why the listing said "of 100" under an About panel saying 151. It means all of them now. closed check-in: 278e021086 user: dmestas tags: repo-people | |
| 09:52 | merge landing mimetype with trunk check-in: cfd042dd99 user: dmestas tags: trunk | |
| 09:52 |
landings: say the mimetype, and keep headings to one line
zit#136 shipped --mimetype, so a remark written in the composer is stored as the Markdown it previewed as. zit#138: the title card holds the whole -m message, so the heading takes its first line. check-in: 73367a3820 user: dmestas tags: trunk | |
| 09:51 |
about: the notes and announcement rows join the panel's icon grammar
Every other row in the About panel is icon + label, and .about-sub indents 1.5rem to clear that icon. These two had no icon, so their excerpt and date hung indented under nothing. A wrapping title also needs baseline alignment, or its later lines slide back under the icon. The note now says who wrote it, as the feed does. check-in: d6a6146502 user: dmestas tags: trunk | |
| 09:46 | merge notes-first into trunk check-in: 116d10e5cb user: dmestas tags: trunk | |
| 09:46 |
about: a project's news comes before its version list
Notes sat third in the sidebar, under Tags. What a project has been doing is a better first answer to "what is this" than which versions it has cut — and with no tab, this is a main door to them, which reads poorly third. closed check-in: d1dde173e0 user: dmestas tags: notes-first | |
| 09:41 |
landing page: probe the tip pair instead of scanning for the record
zit#134: landing show has to walk the whole store to FIND the record before it can answer about it, and quarry already folded that record out of its own index. zit merge --probe names the two check-ins, so the walk disappears -- 0.005s against 0.18s on this forge's own store, and the gap widens with store size, not with the number of landings. Probing the same tips the cache is keyed on also closes a race: the key was built from resolved tips while the probe re-resolved a branch name, so a push landing between the two cached an answer under a key it did not describe. An unresolvable tip now skips the probe instead of keying on ':' -- every landing whose branch could not be resolved shared that one cache entry and could be served another landing's verdict. check-in: bb05986ad8 user: dmestas tags: trunk | |
| 02:57 |
notes: the notes-filtered timeline is a door, not a dead end
Without a tab, /timeline?y=e is where somebody browsing notes stands, and it offered no way to the page that reads them as a feed. The other two doors — the About panel and the docs page — are not where a reader who just filtered a timeline is looking. check-in: 16e8738cb6 user: dmestas tags: trunk | |
| 02:40 | merge forum/landing separation with trunk check-in: f0f4f7c525 user: dmestas tags: trunk | |
| 02:39 |
forum: landings are not forum content
A landing is a forum thread — that is what a stock fossil clone reads — but it is a decision record with its own surface. Off the listing and out of the count, which must agree. An existing thread URL redirects to the record rather than 404ing a link that used to work. check-in: 302ca7fae6 user: dmestas tags: trunk | |
| 02:39 | merge notes into trunk check-in: 1ff2886793 user: dmestas tags: trunk | |
| 02:38 |
notes: one row per technote, not one per edit
Fossil registers one timeline event per technote; quarry registered one per artifact. libfossil has 50 technote artifacts under 26 event ids, so its timeline showed a superseded title five rows above its own correction. The collapse is in the event trigger — insert, then evict every loser for the event id — which is order-independent, as the fold requires: a clone delivers artifacts in wire order. Notes are no longer a tab. Fossil's built-in menu has none, and libfossil, which uses them as a milestone feed, overrode mainmenu to add TODOs and FIXMEs without adding one. They are reached from the About panel, the docs page and the timeline filter instead, and the listing is a feed with excerpts rather than a list of links. Every edit stays readable, as a wiki page's revisions are. Fixes an authoring bug found on the way: zitcli never passed --time, so an edit re-filed the note at the moment it was edited and it moved in the timeline. The filing time is now a field on both forms. closed check-in: ac80214995 user: dmestas tags: notes | |
| 02:34 |
spectrum: separate colliding voices by lightness, never by hue
Two names whose hues land 7 degrees apart painted one block. Near collisions are a birthday bound, not bad luck, so the bar resolves what is in the thread — stepping a colliding voice to the identicon's other lightness. The hue never moves: it is the identity. check-in: e1e9619d0d user: dmestas tags: trunk | |
| 00:06 |
pages must be revalidated, not guessed at
An HTML response carried no cache directive and no validator, which does not mean do not cache — it lets the browser choose a freshness lifetime. Safari chose one, and served a timeline rendered before a deploy while the server answered with another; the reader sees stale state with no way to tell. no-cache rather than no-store: the copy is still kept and reused after revalidation, so the back button stays instant. Only reuse without asking is wrong, and every one of these pages is a view of moving state. check-in: ece3b20f3d user: dmestas tags: trunk | |
|
2026-08-23
| ||
| 23:43 |
docs list: a byline inside a link stays plain
An anchor inside an anchor is invalid — the parser closes the outer one at the inner, which tore every docs row in half. The docs list and the wiki home card are whole-card links, so their bylines go back to plain mark-and-name; the row already goes somewhere. a.who is inline rather than inline-flex for the same family of reason: a flex box is atomic and cannot flow with the text around it. check-in: 01e7bce146 user: dmestas tags: trunk | |
| 23:34 |
state the page's own address, so enhancement works behind basic auth
A URL with credentials (http://user:pw@host/) leaves them on document.baseURI even though location is cleaned, and fetch() refuses any URL carrying credentials — so every enhancement failed at once: diff toggle, unread poll, diff sentinel. A server-stated <base> fixes all of them without script, since the server knows the URL from its own routing and never from userinfo. The toggle also swallowed its own fallback: replaceState to a credential-free URL throws on such a page, and it ran before @get while __prevent had already cancelled the link — neither swap nor navigation. Cosmetics now cannot fail the click. check-in: c35d8c4b5b user: dmestas tags: trunk | |
| 23:14 |
a person is a link: identicon and name go to their timeline
Fossil routes every surface through one helper (hyperlink_to_user); quarry had thirty-two places rendering a name and none of them clickable. One 'who' helper now, applied to the twenty that name an author — the account button and participant stacks stay decorative. timeline.list gains user=, paired with y=all: what someone did includes their wiki edits and ticket changes, not just check-ins. check-in: a18be6d78d user: dmestas tags: trunk | |
| 23:08 |
timeline: internal nodes match the leaf's painted size
The ring is stroked 2.2, so it paints to r+1.1; a 4.8 disc beside it read a fifth smaller. Internals are the ring's outer edge, filled. check-in: e1f3ed4bac user: dmestas tags: trunk | |
| 22:37 |
markdown: a mention reads like a byline
Mark then name, in the page's colour, orange on hover. The sigil is syntax and the mark already says this is a person; a name that is orange everywhere stops meaning clickable anywhere. check-in: dda6810776 user: dmestas tags: trunk | |
| 22:31 |
markdown: mentions carry the identity mark, quotes are visible
An @mention now renders the same glyph as the person's byline, through the resolver seam so markup still knows nothing about accounts. The identicon moved to internal/idn — web and api each hashed the name separately and agreed by luck. Blockquotes had no rule at all. check-in: 0ba22dea9e user: dmestas tags: trunk | |
| 22:19 |
landings: the forum's post card, and the tracker's list
f-post-h and f-post-b are where the padding lives; naming the wrapper alone gets a border round unpadded text. Check-ins use the same bordered list every other listing in the forge uses. check-in: 20373a1806 user: dmestas tags: trunk | |
| 22:13 |
landings: use the shared composer frame, collapse the diff
The composer's textarea has no border of its own — it is built for the f-reply wrapper the ticket page and forum use, and without it the tabs and text floated unframed. The diff is a details now: this page is where a decision is made, and 600 lines between the proposal and the buttons means scrolling past the change to reach them. check-in: 59d7d8fa4c user: dmestas tags: trunk | |
| 22:04 |
merge trunk: landings
Textually clean, but branchTipOf called Timeline with the old positional signature — ported to TimelineFilter. check-in: dae2180a89 user: dmestas tags: trunk | |
| 22:03 |
check-in page: tag history, branch diff, manifest view
Fossil lets an author correct a check-in comment after the fact; quarry showed the superseded C card as if it were current, on 697 fossil check-ins. The correction is now applied at read, batched in AttachCI, with the original kept beside it — the stored card is an artifact fact and stays untouched. hidden and closed surface too. Branch diff is the branch against its fork point, which is not the landing page's base (the target's current tip). Offered only where a fork point exists. The manifest view renders the eight cards that are not the file list and counts the other 980, linking the tree. Also: unified/side-by-side now swaps in place via datastar, keeping the window and correcting the URL; the wiki note panel lets blocks use the full width while prose keeps its measure. check-in: ff7f5d3d69 user: dmestas tags: trunk | |
| 22:01 |
landings: a way to open one, and the lifecycle written down
docs/landings.md covers the whole loop and says plainly that a landing is a forum thread plus branch tags. Writing it found the gap: there was no create control at all. A mirror offers its upstream instead. check-in: c6aa693938 user: dmestas tags: trunk | |
| 21:50 |
landings: prove the lifecycle end to end
open, comment, reject, accept through the forge against a real store — accept merges to trunk via zit#131's bare-store path. Also checks the record still reads as an ordinary forum thread. check-in: 9a84a5d962 user: dmestas tags: trunk | |
| 21:43 |
landings: memoise the mergeability probe on the tip pair
The probe is a full-store scan by design and measures 2.0s here, paid on every view. Keyed on the two check-ins, so a push invalidates it by making a different key rather than by anyone clearing a cache. 1.9s cold, 50ms warm. check-in: 21d510a5bd user: dmestas tags: trunk | |
| 21:38 |
landings: list the branch's check-ins
A proposal is changes with reasons attached; a diff keeps the changes and throws the reasons away. zit#133's display half, from our own index. check-in: 120277efc7 user: dmestas tags: trunk | |
| 21:35 | merge landing mergeability with trunk check-in: 537889b661 user: dmestas tags: trunk | |
| 21:35 |
landings: read mergeability from the store, never from an attempt
zit#131 landed the probe and exit 5. A conflicted landing renders as blocked with its paths named and accept disabled; a refused accept is a state to show, not a fault to report. Unknown is never treated as clean. check-in: e0f59b6abf user: dmestas tags: trunk | |
| 21:06 |
check-in page: patch link, full hash + copy, tags, change stats
Stats are tallied at parse time so a windowed diff reports the whole file, and sit on the file header as well as the summary line. Tags come from checkin_tag, newest word per name winning. Copy falls back through execCommand to selection: navigator.clipboard is undefined on the plain-HTTP origins quarry is usually served from. check-in: ac056aaa1d user: dmestas tags: trunk | |
| 20:11 | merge idn-open: identicons everywhere, About note expanded check-in: ff7c8babbe user: dmestas tags: trunk | |
| 20:11 |
web: identicons on every name, and the About note opens by default
The timeline already had them; the ticket list did not — its row uses .Created and my earlier pass patched a different template that uses .Opened. Also added to ticket timeline entries and the forum queue. The note is no longer folded when long. It was folded past ~1200 bytes because fossil's auto-toc note runs three screens and pushed a timeline below the fold, but a note written about this artifact is the context you came for. The summary stays, so it can still be collapsed; the threshold and the NoteLong field it fed are gone rather than left dead. closed check-in: eb1f126e04 user: dmestas tags: idn-open | |
| 20:02 | merge ci-context: context panel, graph nodes, identicons check-in: f78fd539af user: dmestas tags: trunk | |
| 20:01 |
check-in: context panel, graph nodes, identicons on every name
Fossil's Context panel: the check-in among its neighbours in time, which is the question somebody bisecting a regression is asking. Two bounded index walks, no store read. Needed a new index — every index on checkin led with branch, so ordering by date alone was a full scan of 20,928 rows plus a sort, twice a page. checkin_by_date puts the panel back at ~10ms. Nodes reuse the timeline's palette so a branch is one colour across the forge. One lane deliberately: three neighbours are a slice of time, not a graph. On a phone the row stacks and the drawn rail becomes a border, since an SVG node cannot stretch without distorting its circle. Identicons now appear wherever a person is named — check-in metadata, context rows, timeline, technotes, chat, attachments, wiki history. closed check-in: f73b5b9f05 user: dmestas tags: ci-context | |
| 19:19 | merge landings with trunk check-in: 8a034b58c7 user: dmestas tags: trunk | |
| 19:17 |
landings: the decision surface
A list of what awaits a decision and a page per record: proposal, diff against target computed at view time, discussion, and the controls. accept rides `i` because it merges; everything else is a forum cap. Transitions render as events — zit stores them as replies, which is encoding the interface exists to hide. check-in: 7d2a820f65 user: dmestas tags: trunk | |
| 14:28 | merge checkin-page: comment links, About placement, diff payload check-in: 071724226f user: dmestas tags: trunk | |
| 14:28 |
check-in: link comment routes, move About, stop shipping a dead patch
Comment links resolved only hashes and http URLs, so fossil's own Markdown and limitations rendered as raw markup. They now go through the same route table the wiki renderer uses, and an unmapped one degrades to its label instead of showing brackets. About moves below the comment and metadata — fossil's order. Above the title it was an empty bar floating over the page name. checkin.diff returned the raw patch on every call and nothing read it: ~78KB of duplicate serialised and parsed back per view. Now opt-in. Diffs are also memoised per immutable pair, like listings already are. closed check-in: 7a2510835d user: dmestas tags: checkin-page | |
| 13:50 | merge struct-links: wanted and unlinked reachable from the filter row check-in: c9c04092a9 user: dmestas tags: trunk | |
| 13:49 |
docs: surface the structure lists where they can be found
They were reachable only from a panel at the foot of the page — 36 rows down on a small wiki, a hundred on fossil. That is where you put something a reader already knows about, not where they discover it. Counts now sit in the filter row: wanted 1, unlinked 7. closed check-in: 6554752b15 user: dmestas tags: struct-links | |
| 13:42 |
index: fold landing records into a queryable surface
A landing (zit#127) is a reading of forum_post, not a new artifact kind, so the table is derived and recomputed whenever any post in its thread folds -- which is what makes a reply indexed before its root converge on the same row. Backfilled once at open for indexes whose posts predate the table. check-in: 3c6bee847a user: dmestas tags: trunk | |
| 12:31 |
timeline: the mainline claims rail 0 only when it is free
A merge whose two parents are both on trunk puts two chains in front of one column. Claiming rail 0 anyway stopped drawing the line that was already travelling there — the gap — and overwrote the commit it was heading to. Test asserts every head resumes its predecessor's tail. check-in: 6f34d948a0 user: dmestas tags: trunk | |
| 11:08 |
caps: private tickets exist for holders of e
The edge resolved a CapSet and threw it away; it now rides the context, so an op can ask which letters the caller holds. Private tickets list, count and resolve for e, and for nobody else. One privacyWhere() so a fourth read path cannot silently ship without the clause. check-in: 9b2b188ece user: dmestas tags: trunk | |
| 11:02 |
caps: gate private ticket fields on e instead of dropping them
The capability exists now (RFC 0004), so private_contact and contact are withheld by default and rendered to a holder of e. Default deny with no ungated-forge exemption: that rule would publish them. check-in: 86fadebbab user: dmestas tags: trunk | |