Files
rose-ash/sx/sx/plans/sx-forge.sx
giles b0920a1121 Rename all 1,169 components to path-based names with namespace support
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>
2026-03-12 22:00:12 +00:00

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.")))))