13 check-ins that include changes to files matching 'docs/site/content/*'
|
2026-10-13
| ||
| 15:25 |
feat(sync): add share-links mode for pragma req-links and link (#428)
* feat(sync): add share-links mode for pragma req-links and link sync-protocol-01 Section 9.5 makes share-links mode OPTIONAL. With SyncOpts.ShareLinks a pulling session sends pragma req-links in its first request, as fossil's --share-links does, unless SyncOpts.ProjectCode names another project. It keeps each pragma link URL ARG MTIME as config link:URL = ARG, defossilized and otherwise verbatim, replacing an existing link only with a strictly newer MTIME. A wrong token count, a URL that is not HTTP(S) or an MTIME that is not a positive decimal drops the link. Where fossil 2.28 differs the draft is followed: fossil fails fatally on a link URL its parser rejects and reads MTIME with strtoll base 0. New sync.9.5 client cases run against fossil sync --share-links as well. SP-9.5-4 loses its scope note and is covered; SP-9.5-5 and SP-9.5-6 are new rows for which links a client keeps and when it sends req-links. Tracked in #425. * test(sync): cover links in later rounds and push+pull req-links; match project code case-insensitively check-in: 5473c06942 user: [email protected] tags: main, trunk | |
| 14:49 |
feat(sync): add share-links mode for pragma req-links and link
sync-protocol-01 Section 9.5 makes share-links mode OPTIONAL. With SyncOpts.ShareLinks a pulling session sends pragma req-links in its first request, as fossil's --share-links does, unless SyncOpts.ProjectCode names another project. It keeps each pragma link URL ARG MTIME as config link:URL = ARG, defossilized and otherwise verbatim, replacing an existing link only with a strictly newer MTIME. A wrong token count, a URL that is not HTTP(S) or an MTIME that is not a positive decimal drops the link. Where fossil 2.28 differs the draft is followed: fossil fails fatally on a link URL its parser rejects and reads MTIME with strtoll base 0. New sync.9.5 client cases run against fossil sync --share-links as well. SP-9.5-4 loses its scope note and is covered; SP-9.5-5 and SP-9.5-6 are new rows for which links a client keeps and when it sends req-links. Tracked in #425. check-in: a565d1c467 user: [email protected] tags: trunk, feat/425-share-links | |
| 10:59 |
feat(repo): set the hash policy by name (#408)
artifact-format-01 7.1 (AF-7.1-2) matches policy value strings case-sensitively and exactly and makes an unrecognized value fatal. No surface took a value string, so the row stayed partial. Repo.SetHashPolicy takes sha1, auto, sha3, sha3-only or shun-sha1, as fossil's hash-policy command does with fossil_strcmp, stores the ordinal, and refuses any other string without touching the stored policy. Auto in a repository that already holds a SHA3 artifact stores sha3 (7.3). New conformance cases drive every name, wrong-case names, unknown names and the empty name through it, and the AF-7.1-2 scope note is dropped. check-in: feea6a1614 user: [email protected] tags: main, trunk | |
|
2026-10-12
| ||
| 20:17 |
fix(checkout): make WouldFork fossil's commit-time fork check (#347) (#348)
Since #291 WouldFork was fossil's leaf_ambiguity, which answers no at once for a version that is not a leaf. That is the case a commit forks in: when a pull brings in a child of the checked-out version, the version stops being a leaf, WouldFork said false, and the commit became a second child. EdgeSync's autosync relies on WouldFork to refuse that commit. WouldFork is now fossil's commit refusal (src/checkin.c "Would fork", taken when !is_a_leaf(vid)): true when the version has a child on its own branch, read from plink as is_a_leaf does, merge children included. Another open leaf elsewhere on the branch no longer counts; fossil commits there, extending the checkout's leaf, and only warns afterwards. The repo-state draft's Section 7.5 ambiguity test moves to checkout.LeafAmbiguous, and the repostate.7.5.ambiguity-* conformance cases call it. The superseded #291 changelog text and the WouldFork API doc are corrected. check-in: cd4a11828f user: [email protected] tags: main, trunk | |
|
2026-10-06
| ||
| 15:57 |
fix(checkout): merge the way fossil does, and commit merges with their parent (#244) (#252)
The CLI's merge marked a conflict with vfile.chnged=5, which fossil reads as "added by integrate", and recorded no merge-in version or vmerge row, so a merge went unseen and the next commit dropped the merge parent. Merging now lives in the library as Checkout.Merge and records what fossil records: chnged=2 and mrid for a file taken from the merged-in version, chnged=3 for an added file, a per-file vmerge row for a merged file, and vmerge id 0 for the merge. Conflicts use fossil's markers and are found by looking for them (Checkout.Conflicts), so fossil and go-libfossil read each other's merges. Where fossil relies on its undo copy, Merge keeps the file or refuses instead. Commit reads vmerge for merge parents, and, as fossil's commit does, refuses unresolved conflict markers, empty commits, unknown names and partial commits of a merge. The CLI's merge, conflicts, mark-resolved and ci commands call the library; ci now commits the checkout. check-in: 7ea6fba63f user: [email protected] tags: trunk | |
|
2026-07-29
| ||
| 01:46 | feat(cli): select sqlite driver by tag (#218) check-in: ac4c3537d1 user: [email protected] tags: trunk, v0.8.0 | |
|
2026-07-27
| ||
| 19:19 |
test: add corpus parity gate comparing clone output against canonical fossil (#188) (#191)
The per-package parity tests compare our derivation against fossil's for fixtures built in-test, so they only cover the shapes someone thought to build. Issue #184 -- a silent 100% loss of the ticket-change artifact shape (D,J,K,U,Z) -- passed that suite throughout and was found by an external benchmark cloning the real Fossil repository. Add TestCloneCorpusParity, which builds a repository with the canonical binary, serves it over loopback, clones it with both fossil and libfossil.Clone, and compares what each derived. The comparison is per-event-type, not just totals. On the real Fossil repository the totals read 23,396 vs 27,099 -- a 14% shortfall that reads like rounding -- while the per-type breakdown put ticket events at 96 vs 3,808. Totals for blob, event, mlink, plink, tagxref and leaf are compared too, with deltas reported in both directions: our tagxref ran +17,119 over fossil's there, which is what writing a tag without finishing the work it marks looks like. The corpus is built by the canonical binary at test time rather than downloaded -- seconds and under a megabyte, against the ~10 minutes and ~1 GB the real repository costs (#187) -- and covers check-ins with a branch and a merge, ticket creations and updates, a wiki page, a technote, an attachment, and a tag control artifact. requireCorpusShapes classifies every blob by its card set and fails if a shape falls below its floor, so a corpus that quietly stopped producing tickets cannot let the gate pass while covering nothing. Gated behind LIBFOSSIL_CORPUS_PARITY=1 in addition to the existing fossil binary requirement, so the default suite is unchanged in runtime and outcome. The gate fails on this commit, which is correct: #184 is unfixed, and it also surfaces a second divergence where a merged branch tip is missing from leaf. Forum posts are not covered -- fossil exposes no CLI to create them. check-in: d01b94f4c1 user: [email protected] tags: trunk | |
|
2026-07-22
| ||
| 23:03 |
fix: correct go.mod module path to go-libfossil (#76) (#117)
* fix: correct go.mod module path to go-libfossil (#76) The module directive still declared github.com/danmestas/libfossil after the repository was renamed to go-libfossil. pkg.go.dev/godoc scraping matches the declared module path against its hosting path, so the stale path broke SDK doc generation. Rename the module path across all four in-repo modules (root, the two db/driver submodules, observer/otel, and docs/site) and every internal import, plus the release workflow, the doc-generation script, and the docs. No tag has been published under the go-libfossil path yet, so the cross-module requires cannot resolve from the proxy. Add replace directives pointing the in-repo requires at their local directories so GOWORK=off builds and the CI matrix resolve without a published version. These replaces are ignored by downstream consumers and can be dropped once new-path tags are cut. * Guard releases against replace directives; regenerate SDK docs The go-libfossil rename bridges the in-repo modules with `replace` directives. Go refuses a main module that carries them, so a tag cut while they are present breaks `go install .../cmd/libfossil@<tag>` and every `@version` fetch of the driver submodules. Add a Release workflow step that fails the job before anything is published if any tracked go.mod still contains a replace directive, so the bridge is a CI-enforced TODO rather than a silent landmine. The step comment records what unblocks a release: re-tag the submodules with the corrected module paths, bump the root requires, then drop the replace blocks. Regenerate the SDK reference docs. The previous pass only substituted URLs over the pre-existing generated files, leaving stale signatures (Repo.Timeline was still documented as taking LogOpts rather than TimelineOpts). Note that gomarkdoc must be run outside a git worktree — inside one it silently strips every source link. Also reword the README rename note, which read as though the import path had not changed, and re-sort the ncruces require block. check-in: 6273a0750d user: [email protected] tags: trunk | |
|
2026-07-19
| ||
| 16:00 |
fix: split repository enumeration from ancestry walking (#45) (#54)
Repo.Timeline was an ancestry walk wearing an enumeration's name: it required a start rid, emitted that check-in, followed plink where isprim=1 to the primary parent, and repeated until the chain ended. It never touched the event table and never visited a second parent or a sibling branch head, so it silently omitted any check-in that wasn't a first-parent ancestor of the given start rid — on libfossil's own repository that was 577 of 3,761 check-ins, with no error and no warning. The limit option never bound because the (wrong) walk exhausted first. Split into two operations under honest names: - Repo.Timeline(TimelineOpts) enumerates the event table newest first, every kind by default or a single kind via Type. This matches canonical `fossil timeline`'s -t/--type default (a filter only applies when given and not 'a'). - Repo.Ancestry(LogOpts) keeps the original first-parent walk, unchanged in behavior, under a name that says what it does. Breaking change, no deprecated shim (pre-1.0, clean break): callers of the old Timeline(LogOpts) need to move to Ancestry(LogOpts) if they want the walk, or to Timeline(TimelineOpts) if they want the enumeration fossil's own timeline command performs. The only in-tree callers were the `repo timeline` CLI command and the two examples; all three are migrated to Timeline(TimelineOpts). See CHANGELOG.md. LogEntry gains a Kind field identifying which of event.type's six kinds (ci, e, f, g, t, w) an entry is; Parents is only populated for check-ins, since plink only relates check-in artifacts. Timeline's pagination cursor orders by (mtime DESC, rid DESC) instead of canonical fossil's bare mtime DESC with no tie-break — a deliberate improvement, not an oversight, since fossil's web cursor combines that missing tie-break with a one-second timestamp slop and can repeat or skip rows at a page boundary. Getting the composite cursor to actually round-trip losslessly required fixing a real bug along the way: JulianToTime truncated instead of rounded when converting a julian day back to milliseconds, so TimeToJulian(JulianToTime(m)) was not always equal to m even for exact-millisecond inputs — enough to misplace a row at a page boundary under exactly the same-mtime conditions this issue's acceptance criteria test for. Fixed to round to nearest. Because the same class of drift also appears in the ncruces/WASM sqlite driver's own internal REAL-to-time.Time conversion (independent of this library's code), the cursor comparison also carries a small explicit tolerance rather than relying on bit-exact equality across drivers. Both the ancestry walk's loop and the enumeration's row loop now carry an explicit, testable bound so a corrupt or cyclic plink table can't hang the process. check-in: 9a2697c556 user: [email protected] tags: trunk | |
|
2026-04-26
| ||
| 15:00 |
feat(repo): expose ResolveVersion + ReadFileAt for symbolic versions (#11)
* feat(repo): expose ResolveVersion + ReadFileAt for symbolic versions Repo.ReadFile took a raw int64 RID, leaving every library caller to re-implement symbolic-version resolution (tip, trunk, branch name, UUID prefix) — work the CLI's resolveRID already does inside the cli package. Move the resolver onto Repo as ResolveVersion, refactor cli/shared.go to call it, and add Repo.ReadFileAt(version, path) so callers can read by name without first calling ResolveVersion themselves. Adds ErrVersionNotFound for the not-found case and an ambiguity error for prefix collisions. * chore(cli): drop unused openInternalRepo helper + repo import Now-dead code: resolveRID was its only caller, and resolveRID is now a one-line wrapper around Repo.ResolveVersion that doesn't need the inner handle. Also removes the now-unused internal/repo import that the helper brought in, and refreshes the cli SDK page accordingly. * chore(go.work.sum): pin transitive deps from docs toolchain gomarkdoc pulls these via go install during make docs-gen-sdk; commit the lockfile entries so contributors see no go.work.sum drift after a docs build. check-in: 7eb46a9635 user: [email protected] tags: trunk | |
| 14:14 |
docs: usability improvements from DX audit (#9)
Implements all seven recommended changes from the docs audit: 1. SDK pages now show package names in nav. Add scripts/prepend-sdk-frontmatter.sh that prepends '--- title: <pkg> ---' to each gomarkdoc-generated api.md; wired into 'make docs-gen-sdk'. Sidebar previously showed five undifferentiated 'API' entries; now shows cli, db, dst, libfossil, observer/otel. 2. /examples/ populated with paragraphs + GitHub deep-links for embed-repo-api and wasm. No longer a placeholder pointing back at the repo. 3. Architecture page gets an inline SVG mirroring the landing-page diagram. Self-contained CSS (uses currentColor + ember accent) so it tracks Hextra's light/dark theme without depending on the landing's CSS scope. 4. Cross-links added: quickstart -> production + extension-points, migration -> architecture, architecture -> extension-points. Extension Points and Production patterns are now reachable via prose, not just the sidebar. 5. /docs/ landing expanded from 3 sentences to a 7-line subsection map calling out each page's purpose. 6. Version indicator in navbar (libfossil v0.4.2). Override layouts/_partials/navbar-title.html mimics Hextra's default and appends a small mono version tag from .Site.Params.version. 7. New /docs/production/ page covering error handling, context cancellation, telemetry wiring, repo-handle lifetime, and driver selection — the patterns the quickstart's log.Fatal shortcuts gloss over. check-in: f30849a466 user: [email protected] tags: trunk | |
| 08:12 |
site(landing): SVG architecture diagram + SDK refresh (#7)
* site(landing): SVG architecture diagram + SDK regen - Replace §04 ASCII diagram with an SVG mirroring the dagnats style: three columns (callers / core / plugins), ember flow arrows with CALLS / DELEGATE / EVENTS / PERSIST labels, bottom box for .fossil (SQLite). Picks up the layout's existing .diagram CSS with no new styles. - Refresh gomarkdoc-generated SDK pages — they had drifted from current Go doc comments since the original generation. * docs(site): drop redundant body H1s from frontmatter pages Each of the four moved docs (architecture, extension-points, migration-from-fossil, testing) and the two hand-written driver _index pages had a body '# Title' that duplicated their frontmatter 'title:'. Hextra renders both, producing the visible doubled headline. Removing the body H1 leaves Hextra's frontmatter-driven page heading as the single source. SDK api.md pages from gomarkdoc are unaffected — they have no frontmatter, so Hextra promotes their body H1 to the page title without duplication. * site(landing): bump version refs to v0.4.2 check-in: d1016bd2ef user: [email protected] tags: trunk | |
| 07:52 |
docs site + landing + Cloudflare auto-deploy (#6)
* design: docs site + landing page + Cloudflare auto-deploy Mirror dagnats's docs/landing infrastructure for libfossil: a single-page landing at site/index.html (forked CSS/HTML, content rewritten), a Hugo + Hextra docs site at docs/site/, gomarkdoc-generated SDK reference under docs/site/content/docs/reference/sdk/, llms.txt artifacts, and a wrangler.jsonc that lets Cloudflare's git integration auto-deploy on push to main. Existing docs/*.md files move under docs/site/content/docs/. * design: correct landing-page path to Hugo layout override dagnats's working landing page lives at docs/site/layouts/index.html (a Hugo home-page layout override), not at site/index.html. The top-level site/index.html in dagnats is an older draft that the build pipeline ignores. Match the working setup. * design: align visual system + section list with live dagnats landing The earlier description came from dagnats's stale top-level site/index.html (JetBrains Mono + Instrument Serif italic + ember/teal accents, 8 sections). The live Hugo layout that actually serves at / uses Geist Mono only, prefers-color-scheme dual-mode (warm cream / warm dark), a single ember accent, and 7 sections (Install, What it is, Why you might want it, How it fits together, Compared to neighbors, What it is not, Get going). Update the spec to match what we are actually mirroring. * design: drop SDK regen from CF build to match dagnats exactly Earlier draft had CF install Go + gomarkdoc and re-run docs-gen-sdk on every deploy. dagnats does not do that; it relies on the pre-commit hook to keep committed SDK pages in sync, and ships only Hugo + llms-gen + hugo --minify in the CF build. Match that: smaller, faster CF build, no Go-runtime assumption about Workers Builds, and a true 1:1 mirror. * plan: docs site + landing + CF auto-deploy implementation steps 11 tasks covering Hugo+Hextra bootstrap, content moves, gomarkdoc SDK generation with pre-commit drift check, llms.txt artifacts, Makefile targets, landing page fork from dagnats's live Hugo home layout, wrangler.jsonc for CF Workers Static Assets, README update, and PR creation. * docs(site): bootstrap Hugo + Hextra skeleton * docs(site): move existing docs into Hugo content tree * docs(site): fix links + H1s broken by docs-tree move - Drop .md extensions on Hugo cross-doc links - Switch source-code references to absolute github.com/danmestas/libfossil URLs (relative ../ paths broke when files moved 3 dirs deeper) - Align H1 of architecture.md and migration-from-fossil.md with their frontmatter titles * docs(site): add quickstart, examples, and SDK section stubs * docs(site): tighten quickstart snippets + reference index - Make the Sync example self-contained (open + sync, full main, real signatures) - Bridge from Clone to Open with a one-line prose link - Add a sentence to reference/_index.md so it does not render blank - Use the project's canonical "pure-Go, CGo-free" phrasing * docs(site): add docs-gen-sdk Makefile target + commit generated SDK pages * docs(site): pin gomarkdoc version + replace empty driver stubs with prose - Add GOMARKDOC_VERSION Makefile variable so contributors don't drift on output format when a new gomarkdoc ships - Drop the two driver packages (modernc, ncruces) from gomarkdoc and hand-write _index.md pages explaining the register-on-import contract; the stubs were byte-stable but rendered as visibly broken documentation * docs(site): add gen-llms-txt.sh + docs-gen-llms target * docs(site): switch llms-full frontmatter strip from sed to awk The sed range-negation pattern '/^---$/,/^---$/!p' silently re-opens a suppression range on any bare '---' in body content, eating Markdown horizontal rules and embedded YAML in fenced code blocks. The awk pattern strips the frontmatter only when it begins on line 1, leaving body content intact regardless of how many '---' lines it contains. * hooks: pre-commit fails when SDK pages drift from code * hooks: pre-commit re-installs gomarkdoc if it's the wrong version The drift check's existing gate just looks for gomarkdoc on PATH. A contributor with an older gomarkdoc installed locally would have the gate pass and then run regeneration with their stale binary, producing either a silent false-negative or a confusing OUT-OF-DATE error with no version hint. Compare the installed version against GOMARKDOC_VERSION from Makefile and re-install on mismatch. Best-effort; offline contributors can still commit. * docs(site): add docs-serve, docs-build, docs aggregate targets * docs(site): make docs aggregate parallel-safe via explicit deps The docs aggregate previously listed gen-sdk, gen-llms, and build as side-by-side prereqs. Make doesn't guarantee left-to-right ordering under -j, and gen-llms reads what gen-sdk writes, while build reads both. Encode the chain explicitly so 'make -j docs' is correct. Side benefit: 'make docs-build' standalone now produces a complete deployable site, matching contributor expectation. * site(landing): fork dagnats home layout; rebrand chrome * site(landing): rewrite §01–§07 content for libfossil * site(landing): use .ascii class for diagram + fix §03 phrasing * deploy: add wrangler.jsonc for CF Workers Static Assets * docs: point README at the new docs site check-in: e2a2f28861 user: [email protected] tags: trunk | |