scaffold

package
v0.0.0-...-3238171 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 20, 2026 License: MIT Imports: 15 Imported by: 0

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

Constants

This section is empty.

Variables

View Source
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.

View Source
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

func ComposeServiceNames(path string) []string

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

func DetectStacks(repo string) []string

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

func DetectSubprojects(repo string) []string

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

func Init(repo, stack string, gateLangs, agentDirs []string) error

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

func InitSubproject(repo, dir string) error

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

func Initialized(repo string) bool

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

func RegisterSubprojects(repo string, detected []string) ([]string, error)

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

func WriteCompose(repo string, services []string) error

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

func WriteProject(dir string, subprojects []string) (bool, error)

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.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL