Skip to content
quarry Timeline
Login

Timeline

50 descendants and 50 ancestors of fa70fc4958db9082

2026-08-23
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

10:37
merge ticket field writes with trunk check-in: 616766e048 user: dmestas tags: trunk
10:36
tickets: write every field the schema defines

The new-ticket form rendered type/severity/priority/subsystem and the handler forwarded none of them. foundin was readable and writable nowhere. The sidebar editor listed six of nine fields. check-in: a83e03f2f3 user: dmestas tags: trunk

10:36
merge wiki-struct: structure lists get pages and name their askers check-in: 27828eeadd user: dmestas tags: trunk
10:36
docs: the structure lists get their own pages, and their askers

Three things the panel could not do. The lists were capped at twelve with "and 66 more" in plain text, which is a dead end wearing a summary's clothes — both now have a page, paged like everything else, reachable from the heading and from the count.

A wanted page named nobody. It links to the create form, which is the right action, but said nothing about WHO reached for the name — a to-do item with no brief. The index now records the asking pages and the page lists them.

Links counted link occurrences while its own doc and the tooltip both said pages; a page linking one absent name twice counted twice. Counts pages now.

Layout: the count sat 496px from its label in a 595px row, because space-between flung it to the far edge. closed check-in: af8678e35b user: dmestas tags: wiki-struct

10:05
feed chips name events, not artifacts

One ticket changed nine times is nine rows here. "tickets 93,649" against 17,000 tickets had the right number and the wrong noun. check-in: bcdf35bcef user: dmestas tags: trunk

09:58
merge feed kind fix with trunk check-in: 220dfcc70a user: dmestas tags: trunk
09:58
feed: ask the index for the kind, don't filter after

A chip counted its kind across the repository but paged a window of the whole timeline, so 234 tickets among thousands of check-ins gave ten pages with rows on almost none. Timeline takes a kind; event_by_kind covers it. check-in: 0238002099 user: dmestas tags: trunk

02:46
merge idn-base: identicons are sized by default; doc grid aligns left check-in: 720cb2b07d user: dmestas tags: trunk
02:46
web: give the identicon a base size, and align the doc grid left

Every .idn rule was scoped to a parent — .avatar, .ft-meta, .f-post-h — so an identicon used anywhere new inherited no size, and an SVG with no size fills its container. The wiki history page rendered one person's mark at the width of the screen. A helper meant to be usable wherever a person is named has to be safe by default; the scoped rules are more specific and still win.

Also drops the centring from the doc grid. It indented the block away from the page title, which sits outside the grid: on a doc page the heading started at 392px and its first paragraph at 495px. closed check-in: 717dbf0f20 user: dmestas tags: idn-base

02:39
merge doc-reserve: the contents track is always reserved check-in: e210624077 user: dmestas tags: trunk
02:39
docs: reserve the contents track whether or not a page has contents

Sizing the grid to what each page happened to hold made the prose jump sideways every time a reader clicked from a page with headings to one without. The text should sit where it sat: the contents track is now always reserved, and an empty one costs nothing but space it was going to occupy anyway.

The left rail still follows :has — a doc page has no siblings to list, and reserving a gutter for nothing is a different mistake. closed check-in: 6d2a12980e user: dmestas tags: doc-reserve

02:34
merge numbered paging with trunk check-in: a4a27d1e77 user: dmestas tags: trunk
02:34
paging: numbered pages, GitHub's shape

Infinite scroll out, a real pager in: page numbers with both ends pinned, position, and every page a bookmarkable URL. The feed pages by offset now (a page is a position, not a place you arrived from) and says how far it reaches — 264K events is not a pager, it is an archive, and that lives on each repository's timeline. check-in: 98f77c8273 user: dmestas tags: trunk

02:29
merge doc-links-abs: absolute fossil doc links render check-in: 9900339bd6 user: dmestas tags: trunk
02:29
doc: fossil's own /doc/ links land on the rendered page

fossil content links its documentation absolutely — the Cookbook has importing from Git — and the route mapping sent those to the file view. That was right when the file view was the only thing there was; since doc.get exists it has been putting readers in a source listing of a page quarry can render.

Leaves /uv/ dropped: unversioned content is a fossil feature neither quarry nor zit has, and that is why Download renders as plain text rather than as a link to a 404. closed check-in: d53f14d5b5 user: dmestas tags: doc-links-abs

02:25
merge doc-dirs: directory documents resolve to their index check-in: 9848396ba4 user: dmestas tags: trunk
02:25
doc: a directory serves its index, and falls back to the tree

Fossil's own docs link directories with a trailing slash — index.wiki carries a variety of techniques — and those all 404'd: the doc route found no renderable extension, redirected to the file view, and the file view cannot serve a directory. A real page was sitting behind the error the whole time (www/caps/index.md).

A directory now serves its index document, preferring the formats that render into the page, found with one listing rather than a probe per candidate. A directory with no index goes to the TREE view; only an actual file falls back to source. closed check-in: ff17aa2517 user: dmestas tags: doc-dirs

02:18
merge feed paging with trunk check-in: 0b79646346 user: dmestas tags: trunk
02:17
merge doc-measure: prose at the measure, wide content at the column check-in: 9426c24e62 user: dmestas tags: trunk
02:17
docs: two widths — prose at the measure, wide content at the column

At 1800px the article ended 391 pixels short of the contents rail. That was not breathing room, it was a hole: the column took 1fr while the article capped at the measure, so the leftover sat between them.

The column now sizes to its content and the block centres. Running text still caps at the measure — 73 characters a line, where reading wants 45-75 — but a code block, a table or a diagram gets the whole column, because wrapping those to prose width is what makes people scroll sideways. Measured on fossil's th1.md: prose 625px, code up to 1216. closed check-in: d11bec1130 user: dmestas tags: doc-measure

02:04
merge assoc-notes: associated wiki pages appear on their artifact check-in: 440aa464bf user: dmestas tags: trunk
02:04
wiki: show associated notes on the artifact they describe

Fossil's wikitheory.wiki: pages named branch/NAME or checkin/HASH are associated with that branch or check-in, and fossil shows them in an About section on those screens. Hiding them from the documentation index without this made 49 of fossil's 83 wiki pages reachable only by typing the URL — half the fix, and the worse half.

Notes now appear above their branch's timeline, their check-in, their ticket and their tag. A branch note shows only when the timeline is narrowed to that branch: above every branch it is a caption on the wrong picture.

Long ones start folded. Fossil's own auto-toc note runs three screens and put the timeline entirely below the fold, which is an About that has buried its subject. closed check-in: 9b9618a12f user: dmestas tags: assoc-notes

01:45
merge docs-paging: page the documentation index

Resolved twice against work that landed on trunk in parallel — the wiki structure panel and saved views. All three are orthogonal; nothing was dropped. Truncation goes, since paging replaces it. check-in: ce412bd621 user: dmestas tags: trunk

01:44
docs: page the documentation index (merged with the structure panel) closed check-in: 430e076558 user: dmestas tags: docs-paging-merge
01:41
docs: page the documentation index

Wiki pages alone did not need paging — human authorship bounds them at a couple of hundred — but the tree half is unbounded, and the old 400 cap was a dead end with everything past it reachable only by guessing a filter. Pages of 100, since these are one-line rows in two columns.

One function builds every link, so a filter, a sort, a page and the associated-wiki choice cannot lose each other; a stale offset lands on the first page rather than an empty one. The pager type is shared with the tracker now, which is what it always was. closed check-in: fa70fc4958 user: dmestas tags: docs-paging

01:29
merge docs-tab: one documentation index for the wiki and the tree check-in: 4629420231 user: dmestas tags: trunk
01:28
docs: hide fossil's associated wiki, pin the front door, credit tree authors

Associated wiki — branch/, checkin/, tag/, ticket/ — are notes attached to another artifact, shown on that artifact's page; fossil's own index hides them behind a Show associated wikis checkbox. They are 49 of fossil's 83 wiki pages, so listing them made the index 59% notes about something else. Now hidden, with the same opt-in fossil offers.

Replaces the namespace-collapsing from the previous check-in: that treated the symptom, this is the rule fossil actually defines.

The front door is pinned — a documentation directory's own index, else the README — since fossil has no per-document importance metadata and convention is the honest substitute. Tree documents now carry the author of their last change, which the batched date query was already reading and throwing away. closed check-in: 8459b994d1 user: dmestas tags: docs-tab

01:21
dashboard: what needs you, then where to go, then what changed

Leads with the tickets somebody else answered and left with you, which needs no stored last-seen. Two columns, not three: the third was the feed filtered to one author. The feed's kind chips count exactly the rows they show. check-in: 837a5c908a user: dmestas tags: trunk

01:21
docs: one index for the wiki and the tree

The wiki tab showed half a project's documentation. On fossil's own repository it lists 83 pages — 35 branch/ working notes, 7 test fixtures, and 41 real pages last touched in 2018 — while the 113 current documents under www/ had no way in at all.

The tab is now docs and lists both stores in one shape, sortable by name or recency, filterable across both. Where a page is STORED decides how it is edited, not what it is, so the source is a quiet marker on the row rather than a separate section. Namespaces of three or more pages collapse to one row that filters to itself, which is how 35 branch notes stop burying the rest. /wiki keeps working as a permanent redirect.

No count on the tab: the tree half costs a subprocess to size, and a badge reading 83 above a list of 211 is worse than no badge. check-in: 7e2839cf4c user: dmestas tags: docs-tab

01:10
merge cross-repo tickets with trunk check-in: 30fb5af0aa user: dmestas tags: trunk
01:10
tickets: one tracker page across every repository

/tickets is the same report machinery pointed at all granted trackers: repository becomes a browse axis, rows carry their own repo, and the board and New button stay behind since neither has one repo to mean. check-in: 94a2276f2c user: dmestas tags: trunk

01:05
merge doc-links: relative document links, doc images, entity fix check-in: ef1774989d user: dmestas tags: trunk
01:03
doc: relative links between documents, and their images

Fossil's docs link each other as Quick Start and those stayed literal text, so a rendered doc was a dead end. Relative targets now resolve for tree documents only — a wiki artifact sits at no path and must not emit links relative to one — and the href is left relative so the browser resolves it against the doc's own URL. Images are served as bytes under the same route the markup already points at.

Also stops double-escaping a character reference the author wrote: fossil's own index rendered "Tips & Hints". closed check-in: 44ba7c78f8 user: dmestas tags: doc-links

00:53
merge dashboard list styling with trunk check-in: fe0dc4358f user: dmestas tags: trunk
00:53
dashboard: own the list styling

The dashboard borrowed ul.tickets; when the tracker became a card it grew three boxes. Its lists are dash-list now, and a feed row shows the commit subject instead of the whole message. check-in: 86bb035b9a user: dmestas tags: trunk

00:50
merge doc-render: embedded documentation renders check-in: 96245e37e1 user: dmestas tags: trunk
00:50
doc: render embedded documentation, chosen by extension

A repository's own docs live in its tree — fossil keeps all of www/ there, not as wiki artifacts — so until now they could only be read as source. /doc/<version>/<path> renders .wiki, .md, .html, .txt and .pikchr, mirroring fossil's dispatch, and anything else redirects to the source view rather than erroring. The URL mirrors the tree path, so a relative link between documents resolves by ordinary browser rules.

Embedded HTML goes through the sanitizer rather than out as written: fossil serves it near as-is and warns about CSP, but quarry serves other people's repositories.

Closes the shape of #6ff10002. closed check-in: af13ea62ef user: dmestas tags: doc-render

00:43
merge file-version: symbolic file links resolve to their check-in check-in: f2106ce78c user: dmestas tags: trunk
00:42
file: link the check-in a symbolic version resolved to

/file/trunk/... printed "trunk" as a check-in link, which 404s. The ref now goes to zit for resolution — never the index's branch table, which answers with a branch literally named trunk and is a stale lie on any repository that renamed its default (tk). Only a symbolic ref pays for the lookup. closed check-in: d62d6dfbfb user: dmestas tags: file-version

00:41
timeline nodes take the mark's shape; a leaf stops claiming a line above it

Node measured in the rail's own weight — line, ring gap and centre dot all 2.5 — so it reads as the logo instead of a squashed version. The upward line on tips was mine: hadAbove read a rail alloc had just pointed at this commit, so every tip drew a line to nothing. check-in: f312b5951d user: dmestas tags: trunk

00:34
merge wiki-read: the wiki made readable check-in: 200d8889cf user: dmestas tags: trunk
00:34
wiki: track the contents-highlight asset

go:embed reads from disk, so the build was green locally while the file was untracked — a fresh checkout would have failed to compile. closed check-in: 5d5aa3902e user: dmestas tags: wiki-read

00:33
wiki: contents, a measure, sibling pages and a real index

Long pages were unreadable: fossil's Cookbook runs 26,000 pixels with 51 headings, no contents, and lines of ~152 characters — its author had hand-written an index at the top, which is the need stated in the only place they could state it. Headings now carry anchors whichever format wrote them (Fossil wiki passes raw HTML through, so half a fossil corpus had none), a contents rail tracks the reading position, and the measure is capped near 65.

The index gains a filter, a sort, revision counts, two columns and the Home page pinned above them. Not paged: the largest wiki in this corpus is 172 pages, and a browse list you page through is one you cannot scan.

Also fixes the global nav-link box leaking into both new rails and into the ticket rail, which drew a border around the current entry. check-in: c195eed2fb user: dmestas tags: wiki-read

00:28
timeline: branch colours cannot collide on a page

The hue was a raw hash mod 360, so two names could land a few degrees apart — ticket-list and fossil-caps rendered as one magenta. Hues now come from nine slots at least 30 degrees apart, with the mainline's blue and the accent's orange left out; a branch keeps its hashed slot unless another branch in view wants it, and assignment is by name so it never depends on commit order. check-in: a754d20b3c user: dmestas tags: trunk

00:21
caps phase 4: imported fossil users sign in, and the store path joins the wire path

Authenticate accepts an imported §6.3 credential once and upgrades the account to argon2, dropping the imported secret; a wrong guess never consumes it. quarry users pull without --url now reads the store's own table (zit#124/#125) — no credential needed for a repo we already serve. Proven end to end against a real fossil: a user who existed only there signed into quarry with their original password. check-in: 41b085ae25 user: dmestas tags: trunk

2026-08-22
20:59
merge ticket-paging: page the list and table, drop the UI .json link check-in: 63da80d3ea user: dmestas tags: trunk
20:59
tickets: page the list and table; drop the .json link from the UI

The table computed a next page and never rendered it, so a tracker over 50 tickets simply ended. Both views now page by offset with a position line and both ends drawn. Triage order is computed in Go over the fetched rows, so it stays a bounded single page rather than pretending to page.

Only PageURL sets an offset: every other control returns to page one. closed check-in: 0507def643 user: dmestas tags: ticket-paging

20:51
merge ticket-list: the tracker page rebuilt

State axis with real counts, GitHub-shaped rows, report filters in six axes, a query box that parses into them, table and board views, a browse rail, and a .json link on every report. Chips now mute the value nearly every listed row shares. check-in: a8c4a6c7f5 user: dmestas tags: trunk

20:50
merge trunk into ticket-list closed check-in: 616003aaaa user: dmestas tags: ticket-list
20:50
tickets: move the .json link out of the toolbar into the report row

It hands a scripter this filtered listing as a machine URL, which is worth nothing until there is a filter — it did not earn a place between the view toggles and the primary button. check-in: b2cac713f3 user: dmestas tags: ticket-list

20:48
timeline: the mainline always holds the leftmost rail

A branch that committed most recently was taking rail 0, and trunk was inheriting a branch's column at the fork point because the branch line followed its parents there. The default branch (timeline.list now names it) reserves rail 0 whenever it is on the page; other lines converge into it. Absent from view, nothing is reserved and the rest close up. check-in: 6b6121e609 user: dmestas tags: trunk

20:46
tickets: left rail — views, subsystems and people with open counts

Every entry is an ordinary report URL, so the rail stores nothing and promises nothing the address bar cannot say. Browse groups count OPEN work and sort by it; clicking the entry you are on removes that axis. Hidden under 64rem, where the dropdowns already reach every value. check-in: 15c58d6fe0 user: dmestas tags: ticket-list

17:16
tickets: query box, parsed into the report it spells

is:closed subsystem:web crash becomes state=closed&subsystem=web&title=crash and redirects there, so the box and the dropdowns are two spellings of one URL rather than two sources of truth. Free words match titles; an unknown prefix stays text. boardData now takes the nav instead of six positionals. check-in: 4138f81f5f user: dmestas tags: ticket-list

17:09
merge trunk (fossil user import) into ticket-list check-in: ea90352635 user: dmestas tags: ticket-list
16:57
tickets: table view with sortable columns, and a .json link

Fossil's dense report table as a third view, its headers sorting through a closed ORDER BY whitelist so a clicked column never reaches SQL from a URL. Every view carries a .json link: the same op, same parameters, the report with the presentation stripped. check-in: 306f4eec6a user: dmestas tags: ticket-list

16:54
quarry users pull: import a remote fossil's users and caps

Fetch (admin-credentialed) then import: unknown logins are created with their fossil §6.3 credential and the project code it needs, existing accounts keep their own password, categories land as categories. An unmentioned category keeps quarry's default rather than blanking into a lockout. check-in: f70144e381 user: dmestas tags: trunk

16:51
fetch a remote fossil's user table over the wire, admin-credentialed

reqconfig /user in one round trip (sync RFC §6, §9.3). The REMOTE enforces admin — a developer gets no rows, a bad password fails login, both pinned against a real fossil. Row format verified against fossil 2.28: one config card per row, quoted key/value pairs. check-in: b2ef1ce14d user: dmestas tags: trunk

16:50
gofmt: format three files carried in from trunk

subs.go was dirty because gofmt rewrites a pair of apostrophes in a comment into a typographic closing quote; reworded to say empty plainly so formatting is now a fixed point. check-in: 81e89bc4d8 user: dmestas tags: ticket-list

16:46
tickets: report filters, and chips that mute what every row shares

Six report axes as native selects in one GET form; the URL is the report, so a listing is shareable and scriptable with no query language. Counts run through the same filter and every header link preserves it.

Chips mute a value nearly every listed row shares — "Fixed" on 34 of 34 closed rows distinguished nothing. check-in: 7cfce7761b user: dmestas tags: ticket-list

16:37
merge trunk (fossil capability model) into ticket-list check-in: 7f907f987a user: dmestas tags: ticket-list
16:35
merge fossil-caps: fossil capability model native (RFC 0004 phases 1-3, 5) check-in: bd494b50d4 user: dmestas tags: trunk
16:33
tickets: state axis, counts header, GitHub-shaped rows

Replace the list op's closed bool with a three-way state (open/closed/all) and carry it through the web layer as ?state=, so filtering and the view/sort axes stay independent. Header gains real open/closed/all counts; rows get a state glyph, signal-only chips, author and comment count.

Also fixes a.btn outranking .btn-primary, which rendered every primary anchor button in the forge as a plain one. check-in: bd62e4820f user: dmestas tags: ticket-list

16:32
caps phase 5c: capability editor in settings

Per-repo category strings and per-account caps, editable in place with the expanded effective set shown beside each. CapsAdmin is an optional seam — a forge without it simply has no editor. closed check-in: b1e46974fc user: dmestas tags: fossil-caps

16:28
caps phase 5b: the capability matrix as executable spec

Each row driven twice — the letter alone must open its surface, and every OTHER letter together must not. Router resolves the repo from the request body for ops that carry it as a field (repos/update). check-in: 3df10d7f78 user: dmestas tags: fossil-caps

16:23
caps phase 5a: web write paths gate on capabilities

gateCap on every forum/wiki/ticket/technote/chat POST; caps plane separated from sessions (WithCaps) so enforcement doesn't imply a login page; an ungated forge stays ungated. Harness proves category caps reach surfaces and that removing a letter closes the same request. check-in: 54cc5168ca user: dmestas tags: fossil-caps

16:12
gofmt: comment alignment in api tests check-in: be45fccb29 user: dmestas tags: fossil-caps
16:11
caps phases 2-3: ops declare fossil capabilities; router and web gate on them

RFC 0004 §4 table encoded on all ~45 ops; RouterWithCaps refines each Auth floor with EffectiveCaps; web gates and TrustedAuthor read caps with role fallback. Harness proves o/3/a separation end to end. check-in: 31437ec328 user: dmestas tags: fossil-caps

16:01
index: ticket summaries carry author, last user and remark count check-in: b21951a839 user: dmestas tags: ticket-list
14:34
merge trunk (composer fixes) into fossil-caps check-in: 03ca7e41fb user: dmestas tags: fossil-caps
14:27
composer card clips its corners: square textarea no longer paints over the rounded border check-in: 347a061cc1 user: dmestas tags: trunk
14:27
merge fossil-caps: caps phase 1; composer hidden fix check-in: c5fe4789aa user: dmestas tags: trunk
14:19
composer: hidden wins over the split pane's flex check-in: 5498b20014 user: dmestas tags: fossil-caps
14:19
caps phase 1: fossil cap strings in OLTP, EffectiveCaps expansion, roles→caps migration

RFC 0004 §3/§5. v never implies u; a excludes s x y; s is universal; blank nobody+anonymous = private. Migration runs on every open, idempotent, never clobbers explicit caps. check-in: be3686ccbe user: dmestas tags: fossil-caps

14:18
composer: Preview tab lives in composer.js — per-composer pane, posts the draft as body; preview endpoint is a plain fragment check-in: 34e1534151 user: dmestas tags: trunk
14:13
RFC 0004: fossil capability compatibility — plan check-in: 6bb1c20891 user: dmestas tags: trunk