Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
273 changes: 273 additions & 0 deletions docs/ADRs/0003-org-config-repo-convention.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,273 @@
---
title: "3. Org-level configuration lives in a conventional repo"
status: Proposed
relates_to:
- governance
- codebase-context
- intent-representation
- architectural-invariants
- agent-architecture
- agent-infrastructure
topics:
- configuration
- adoption
- convention
---

# 3. Org-level configuration lives in a conventional repo

Date: 2026-03-25

## Status

Proposed

## Context

An organization adopting fullsend must configure it: the intent repo, the
architecture documentation, runtime and model, infrastructure, sandbox
defaults, org-specific agents and skills, and per-repo overrides. (See issue
#75.)

Today no conventional location exists. Without one, every tool must be told
where to find config, or each tool invents its own convention.

## Options

### Option 1: `<org>/.fullsend` repo

Each adopting organization creates a repo named `.fullsend` in their org or
group (GitHub org, GitLab group, Forgejo org, or equivalent) — the single
entry point for all fullsend configuration.

The dot-prefix mirrors `.github` for org-level configuration, signaling
"infrastructure/meta" rather than application code. The name avoids collisions
with other tooling.

**Pros:**
- Clean, memorable convention. Tooling looks in exactly one place.
- Org-owned — the adopting org controls configuration, permissions, and review.
- Decoupled from fullsend's release cycle.
- Dot-prefix follows an established pattern (`.github`, `.gitlab`).
- CODEOWNERS enforces appropriate approval on configuration changes.

**Cons:**
- Dot-prefixed repos sort differently and sometimes hide in forge UIs.
- Adopters must learn a new convention.
- Dot-prefix visibility varies across platforms.

### Option 2: `<org>/fullsend-config` repo

Same as Option 1, without the dot-prefix.

**Pros:**
- Appears in normal alphabetical listings on all forges.
- Name is self-documenting.

**Cons:**
- Lacks the dot-prefix signal for "meta/infra."
- Slightly more generic name; collision unlikely but possible.

### Option 3: Configuration inside an existing platform meta-repo

Put fullsend configuration in a subdirectory of the org's existing platform
meta-repo (GitHub's `.github` or equivalent). GitLab and Forgejo lack an
equivalent convention — itself a problem with this option.

**Pros:**
- No new repo on platforms that already have a meta-repo.
- Permissions may already exist.

**Cons:**
- Mixes concerns. Meta-repos serve issue templates, CI config, and community
health files; adding agent configuration overloads their purpose.
- Tooling must look inside a subdirectory of a multi-purpose repo.
- CODEOWNERS for fullsend config must coexist with other CODEOWNERS rules.
- Growing fullsend config (agents, skills, workflows) would dominate the
meta-repo.
- Not portable: GitHub's `.github` has no equivalent on GitLab or Forgejo.

### Option 4: External configuration management system

Use a runtime configuration store (Consul, etcd, HashiCorp Vault, AWS
Parameter Store) as the source of truth for org-level config.

**Pros:**
- Purpose-built for configuration: dynamic updates, access control, secret
storage.
- Some organizations already run these systems.

**Cons:**
- Breaks the "everything auditable in version control" principle — no PR
review, no CODEOWNERS, no merge history.
- Introduces infrastructure dependencies that vary across environments.
- Each store has its own API, auth model, and operational requirements.
- Config changes bypass the review and governance processes fullsend relies
on.
- Structural configuration (agents, workflows, intent repo location) belongs
in version control; only secrets and dynamic runtime values belong in
systems like Vault.

### Option 5: Forge-native org/group settings

Store fullsend configuration in the forge's own org-level settings (GitHub
org settings API, GitLab group variables, Forgejo org settings).

**Pros:**
- No additional repo or system.

**Cons:**
- Opaque: no version control, no merge-request review, no audit trail
beyond platform logs.
- Each platform exposes different settings APIs; a model that works on
GitHub may not map to GitLab or Forgejo.
- Key-value or flat structures lack the expressiveness for agent
definitions, workflow overrides, or layered inheritance.
- Platform admin permissions govern changes, not CODEOWNERS-style
path-level review.

### Option 6: Hosted control plane / SaaS

A hosted web service where orgs configure fullsend via a UI or API.

**Pros:**
- Could offer a polished experience with validation, previews, and guided
setup.

**Cons:**
- Introduces a central dependency the org does not control.
- Moves configuration out of version control — no PR review, no CODEOWNERS,
no git history.
- Creates a high-value attack target: compromising the control plane
compromises every org.
- Contradicts fullsend's design philosophy: the repo is the coordinator,
not a service.

### Option 7: Configuration inside the fullsend repo itself

Each adopting org gets a directory in the fullsend repo (e.g., `orgs/nonflux/`).

**Pros:**
- Everything in one place; maintainers see all adopters.

**Cons:**
- Couples org config to fullsend's release cycle and permissions.
- Orgs cannot modify config without a PR to fullsend.
- Violates the principle that org config is org-owned.
- Conflates the framework with its instances.

## Decision

Adopting organizations create a **`<org>/.fullsend`** repo as the conventional
location for all org-level fullsend configuration.

This repo is the root of the dependency graph for fullsend in an org. All
tooling — harness, trigger layer, agent runtimes, drift scanners — starts here.
The convention is:

1. **Tooling looks for `<org>/.fullsend`** to bootstrap. If the repo exists,
the org has adopted fullsend. If not, there is nothing to configure.
2. **The `.fullsend` repo points to everything else:** the intent repo,
architecture repo, infrastructure config, agent definitions, workflow
definitions, sandbox profiles, and per-repo overrides.
3. **The adopting org governs the `.fullsend` repo.** Its CODEOWNERS, branch
protection, and review requirements follow the org's governance model.
Changes here are governance-level changes (see
[governance.md](../problems/governance.md) — configuration security).
4. **Agents cannot modify this repo.** The `.fullsend` repo defines agent
behavior; agents must not modify their own configuration. Enforcement:
exclude bot/service accounts from write access and require human approval
via CODEOWNERS on all paths. This aligns with the principle that CODEOWNERS
files are always human-owned.

### Repo structure (initial)

```
.fullsend/
config.yaml # Top-level org configuration
guardrails.yaml # Org-wide guardrails (separate file for CODEOWNERS)
agents/ # Org-specific agent definitions (extends base set)
skills/ # Org-specific skills (extends base set)
workflows/ # Workflow overrides/extensions
repos/ # Per-repo configuration overrides
<repo-name>.yaml
```

The `config.yaml` contains pointers and org-wide defaults. This repo holds
structural configuration only; secrets (API keys, credentials) are managed
separately via the org's secret management system (Vault, sealed secrets, etc.).

```yaml
version: 1 # Schema version for future evolution

# Where to find org-specific resources
intent_repo: <org>/features # or <org>/intent
architecture_repo: <org>/architecture

# Agent runtime defaults
runtime:
harness: claude-code # or opencode
model: claude-sonnet-4-6

# Infrastructure
infrastructure:
platform: kubernetes # or github-actions, etc.
# platform-specific config follows

# Sandbox defaults
sandbox:
network_policy: restricted
filesystem: ephemeral
```

Per-repo overrides in `repos/<repo-name>.yaml` can override org defaults
(within the bounds of org-wide guardrails that cannot be weakened).

The exact schema will evolve. The decision here is about the convention and
location, not the schema details.

### Inheritance model

Base fullsend provides default agents, skills, and workflows. The `.fullsend`
repo extends or overrides them for the org. Per-repo config in
`repos/<repo-name>.yaml` further overrides for specific repos. The layering is:

```
fullsend defaults < org .fullsend config < per-repo overrides
```

Org config can add agents, skills, and workflows. It can override defaults. It
cannot weaken org-wide guardrails. Guardrails live in a separate
`guardrails.yaml` file so that CODEOWNERS can enforce stricter review on that
file specifically (CODEOWNERS operates on file paths, not YAML sections).

**Limitation:** per-repo overrides in `repos/<repo-name>.yaml` use the same
layering mechanism as org-over-upstream. Without additional enforcement, a repo
override could weaken org-level guardrails. The exact mechanism for protecting
org guardrails from repo-level override is tracked as a follow-up (see issue
#84).

## Consequences

- **Single, discoverable configuration root.** No ambiguity about where
config lives.
- **Org-owned.** The adopting org controls permissions, review, and release
cadence for its own config — no PRs to fullsend needed.
- **Security-critical asset.** The `.fullsend` repo defines agent behavior
and must be protected accordingly: restricted write access, required
reviews, audit logging. (See [governance.md](../problems/governance.md) —
configuration security.)
- **Stable convention for tooling.** Harness assembly, trigger layer, and
CLI tooling all assume `.fullsend` exists and follow pointers from there.
- **Centralized per-repo overrides.** All org configuration is auditable in
one place rather than scattered across repos.
- **`docs/problems/applied/` stays for problem analysis**, not operational
config.
- **Natural bootstrap for adoption.** A fullsend installer's first step is
creating the `.fullsend` repo and populating initial config. Everything
else flows from that repo existing.
- **Guardrail override gap.** The inheritance model does not yet define how
an org protects specific settings from being weakened by per-repo overrides.
Separating guardrails into their own file solves the org-level CODEOWNERS
problem, but the repo-level override boundary needs further design (issue
#84).
17 changes: 13 additions & 4 deletions docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ The compute and orchestration layer that runs agent workloads. Responsible for p

This is the "where do agents physically run" question — whether that's a managed platform, internal Kubernetes, CI runners repurposed for agent work, or something purpose-built.

Infrastructure platform choice and configuration are specified in the org's `<org>/.fullsend` repo. (See [ADR 0003](ADRs/0003-org-config-repo-convention.md).)

**Open questions:**

- Do we adopt a 3rd party platform, use existing internal infrastructure, or build our own? (See [agent-infrastructure.md](problems/agent-infrastructure.md) for the three directions.)
Expand All @@ -24,6 +26,8 @@ The isolation boundary around a running agent. Responsible for filesystem access

The sandbox is a security primitive. Its job is containment: if an agent is compromised or misbehaves, the blast radius is limited to what the sandbox permits.

Sandbox defaults (network policy, filesystem restrictions) are configured in the org's `<org>/.fullsend` repo and can be overridden per-repo. (See [ADR 0003](ADRs/0003-org-config-repo-convention.md).)

**Open questions:**

- What is the right isolation level — process, container, microVM, or separate cluster? (See [agent-infrastructure.md](problems/agent-infrastructure.md) and [security-threat-model.md](problems/security-threat-model.md).)
Expand All @@ -37,12 +41,13 @@ The configuration and context layer that prepares an agent for its task. Respons

The harness is what makes a generic LLM into a specific agent with a specific role. It assembles what the agent needs to know and what it's allowed to do before the agent starts working.

The harness draws its configuration from the org's `<org>/.fullsend` repo — skills, workflow definitions, and agent behavioral instructions are assembled from the layered config (fullsend defaults < org config < per-repo overrides). (See [ADR 0003](ADRs/0003-org-config-repo-convention.md).)

**Open questions:**

- Does the harness live inside the sandbox (configuring the agent from within its isolation boundary) or outside it (preparing the environment before the agent starts)?
- How is codebase context assembled? (See [codebase-context.md](problems/codebase-context.md).)
- How do we version and test harness configurations? (See [testing-agents.md](problems/testing-agents.md).)
- Is the harness per-role, per-repo, or both?

## Agent Runtime

Expand Down Expand Up @@ -89,9 +94,10 @@ Where agent behavioral rules live. Responsible for holding autonomy levels, revi

Policy is distinct from the harness (which configures *how* an agent works) and from intent (which defines *what* work is authorized). Policy defines the *boundaries* of agent behavior — what an agent is allowed to do regardless of what it's asked to do.

The org's `<org>/.fullsend` repo is the natural home for policy configuration — org-wide guardrails, per-repo autonomy levels, and escalation rules all live there, governed by the org's own CODEOWNERS and review process. (See [ADR 0003](ADRs/0003-org-config-repo-convention.md).)

**Open questions:**

- Where does policy live — a dedicated repo, per-repo configuration files, or a combination? (See [governance.md](problems/governance.md).)
- How is policy versioned, and how do we ensure agents run under the correct policy version?
- Who can change policy, and what approval process governs policy changes? (See [governance.md](problems/governance.md).)
- How does policy interact with the autonomy spectrum — is the auto-merge vs. escalate decision a policy setting? (See [autonomy-spectrum.md](problems/autonomy-spectrum.md).)
Expand All @@ -102,9 +108,11 @@ The system that provides authorized intent for agent work. Responsible for repre

Intent answers the question "should this change exist?" before anyone asks "is this change correct?" Without authorized intent, an agent has no basis for deciding what to work on or whether its output matches what was asked for.

The org's `<org>/.fullsend` repo holds the pointer to the intent source (e.g., `intent_repo: <org>/features`), so tooling discovers where intent lives without hardcoding. (See [ADR 0003](ADRs/0003-org-config-repo-convention.md).)

**Open questions:**

- What is the right representation — GitHub issues, a dedicated intent repo, RFCs, or tiered combinations? (See [intent-representation.md](problems/intent-representation.md).)
- What is the right representation — forge issues, a dedicated intent repo, RFCs, or tiered combinations? (See [intent-representation.md](problems/intent-representation.md).)
- How do agents verify that intent is authentic and hasn't been tampered with?
- How do different tiers of intent (standing rules, tactical issues, strategic features) map to different authorization requirements?
- How does intent interact with the "try it" phase — agents building exploratory drafts before authorization? (See [intent-representation.md](problems/intent-representation.md).)
Expand All @@ -129,9 +137,10 @@ The catalog of available agent roles and their configurations. Responsible for d

The registry is the bridge between the abstract roles defined in [agent-architecture.md](problems/agent-architecture.md) (correctness agent, intent alignment agent, etc.) and the concrete runtime configurations that the harness uses to set up each agent.

Fullsend provides a base set of agent definitions. The org's `<org>/.fullsend` repo extends this with org-specific agents in its `agents/` directory, following the inheritance model: fullsend defaults < org config < per-repo overrides. (See [ADR 0003](ADRs/0003-org-config-repo-convention.md).)

**Open questions:**

- Is the registry a formal system (a database, a config repo) or an informal convention (a directory of harness configurations)?
- How are new agent roles added, tested, and promoted to production? (See [testing-agents.md](problems/testing-agents.md).)
- Does the registry include version information, so we can roll back to a previous agent configuration?
- How does the registry relate to the policy store — does policy reference registry entries, or are they independent?