Commit Graph

3 Commits

Author SHA1 Message Date
e48dbd42b4 sx-gitea: linear closure walk + working-tree importer (78/78 wire)
The closure walk rebuilt its seen-set with assoc — which on this kernel
copies the entire hashtable per call — and stacked pending cids with
concat; pack-cids then insertion-sorted the result. All three are
quadratic, which surfaced the moment a real repo (4.5k files) went over
the wire: a single push spent an hour in the walk. The seen-set is now a
private dict mutated in place (dict-set!, the acl engine's own pattern),
pending cids are cons-stacked, and packs are unsorted (order is
irrelevant to the receiver). Wire suite stays 78/78; every clone/fetch/
push on repo-scale histories now walks each object once.

lib/gitea/import.sx: working-tree importer — file-read + http-request
adapt the Phase 3 wire client to a live server (gitea/http-app);
staging (deterministic commits, so an interrupted import replays to
identical CIDs and resumes without re-pushing) is separate from the
single delta push; pack lines that exceed the pkt limit are skipped and
reported.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-03 17:34:31 +00:00
d96529effe sx-gitea Phase 4: issues — content-document bodies + relations graph (TDD, 360/360)
lib/gitea/issues.sx: issues as kv records (zero-padded per-repo
numbering, title/author/state, sorted label+assignee sets, Markdown
body, comment thread). Bodies and comments are content-on-sx documents:
content/from-markdown -> block doc -> content/html for pages, with the
round-trip law asserted in the suite. The issue graph (issue->repo
parent, author origin, assignee member, label link, commenter reply) is
DERIVED into lib/relations facts and rebuilt on fact change — same
pattern as the acl db, so deleting a repo can never dangle edges.

Views: open/closed/by-label/by-assignee; graph queries: repo-issue-nodes,
user-authored, user-assigned, label-issues, issue-participants.

Web: issues list + issue page (rendered HTML body + comments), JSON API:
create (any authenticated reader), comment, close/reopen (author or
write), label/assignee management (write). All read-gated like the rest.

Infra: gitea/route-packs registry — wire/issues append their routes at
load; gitea/app serves all packs. repo-delete! now purges collab/issue/
issue-seq rows too (ghost-state regression tested). Conformance runner
gains per-suite extra modules; the issues suite loads relations +
smalltalk + content (~5s).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-03 13:53:21 +00:00
83a8a2f8db sx-gitea Phase 3: wire — smart-HTTP protocol over native CIDs (TDD, 272/272)
lib/gitea/wire.sx: git-style pkt-line framing (byte-compatible hex4
lengths + flush sections); object closure walker (commits/trees/blobs/
tags) with missing-object detection; wants/haves pack negotiation.
Objects travel as '<cid> <serialized-sx>' pkt lines — receivers re-derive
the CID from the bytes, so packs are tamper-evident by construction.

Server endpoints: GET info/refs (read-gated advertisement incl. '@ HEAD'
symref line), POST git-upload-pack (read), POST git-receive-pack (write;
401/403/404 like the rest of the API) with per-ref command application:
create/update/delete via ref-CAS, fast-forward enforcement on heads/*,
closure-completeness check, stale detection, heads|tags-only.

Client: gitea/remote over any dream app fn — ls-remote, clone! (sets
HEAD + default-branch, cleans up on unreachable remote), mirror fetch!,
push!/push-delete! with local pack computation. Suite syncs two
in-memory forges end to end: clone, incremental fetch, push, non-ff
rejection + recovery, branch create/delete, tag push, private-repo
credentialed round trip.

sx-parse comes from spec/parser.sx on the OCaml server host — added to
the conformance load order. Also merged loops/git (git-wire export/
import adapters, 267/267) for future stock-git interop.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-03 13:35:40 +00:00