Change module path from forge.lthn.ai/core/go-scm to dappco.re/go/core/scm. Update all Go source imports for migrated packages: - go-log -> dappco.re/go/core/log - go-io -> dappco.re/go/core/io - go-i18n -> dappco.re/go/core/i18n - go-ws -> dappco.re/go/core/ws - api -> dappco.re/go/core/api Non-migrated packages (cli, config) left on forge.lthn.ai paths. Replace directives use local paths (../go, ../go-io, etc.) until the dappco.re vanity URL server resolves these modules. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
5.8 KiB
5.8 KiB
| title | description |
|---|---|
| go-scm | SCM integration, AgentCI automation, and data collection for the Lethean ecosystem. |
go-scm
go-scm provides source control management integration for the Lethean ecosystem. It wraps the Forgejo and Gitea APIs behind ergonomic Go clients, runs an automated PR pipeline for AI agent workflows, collects data from external sources, and manages multi-repo workspaces via a declarative registry.
Module path: dappco.re/go/core/scm
Go version: 1.26
Licence: EUPL-1.2
Quick Start
Forgejo API Client
import "dappco.re/go/core/scm/forge"
// Create a client from config file / env / flags
client, err := forge.NewFromConfig("", "")
// List open issues
issues, err := client.ListIssues("core", "go-scm", forge.ListIssuesOpts{
State: "open",
})
// List repos in an organisation (paginated iterator)
for repo, err := range client.ListOrgReposIter("core") {
fmt.Println(repo.Name)
}
Multi-Repo Git Status
import "dappco.re/go/core/scm/git"
statuses := git.Status(ctx, git.StatusOptions{
Paths: []string{"/home/dev/core/go-scm", "/home/dev/core/go-ai"},
Names: map[string]string{"/home/dev/core/go-scm": "go-scm"},
})
for _, s := range statuses {
if s.IsDirty() {
fmt.Printf("%s: %d modified, %d untracked\n", s.Name, s.Modified, s.Untracked)
}
}
AgentCI Poll-Dispatch Loop
import (
"dappco.re/go/core/scm/jobrunner"
"dappco.re/go/core/scm/jobrunner/forgejo"
"dappco.re/go/core/scm/jobrunner/handlers"
)
source := forgejo.New(forgejo.Config{Repos: []string{"core/go-scm"}}, forgeClient)
poller := jobrunner.NewPoller(jobrunner.PollerConfig{
Sources: []jobrunner.JobSource{source},
Handlers: []jobrunner.JobHandler{
handlers.NewDispatchHandler(forgeClient, forgeURL, token, spinner),
handlers.NewTickParentHandler(forgeClient),
handlers.NewEnableAutoMergeHandler(forgeClient),
},
PollInterval: 60 * time.Second,
})
poller.Run(ctx)
Data Collection
import "dappco.re/go/core/scm/collect"
cfg := collect.NewConfig("/tmp/collected")
excavator := &collect.Excavator{
Collectors: []collect.Collector{
&collect.GitHubCollector{Org: "lethean-io"},
&collect.MarketCollector{CoinID: "lethean", Historical: true},
&collect.PapersCollector{Source: "all", Query: "cryptography VPN"},
},
Resume: true,
}
result, err := excavator.Run(ctx, cfg)
Package Layout
| Package | Import Path | Description |
|---|---|---|
forge |
go-scm/forge |
Forgejo API client -- repos, issues, PRs, labels, webhooks, organisations, PR metadata |
gitea |
go-scm/gitea |
Gitea API client -- repos, issues, PRs, mirroring, PR metadata |
git |
go-scm/git |
Multi-repo git operations -- parallel status checks, push, pull; Core DI service |
jobrunner |
go-scm/jobrunner |
AgentCI pipeline engine -- signal types, poller loop, JSONL audit journal |
jobrunner/forgejo |
go-scm/jobrunner/forgejo |
Forgejo job source -- polls epic issues for unchecked children, builds signals |
jobrunner/handlers |
go-scm/jobrunner/handlers |
Pipeline handlers -- dispatch, completion, auto-merge, publish-draft, dismiss-reviews, fix-command, tick-parent |
agentci |
go-scm/agentci |
Clotho Protocol orchestrator -- agent config, SSH security helpers, dual-run verification |
collect |
go-scm/collect |
Data collection framework -- collector interface, rate limiting, state tracking, event dispatch |
manifest |
go-scm/manifest |
Application manifest -- YAML parsing, ed25519 signing and verification |
marketplace |
go-scm/marketplace |
Module marketplace -- catalogue index, search, git-based installer with signature verification |
plugin |
go-scm/plugin |
CLI plugin system -- plugin interface, JSON registry, loader, GitHub-based installer |
repos |
go-scm/repos |
Workspace management -- repos.yaml registry, topological sorting, work config, git state, KB config |
cmd/forge |
go-scm/cmd/forge |
CLI commands for the core forge subcommand |
cmd/gitea |
go-scm/cmd/gitea |
CLI commands for the core gitea subcommand |
cmd/collect |
go-scm/cmd/collect |
CLI commands for data collection |
Dependencies
Direct
| Module | Purpose |
|---|---|
codeberg.org/mvdkleijn/forgejo-sdk/forgejo/v2 |
Forgejo API SDK |
code.gitea.io/sdk/gitea |
Gitea API SDK |
forge.lthn.ai/core/cli |
CLI framework (Cobra, TUI) |
forge.lthn.ai/core/config |
Layered config (~/.core/config.yaml) |
dappco.re/go/core/io |
Filesystem abstraction (Medium, Sandbox, Store) |
dappco.re/go/core/log |
Structured logging and contextual error helper |
dappco.re/go/core/i18n |
Internationalisation |
github.com/stretchr/testify |
Test assertions |
golang.org/x/net |
HTML parsing for collectors |
gopkg.in/yaml.v3 |
YAML parsing for manifests and registries |
Indirect
The module transitively pulls in forge.lthn.ai/core/go (DI framework) via config, plus spf13/viper, spf13/cobra, Charmbracelet TUI libraries, and Go standard library extensions.
Configuration
Authentication for both Forgejo and Gitea is resolved through a three-tier priority chain:
- Config file --
~/.core/config.yamlkeysforge.url,forge.token(orgitea.*) - Environment variables --
FORGE_URL,FORGE_TOKEN(orGITEA_URL,GITEA_TOKEN) - CLI flags --
--url,--token(highest priority)
Set credentials once:
core forge config --url https://forge.lthn.ai --token <your-token>
core gitea config --url https://gitea.snider.dev --token <your-token>
Further Reading
- Architecture -- internal design, key types, data flow
- Development Guide -- building, testing, contributing