3.6 KiB
3.6 KiB
Conventions
Rules that govern this repo. Anything that becomes load-bearing belongs here, in conventions.md, never in a section appended to another doc.
Repository layout
cmd/ one subdir per shippable binary; package main only
internal/ every other package; never imported outside this module
internal/agent/profiles built-in TOML profiles, embedded with //go:embed
docs/ one topic per file (see "Docs" below)
plan.md the long-form design doc; source-of-truth for phasing
README.md TOC only
No top-level pkg/ until we have an external consumer.
Go
- Module path:
gitea.alexandru.macocian.me/Charlie/sherlock. - Target Go toolchain:
go 1.25(pinned viago.mod'sgodirective; CI installs the matching minor). - One
package mainpercmd/<binary>/. No multiple-main-files trickery. - Every other package has a top-of-file
Package <name> ...doc comment (in the leading.gosource file; we drop standalonedoc.gofiles once a real source file exists). - Third-party deps are added with a one-line justification. The current set:
github.com/zalando/go-keyring— OS keyring for token persistence (Decision #8).github.com/BurntSushi/toml— parseservices.d/*.tomlandagents.d/*.toml(Decision #4).github.com/coreos/go-oidc/v3— OIDC discovery + ID-token verification against Authentik.golang.org/x/oauth2— auth-code + PKCE + refresh against Authentik's token endpoint.golang.org/x/sync—singleflightfor collapsing concurrent token refreshes.
Docs
README.mdis TOC only. One-line description + a bulleted index ofdocs/*.md.- One topic per file under
docs/. Never append a new section to an existing doc to cover a new concern; createdocs/<new-topic>.mdand link it fromREADME.md. plan.mdis the long-form design + phasing doc. It is allowed to be long.- Cross-link aggressively: every doc should link to the other docs whose concerns it touches.
- ASCII diagrams over images. Diagrams live next to the prose that explains them.
Naming
- Binaries are kebab-case (
sherlock-broker,gitea-mcp). - Built-in agent profiles match the agent's canonical CLI name (
copilot,claude,aider). - Service registry files match the service's canonical name (
gitea.toml,grafana.toml). - Env vars are
<SERVICE>_TOKEN(e.g.GITEA_TOKEN,GSSH_TOKEN).
Extensibility invariants
- Agent extensibility: adding a new agent CLI MUST be a TOML drop-in under
~/.config/sherlock/agents.d/. If a code change is required, the design has drifted — fix the abstraction ininternal/agent/, don't accept the code change. - Service extensibility: adding a new downstream service MUST be a TOML drop-in under
~/.config/sherlock/services.d/+ (optionally) a newcmd/<service>-mcp/binary. The broker itself does not learn about individual services in Go code.
Commits
- Conventional-ish:
area: short imperative(e.g.broker: persist tokens with age,docs: add gssh-integration). - One logical change per commit. CI must pass on every commit on
main.
CI
.gitea/workflows/ci.yamlruns on every push + PR. It runsgofmt,go vet,errcheck,staticcheck,go test -race, andgo build. No other gates.- No deploy pipeline — sherlock is operator-installed via
go install. Release artifacts (binaries to the gitea registry / releases) land in Phase 5 if at all.
Security
- No secrets in this repo, ever. Not in tests, not in fixtures, not in comments.
- The operator's Authentik tokens and (Phase 2+) per-service tokens live in the OS keyring. See storage.md.