10 most recent check-ins occurring on or after 2026-08-16 23:49:24.
More ↑
|
2026-08-17
| ||
| 14:47 |
ci: verdicts on the timeline and check-in, live run status
Two follow-ups to the CI slice. A check-in now carries its verdict wherever it appears — a pass/fail badge on timeline cards and the check-in page, and a ci field on the API. It is read from the store's tag artifacts, not from dagnats, so it answers with the engine down and travels with a clone. A check-in with no verdict shows nothing rather than a neutral badge that would read as a result. The CI page follows runs live. dagnats' /runs/{id}/events is a JSON snapshot rather than a stream, so this polls and sends only when the rendered fragment actually differs, reusing the SSE shape the timeline and fleet already use. data-init sits on a wrapper OUTSIDE the patched element — the mistake that silently killed both other streams this morning and only showed up in a browser. Verified in a browser rather than by asserting the server is right: a commit to synthetic made the table go from one row to two with no reload. check-in: f50a282ab1 user: dmestas tags: trunk | |
| 13:13 |
ci: wire the trigger, poll runs, record the verdict as a tag
Completes the loop 0001 §6 describes. The trigger runs after each ingest fold — the moment a check-in becomes visible whatever brought it in, a local commit, a push or a sync. A poller refreshes runs quarry still thinks are going, and a terminal run becomes a tag artifact on the check-in, so CI history clones with the repository instead of living in the forge. The verdict tag is --raw, and that is not a detail: without it the name enters the symbolic namespace where it resolves to a check-in like a release name, and the SECOND check-in to pass would make 'ci-pass' ambiguous for both. zit#80 landed exactly this last night. It is written through the lease holder, like every artifact quarry mints, so two nodes cannot both record a verdict. Proven end to end against the live dagnats: a commit to synthetic launched ci/build.json read AT that check-in, the run was recorded, cancelling it drove the poller to write ci-fail with the run id as the tag's value, and the tag came back through ingest into the index. check-in: e326831901 user: dmestas tags: trunk | |
| 13:02 |
ci: the trigger half of v3 — dagnats is the engine
0001 §6 splits this narrowly: dagnats runs pipelines, quarry notices a check-in and shows the result. quarry defines nothing, schedules nothing, retries nothing. A pipeline is TRACKED CONTENT — ci/*.json in the repository, dagnats' native format — read at the check-in under test, so the pipeline for a historical check-in is the pipeline that ran and there is no forge-side store to drift. Only files directly under ci/ count; a nested path is somebody's fixture. Two behaviours worth naming. First sight of a repository takes the tip as a watermark and launches NOTHING: running a pipeline per historical check-in would be a denial of service against the engine and would say nothing about code nobody just changed — on an imported corpus that is tens of thousands of runs. And an unrecognised run status counts as still running, because claiming a run finished when it has not is how a verdict gets written against a build still going. Verified against the live dagnats for the wire shapes; the trigger itself is covered by tests. check-in: 0502a93834 user: dmestas tags: trunk | |
| 01:12 |
web: a repository has a front door — file browser and README
/r/{repo} was a 404. A repository's landing page was the timeline, which is fossil's instinct rather than a forge's, and there was no way to browse files at all: /file/{hash}/{path} served content only if you already knew the exact path, and nothing linked to it. 0002 §1 lists this as a v1 row that never got built. tree.list turns zit ls's flat path set into one directory level — a store has no directory objects, so a directory is a shared prefix and a count of what is under it — with the directory's README rendered beneath, breadcrumbs, and files linking into the existing highlighted view. The branch selector carries each tip hash, not just the name: zit permits two branches to share a name where forgejo assumes uniqueness, so a name-keyed control would silently pick one. The clone box emits the reader's own host, since a hardcoded base is wrong for every deployment but one. check-in: 7058721205 user: dmestas tags: trunk | |
| 00:57 |
tickets: display them the way fossil models them
The page dumped every folded field into one table, which read as noise and lost most of the ticket. Fossil's model has three parts and quarry was collapsing all of them into one: - Scalar state (status, priority, resolution…) folds last-write-wins. - A leading + is the APPEND form: 'J +comment more' grows the field rather than replacing it. quarry stored a separate field literally named '+comment' — sqlite's tickets use it 255 times. - icomment belongs to the CHANGE, never to the ticket. Folding it left one comment standing where a conversation was: the busiest tcl ticket showed 1 of its 84. Per-change plumbing (icomment, mimetype, login, username) no longer appears as ticket state. The page now leads with the title, shows fossil's header order, renders the description and every comment through their own recorded mimetype, and attributes each — including fossil's 'claiming to be' when the typed name differs from the login, which on an open tracker it may. Verified on tcl 408840ff: 11 clean fields, 84 comments, 5 attachments. check-in: 9ac012f7f2 user: dmestas tags: trunk | |
| 00:32 |
notify: address repo activity as a topic, with a key notify accepts
Running the real companion found two faults no stub would have. NotifyEvent.To is documented as "a user, or a repo:<name> topic", but quarry put that string in subscriberId. notify addresses the two through DIFFERENT fields, so an activity event did not fan out — it invented a subscriber literally named repo:synthetic and every watcher heard nothing. Verified against notify: the message existed, addressed to nobody real. notify also refuses a topic key containing a colon (lowercase, digits, hyphen, underscore only) and rejects the whole trigger, so quarry's own convention could never have been a valid key. repoTopicKey translates at the boundary; quarry keeps its internal vocabulary. Names differing only in punctuation or case collapse to one key, which is documented rather than hashed away — an operator has to be able to read the key they subscribe someone to. End to end on a real notify + dagnats: a wiki save reaches every member of repo-synthetic, an @mention reaches the person, and both render in quarry's inbox. check-in: 526e25a5d6 user: dmestas tags: trunk | |
| 00:19 |
notify: authenticate triggers, and embed the inbox
Two things, one of them a live bug. notify's /v1 routes sit behind an API-key middleware and quarry's client sent no Authorization header, so every trigger it fired would have been answered 401. It went unnoticed because --notify was never configured and a trigger failure is logged rather than raised. --notify-key (or QUARRY_NOTIFY_KEY) supplies it, and serve says so at startup when it is missing rather than leaving the answer to be discovered in the log. The inbox is notify's, embedded (0001 §5): GET /v1/messages?channel=in_app for the signed-in account, rendered with unread emphasised. quarry models no notification state — it displays what notify owns. The wire field names are notify's Go field names: its domain.Message carries db tags but no json tags, so the encoder falls back to the identifiers. A test pins that, since decoding lowercase would silently produce empty subjects. An outage is not emptiness: a failed fetch says notifications are unavailable instead of showing an empty list, which would be a lie about whether anyone had written to you. check-in: e33f1c4e8c user: dmestas tags: trunk | |
| 00:10 |
web: cookie sessions and a login page
Basic auth works and stays for the API, but a browser has no way to log out of it and the credential lives in the browser's keeping. A gated page now redirects to /login instead of raising a Basic prompt, the header names who is signed in and offers sign-out, and Basic remains for scripts. Session tokens are stored as SHA-256 digests, so the table cannot be read back into working cookies. Cookies are HttpOnly, Path=/, SameSite=Lax — Lax being what stops another origin POSTing quarry's write forms on a reader's behalf — and Secure under TLS. A password change or an account deletion ends that account's sessions; otherwise 'change your password' would leave the browser already holding one still signed in. Authorization for a cookie runs the same RoleOf lookup the password path uses, so a cookie is never worth more than a password. safeNext keeps the post-login redirect on this site: a reader is at their most trusting on the hop straight after authenticating, which is exactly when an open redirect pays. check-in: 7bdf7a189b user: dmestas tags: trunk | |
|
2026-08-16
| ||
| 23:55 |
index: pin the artifacts that once vanished, and check corpus parity
Two nets for the same failure: an artifact that fails to parse becomes opaque content, so the record is simply absent and nothing reports it. TestAwkwardArtifactsSurviveIngest feeds shapes real repositories contain — empty C card, empty J value, empty T value, a titled technote, a forum post with no N card — through parse AND fold, asserting the row lands. Reverting the tokenizer fix fails all three empty-token cases, so the net catches what actually happened. TestCorpusParity compares a built index against fossil's own tables and is opt-in via QUARRY_PARITY, since the corpora are hundreds of megabytes. Known differences are listed individually with reasons, so anything else fails rather than being tolerated. It found one on its first run against libfossil: a wiki-tag-propagation-test tag that looks like a page name but is a tag applied to the FIXMEs artifacts. quarry was right and the ground-truth query could not tell the difference — recorded as such. check-in: 86b845671d user: dmestas tags: trunk | |
| 23:49 |
xfer: read the project code with zit stat -R; serve bare stores
zit#85 landed, so the identity of a store is readable without a checkout. ProjectCode drops the clone handshake — free port, spawn zit serve, poll for readiness, POST a container, scrape the push card — for one subprocess that answers directly. That handshake was the last thing keeping quarry from serving a BARE store: the read plane was already -R-only with no cmd.Dir anywhere, but zit serve is checkout-only. Verified by serving a directory holding nothing but libfossil's .zit — 3,835 check-ins, and timeline, wiki, ticket, forum and technote all answer 200. Startup also loses a per-repository 5-second worst case. check-in: d7528db81f user: dmestas tags: trunk | |