Component names now reflect filesystem location using / as path separator and : as namespace separator for shared components: ~sx-header → ~layouts/header ~layout-app-body → ~shared:layout/app-body ~blog-admin-dashboard → ~admin/dashboard 209 files, 4,941 replacements across all services. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
158 lines
8.7 KiB
Plaintext
158 lines
8.7 KiB
Plaintext
;; sx-forge — SX-based Git Forge
|
|
;; Plan: a Gitea/Forgejo-style git hosting platform where everything —
|
|
;; repositories, issues, pull requests, CI, permissions — is SX.
|
|
|
|
(defcomp ~plans/sx-forge/plan-sx-forge-content ()
|
|
(~docs/page :title "sx-forge: Git Forge in SX"
|
|
|
|
(~docs/section :title "Vision" :id "vision"
|
|
(p "A git forge where the entire interface, configuration, and automation layer "
|
|
"is written in SX. Repositories are browsed, issues are filed, pull requests "
|
|
"are reviewed, and CI pipelines are triggered — all through SX components "
|
|
"rendered via the same hypermedia pipeline as every other SX app.")
|
|
(p "Configuration is SX. Webhooks are SX. Access control policies are SX macros "
|
|
"that expand to permission checks. Repository templates are defcomps. "
|
|
"The forge doesn't use SX — it " (em "is") " SX."))
|
|
|
|
(~docs/section :title "Why" :id "why"
|
|
(p "Gitea/Forgejo are excellent but they're Go binaries with YAML/INI config, "
|
|
"Markdown rendering, and a template engine that's separate from the application logic. "
|
|
"Every layer speaks a different language.")
|
|
(p "sx-forge collapses these layers:")
|
|
(ul :class "space-y-2 text-stone-600 list-disc pl-5"
|
|
(li "Repository browsing = SX components rendering git tree objects")
|
|
(li "Issue tracking = SX forms with sx-post, stored as content-addressed SX documents")
|
|
(li "Pull requests = SX diff viewer + sx-activity for review comments")
|
|
(li "CI integration = sx-ci pipelines triggered by push hooks")
|
|
(li "Configuration = SX s-expressions, manipulated by macros")
|
|
(li "Access control = SX macros that expand to permission predicates")
|
|
(li "API = SX wire format (text/sx) alongside JSON for compatibility")))
|
|
|
|
(~docs/section :title "Architecture" :id "architecture"
|
|
(div :class "overflow-x-auto mt-4"
|
|
(table :class "w-full text-sm text-left"
|
|
(thead
|
|
(tr :class "border-b border-stone-200"
|
|
(th :class "py-2 px-3 font-semibold text-stone-700" "Layer")
|
|
(th :class "py-2 px-3 font-semibold text-stone-700" "Implementation")
|
|
(th :class "py-2 px-3 font-semibold text-stone-700" "Notes")))
|
|
(tbody :class "text-stone-600"
|
|
(tr :class "border-b border-stone-100"
|
|
(td :class "py-2 px-3 font-semibold" "Git backend")
|
|
(td :class "py-2 px-3" "libgit2 or shell-out to git")
|
|
(td :class "py-2 px-3" "Smart HTTP + SSH protocols. Bare repos on disk."))
|
|
(tr :class "border-b border-stone-100"
|
|
(td :class "py-2 px-3 font-semibold" "UI")
|
|
(td :class "py-2 px-3" "SX components (defcomp)")
|
|
(td :class "py-2 px-3" "Tree browser, diff viewer, blame, commit log — all defcomps."))
|
|
(tr :class "border-b border-stone-100"
|
|
(td :class "py-2 px-3 font-semibold" "Issues / PRs")
|
|
(td :class "py-2 px-3" "SX documents on IPFS")
|
|
(td :class "py-2 px-3" "Content-addressed. Federated via sx-activity."))
|
|
(tr :class "border-b border-stone-100"
|
|
(td :class "py-2 px-3 font-semibold" "CI")
|
|
(td :class "py-2 px-3" "sx-ci pipelines")
|
|
(td :class "py-2 px-3" "Push hook triggers pipeline. Results as SX components."))
|
|
(tr :class "border-b border-stone-100"
|
|
(td :class "py-2 px-3 font-semibold" "Auth")
|
|
(td :class "py-2 px-3" "OAuth2 + SX policy macros")
|
|
(td :class "py-2 px-3" "Permissions are macro-expanded predicates."))
|
|
(tr :class "border-b border-stone-100"
|
|
(td :class "py-2 px-3 font-semibold" "Config")
|
|
(td :class "py-2 px-3" "SX s-expressions")
|
|
(td :class "py-2 px-3" "forge.sx per-instance. repo.sx per-repo."))
|
|
(tr :class "border-b border-stone-100"
|
|
(td :class "py-2 px-3 font-semibold" "Federation")
|
|
(td :class "py-2 px-3" "sx-activity (ActivityPub)")
|
|
(td :class "py-2 px-3" "Cross-instance PRs, issues, stars, forks."))))))
|
|
|
|
(~docs/section :title "Configuration as SX" :id "config"
|
|
(p "Instance configuration is an SX file, not YAML or INI:")
|
|
(highlight "(define forge-config
|
|
{:name \"Rose Ash Forge\"
|
|
:domain \"forge.rose-ash.com\"
|
|
:ssh-port 2222
|
|
:storage {:backend :filesystem :root \"/data/repos\"}
|
|
:auth {:provider :oauth2
|
|
:issuer \"https://account.rose-ash.com\"}
|
|
:federation {:enabled true
|
|
:allowlist (list \"*.rose-ash.com\")}
|
|
:ci {:runner :sx-ci
|
|
:default-pipeline \"ci/default.sx\"}})" "lisp")
|
|
(p "Macros transform configuration:")
|
|
(highlight ";; Macro: generate mirror config from upstream
|
|
(defmacro mirror-repo (name upstream)
|
|
`(define-repo ,name
|
|
{:mirror true
|
|
:upstream ,upstream
|
|
:sync-interval 3600
|
|
:ci false}))" "lisp")
|
|
(p "Per-repository configuration lives in " (code "repo.sx") " at the repo root:")
|
|
(highlight "(define repo-config
|
|
{:default-branch \"main\"
|
|
:ci (pipeline
|
|
(stage :test (sx-ci/run \"test.sx\"))
|
|
(stage :deploy
|
|
(when-branch \"main\"
|
|
(sx-ci/deploy :target :production))))
|
|
:permissions
|
|
{:push (or (role? :maintainer) (role? :admin))
|
|
:merge-pr (and (ci-passed?) (approved-by? 1))
|
|
:admin (role? :admin)}})" "lisp"))
|
|
|
|
(~docs/section :title "SX Diff Viewer" :id "diff-viewer"
|
|
(p "Diffs rendered as SX components, not pre-formatted text:")
|
|
(highlight ";; The diff viewer is a defcomp, composable like any other
|
|
(defcomp ~plans/sx-forge/diff-view (&key (diff :as dict))
|
|
(map (fn (hunk)
|
|
(~diff-hunk
|
|
:file (get hunk \"file\")
|
|
:old-start (get hunk \"old-start\")
|
|
:new-start (get hunk \"new-start\")
|
|
:lines (get hunk \"lines\")))
|
|
(get diff \"hunks\")))" "lisp")
|
|
(p "Because diffs are SX data, macros can transform them:")
|
|
(ul :class "space-y-2 text-stone-600 list-disc pl-5"
|
|
(li "Syntax highlighting via the same " (code "highlight") " helper used everywhere")
|
|
(li "Inline review comments as SX forms (sx-post to comment endpoint)")
|
|
(li "Suggestion blocks — click to apply a proposed change")
|
|
(li "SX-aware diffs — show component-level changes, not just line changes")))
|
|
|
|
(~docs/section :title "Federated Forge" :id "federation"
|
|
(p "sx-activity enables cross-instance collaboration:")
|
|
(ul :class "space-y-2 text-stone-600 list-disc pl-5"
|
|
(li (strong "Cross-instance PRs") " — open a PR from your fork on another instance")
|
|
(li (strong "Federated issues") " — file an issue on a remote repo from your instance")
|
|
(li (strong "Stars and forks") " — ActivityPub Follow/Like activities")
|
|
(li (strong "Mirror sync") " — subscribe to upstream changes via sx-activity")
|
|
(li (strong "Review comments") " — threaded discussions federated as SX documents"))
|
|
(p "Every issue, comment, and review is a content-addressed SX document on IPFS. "
|
|
"Federation distributes references. The content is permanent and verifiable."))
|
|
|
|
(~docs/section :title "Git Operations as IO Primitives" :id "git-ops"
|
|
(p "Git operations exposed as SX IO primitives in boundary.sx:")
|
|
(highlight ";; boundary.sx additions
|
|
(io git-log (repo &key branch limit offset) list)
|
|
(io git-tree (repo ref path) list)
|
|
(io git-blob (repo ref path) string)
|
|
(io git-diff (repo base head) dict)
|
|
(io git-refs (repo) list)
|
|
(io git-commit (repo message files &key author) dict)
|
|
(io git-create-branch (repo name from) dict)
|
|
(io git-merge (repo source target &key strategy) dict)" "lisp")
|
|
(p "Pages use these directly — no controller layer, no ORM:"))
|
|
|
|
(~docs/section :title "Implementation Path" :id "implementation"
|
|
(ol :class "space-y-3 text-stone-600 list-decimal pl-5"
|
|
(li (strong "Phase 1: Read-only browser") " — git-tree, git-blob, git-log, git-diff as IO primitives. "
|
|
"SX components for tree view, blob view, commit log, diff view.")
|
|
(li (strong "Phase 2: Issues") " — SX forms for create/edit. Content-addressed storage. "
|
|
"Labels, milestones, assignees as SX data.")
|
|
(li (strong "Phase 3: Pull requests") " — fork model, diff + review UI, merge strategies. "
|
|
"CI status checks from sx-ci.")
|
|
(li (strong "Phase 4: CI integration") " — push hooks trigger sx-ci pipelines. "
|
|
"Results rendered as SX components on the PR page.")
|
|
(li (strong "Phase 5: Federation") " — sx-activity for cross-instance PRs, issues, stars.")
|
|
(li (strong "Phase 6: Admin") " — SX macro-based permission policies. "
|
|
"Instance and org management via SX config.")))))
|