Documentation
¶
Overview ¶
Package scaffold writes the Coop working set into a repo: AGENTS.md, the .agent/ queue and agent fallbacks, optional project adapters, the workflow skills, and optionally a per-project .agent/Dockerfile + .agent/compose.yml. Every template is embedded in the binary, so one `coop` binary can scaffold any repo with no extra files.
Index ¶
- Variables
- func ComposeServiceNames(path string) []string
- func DetectStacks(repo string) []string
- func DetectSubprojects(repo string) []string
- func Init(repo, stack string, gateLangs, agentDirs []string) error
- func InitSubproject(repo, dir string) error
- func Initialized(repo string) bool
- func RegisterSubprojects(repo string, detected []string) ([]string, error)
- func SuggestDocker(repo string)
- func WriteCompose(repo string, services []string) error
- func WriteProject(dir string, subprojects []string) (bool, error)
Constants ¶
This section is empty.
Variables ¶
var ComposeServices = []string{"postgres", "redis"}
ComposeServices is the menu of sibling services `coop init` can scaffold into .agent/compose.yml — what the interactive prompt offers and what --services accepts.
var GateLangs = []string{"go", "terraform", "elixir", "rust"}
GateLangs is the ordered set of stacks coop can scaffold a commit format gate for. It's the menu the interactive prompt offers and what DetectStacks chooses from.
Functions ¶
func ComposeServiceNames ¶
ComposeServiceNames is the exported reader for composeServices — the service names actually defined in the compose file at path (nil if there's no file or no services), e.g. for `coop help` to list what `coop up` would start. Distinct from the ComposeServices var (the offerable menu): picking "postgres" writes a service named "db", so the real name comes from the file.
func DetectStacks ¶
DetectStacks reports which gate languages the repo uses, by marker file, *.tf presence, or .tool-versions — in GateLangs order, so the generated gate is deterministic.
func DetectSubprojects ¶
DetectSubprojects returns the directories under repo that are themselves coop projects (they contain a .agent/ dir) — a monorepo's members. Paths are repo-relative and slash-separated ("terraform/environments/va1"), sorted; empty for a single project.
The walk goes to ANY depth, because a member is not always a direct child: an infra repo nests its terraform roots (terraform/environments/va1), and requiring depth-1 meant those layouts had to hand-edit .agent/project.yaml forever. Three prunes keep it cheap and correct:
- hidden dirs (.git, .agent, .terraform, …) — never members, and the heavy ones live there
- the build/vendor dirs in subprojectSkipDirs, which can hold thousands of files
- a member's own subtree: once a directory is a member, its children are ITS business, so nesting a member inside a member can't produce two overlapping queues for the same work
func Init ¶
Init scaffolds the working set into repo. The toolchain is driven by .tool-versions: with no --stack a present .tool-versions auto-scaffolds the asdf .agent/Dockerfile; `--stack asdf` forces it. gateLangs are the stacks the commit hooks check (from DetectStacks, or the caller's interactive prompt); empty means a neutral gate. Per-file progress prints as faint ui.Detail lines; the caller prints the summary and the next-step actions. Existing files are never clobbered.
func InitSubproject ¶
InitSubproject scaffolds the MINIMAL coop set for a monorepo member: just its own task queue. Members share the root's AGENTS.md, skills, rules, hooks, box — AND its single top-level .agent/project.yaml (members never get their own) — so they're pure task-queue holders. Each member still has its OWN tasks (per-component work) and backlog (the xx_backlog drawer, created on demand by `coop backlog add`); the root keeps a queue too, for changes that span members. Writes only what's absent. repo is the monorepo root and dir the member: progress is reported repo-relative, so a nested member reads as terraform/environments/va1/… and two members with the same basename stay distinct (rendering from the member's PARENT collapsed both to "va1/…").
func Initialized ¶
Initialized reports whether repo already carries a coop scaffold. `coop init` uses it to stay quiet on a re-run: with the working set already in place there is nothing an interactive prompt could change (every write is no-clobber), so asking again is pure friction — and the first-run "next steps" are the wrong advice for a repo that's been building for weeks.
func RegisterSubprojects ¶
RegisterSubprojects adds any detected member missing from an EXISTING project.yaml's subprojects: list, returning what it added. A repo grows members after its first init, and leaving them unlisted means coop silently ignores their queues — the old behaviour was to print "add these to subprojects:" and make you do it by hand, every init, forever.
The edit is surgical text, not a YAML re-marshal: project.yaml is a commented template that documents every key, and round-tripping it through a YAML encoder would strip all of that. Missing file, or a subprojects: block coop can't confidently locate → returns nothing and changes nothing, so the caller's advisory stays the fallback.
func SuggestDocker ¶
func SuggestDocker(repo string)
SuggestDocker prints (docs only, never writes) how to build the agent box on the repo's existing Docker. It runs only when the box isn't set up yet — a Dockerized repo with no .agent/Dockerfile is the gap it fills; it never nags an already-configured one. The caller (cmdInit) runs it after the summary anchor so it reads as box-setup guidance before the steps.
func WriteCompose ¶
WriteCompose scaffolds .agent/compose.yml for the chosen sibling services (a subset of ComposeServices), never clobbering an existing file. It is a no-op when no service is chosen — coop never adds a db/redis a project didn't ask for. It writes the DEFAULT location (project.DefaultCompose); a repo that later moves the file says so via box.compose.
func WriteProject ¶
WriteProject writes <dir>/.agent/project.yaml if it's absent, reporting whether it wrote one. A non-empty subprojects list makes it a monorepo root listing them; empty writes a leaf template with commented serve/subprojects examples. It never clobbers an existing file (so re-running init keeps your edits — cmdInit notes any newly-detected members instead).
Types ¶
This section is empty.