project

package
v0.0.0-...-7911669 Latest Latest
Warning

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

Go to latest
Published: Aug 25, 2026 License: MIT Imports: 10 Imported by: 0

Documentation

Overview

Package project reads a repo's .agent/project.yaml — coop's per-project config, committed with the repo (unlike the git-ignored rest of .agent/). It carries:

  • subprojects: for a monorepo, the member project dirs whose .agent/tasks queues coop aggregates automatically, so you don't hand-maintain COOP_TASKS.
  • serve.ports: container ports coop publishes so a dev server running in the box is reachable from the host browser, each mapped to a stable host port.
  • box: the committed box policy and literal environment defaults every run in this repo inherits — applied below explicit user/runtime settings (box.Run overlays it).
  • gate: the revalidation command `coop fork merge` runs in the box (an explicit COOP_GATE wins).

SECURITY: this file is committed and read on the HOST from a repo you may not fully trust, so it must never be able to LOOSEN the user's posture. The precedence (explicit env/conf > this file > built-in default) makes egress tighten-only by construction — its built-in default is already the loosest value ("open") — and no_new_privileges is deliberately NOT a key here (its default is on; a committed switch could only turn it off). box.env reaches only the container, rejects Coop's reserved COOP_ namespace, and stays below the user's agents/env and runtime-generated values.

Index

Constants

View Source
const (
	DefaultDockerfile = ".agent/Dockerfile"
	DefaultCompose    = ".agent/compose.yml"
)

Default box-input paths when project.yaml doesn't set box.dockerfile / box.compose. Both live under .agent/ (coop's committed home) — the Dockerfile alongside the sidecar compose file.

View Source
const File = ".agent/project.yaml"

File is the repo-relative path of the project config.

Variables

This section is empty.

Functions

func ComposePath

func ComposePath(repo string) string

ComposePath returns the repo-relative path to the sidecar compose file — box.compose from project.yaml, else DefaultCompose. Best-effort, like DockerfilePath.

func DockerfilePath

func DockerfilePath(repo string) string

DockerfilePath returns the repo-relative path to the box's Dockerfile — box.dockerfile from project.yaml, else DefaultDockerfile. Best-effort: a project.yaml that won't load (which the build/run paths surface loudly on their own Load) falls back to the default here rather than erroring, so path-existence checks stay total.

func HostPort

func HostPort(repo string, port int) int

HostPort maps a repo + container port to a host port deterministically: the same project always publishes to the same host port (bookmarkable, and stable across box restarts), while two different projects almost never collide. Deterministic rather than first-come so the URL reporter and the box itself agree on the mapping without having to coordinate.

func HostPortFor

func HostPortFor(repo, key string) int

HostPortFor maps a repo + an arbitrary key to a host port deterministically — the same key always publishes to the same host port, two different keys almost never collide. HostPort is the port-only case (key = the port); sidecars key on "<service>:<port>" so two services sharing a container port — or a sidecar port equal to a serve.port — still get distinct host ports.

func TaskDirs

func TaskDirs(repo string) ([]string, error)

TaskDirs returns the repo-relative .agent/tasks queue(s) for repo, aggregating a monorepo's subprojects so no one has to hand-maintain COOP_TASKS. A single repo (no subprojects) yields just ".agent/tasks". A monorepo yields each subproject's queue, plus the root's own if it has one. A missing project.yaml falls back to ".agent/tasks"; an invalid one returns the error.

Types

type Box

type Box struct {
	Dockerfile string            `yaml:"dockerfile"` // box image definition, repo-relative ("" ⇒ .agent/Dockerfile)
	Compose    string            `yaml:"compose"`    // sidecar services compose file, repo-relative ("" ⇒ .agent/compose.yml)
	Env        map[string]string `yaml:"env"`        // literal box-only environment defaults

	Egress  string `yaml:"egress"`  // "" (unset) | "open" | "none" — anything else fails Load
	AutoUp  *bool  `yaml:"auto_up"` // auto-start .agent/compose.yml services (default true)
	Network *bool  `yaml:"network"` // join the sibling-services network (default true)
	Memory  string `yaml:"memory"`  // docker --memory syntax, passed through (e.g. 4g)
	CPUs    string `yaml:"cpus"`    // docker --cpus value
	Pids    string `yaml:"pids"`    // --pids-limit: a positive integer, or ""/0/unlimited for none
}

Box is the committed per-repo box policy. Every field is optional; an unset field keeps the user's own setting (env/conf) or coop's built-in default. The booleans are pointers because absent must stay distinguishable from false (their defaults are true).

type Context

type Context struct {
	Routes []Route `yaml:"routes"`
}

Context is the path-routed context configuration: which committed docs to compile for a given scope (touched paths). See internal/contextc for the compiler; canonical AGENTS.md/CLAUDE.md are always included regardless of routes.

type Project

type Project struct {
	Subprojects []string `yaml:"subprojects"` // monorepo member dirs (repo-relative), each its own coop project
	Serve       Serve    `yaml:"serve"`
	Box         Box      `yaml:"box"`     // committed box policy (below an explicit COOP_* setting)
	Review      Review   `yaml:"review"`  // publication-review-only services and literal environment
	Context     Context  `yaml:"context"` // path-routed instruction/rule/KB compilation (coop context)
	Gate        string   `yaml:"gate"`    // fork-merge revalidation command (an explicit COOP_GATE wins)
}

Project is the parsed .agent/project.yaml.

func Load

func Load(repo string) (*Project, error)

Load reads <repo>/.agent/project.yaml. A missing file is not an error — it returns an empty Project, the common single-repo case. A present-but-invalid file (bad YAML, an unknown key, an out-of-range port, a bad box value, or a subproject path that escapes the repo) IS an error, so a typo surfaces instead of silently doing nothing. Subproject paths are cleaned in place.

func (*Project) ComposeRel

func (p *Project) ComposeRel() string

func (*Project) DockerfileRel

func (p *Project) DockerfileRel() string

DockerfileRel / ComposeRel project the box-input paths off a loaded Project: the configured value, else the default. Callers that already hold a *Project (e.g. Build, which Loads to fail loudly on a bad file) use these; the package-level helpers below are for the path-check sites.

type Review

type Review struct {
	Compose string            `yaml:"compose"`
	Env     map[string]string `yaml:"env"`
}

Review is the trusted, committed environment used only for a disposable review candidate. It lets a repository use a minimal CI-like dependency stack instead of copying ignored local development state into the scratch clone.

type Route

type Route struct {
	Paths   []string `yaml:"paths"`   // repo-relative globs (e.g. "portal/**", "**/*.ex")
	Include []string `yaml:"include"` // repo-relative docs to compile when a path matches
}

Route includes its Docs whenever any of its Paths globs matches a scope path. Both are repo-relative (validated in Load); Paths support `*` within a segment and `**` across segments.

type Serve

type Serve struct {
	Ports []int `yaml:"ports"` // what your dev server listens on inside the box
}

Serve is the serving config: container ports to publish.

Jump to

Keyboard shortcuts

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