From 6fc9eaddd3b882cb50e8580c8eeb67f41883f0cd Mon Sep 17 00:00:00 2001 From: Ralph Bean Date: Wed, 25 Mar 2026 16:31:58 -0400 Subject: [PATCH 1/3] ADR 0003: org-level config lives in /.fullsend repo MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Establishes the convention that adopting organizations create a .fullsend repo as the single entry point for all fullsend configuration. This repo holds pointers to intent and architecture repos, agent runtime defaults, infrastructure and sandbox config, workflow overrides, org-specific agent definitions and skills, per-repo overrides, and org-wide guardrails. The ADR evaluates seven options including non-git alternatives (external config stores, forge-native settings, hosted SaaS) and explains why version-controlled, CODEOWNERS-governed configuration in a conventional repo is the right fit. The convention is forge-agnostic — works for GitHub orgs, GitLab groups, and Forgejo orgs. Updates docs/architecture.md to reference the .fullsend repo as the configuration home for six components: Agent Infrastructure, Agent Sandbox, Agent Harness, Policy Store, Intent Source, and Agent Registry. Closes several open questions that this decision answers. Relates to #75. Co-Authored-By: Claude Opus 4.6 --- docs/ADRs/0003-org-config-repo-convention.md | 314 +++++++++++++++++++ docs/architecture.md | 17 +- 2 files changed, 327 insertions(+), 4 deletions(-) create mode 100644 docs/ADRs/0003-org-config-repo-convention.md diff --git a/docs/ADRs/0003-org-config-repo-convention.md b/docs/ADRs/0003-org-config-repo-convention.md new file mode 100644 index 0000000000..12117c36dc --- /dev/null +++ b/docs/ADRs/0003-org-config-repo-convention.md @@ -0,0 +1,314 @@ +--- +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 + +Fullsend defines a general framework — agents, workflows, review models, intent +systems, sandbox profiles — but an organization adopting fullsend needs to +configure all of this for their specific context. Today there is no conventional +place for that configuration. Issue #75 identifies the gap: core fullsend +content is organization-agnostic, but adopting organizations need a place for +operational configuration that tooling can discover automatically. + +The configuration an org needs to provide includes: + +- **Pointers to org-specific repos.** Where is the intent/features repo (see + [intent-representation.md](../problems/intent-representation.md))? Where is + the architecture documentation (see + [architectural-invariants.md](../problems/architectural-invariants.md))? +- **Agent runtime defaults.** Which agent runtime to use, which model, what + resource limits. +- **Workflow definitions.** Base workflow overrides or extensions for the org + (see issue #68, #69). +- **Infrastructure layer configuration.** Where agents run — Kubernetes, + CI runners, or other compute (see + [agent-infrastructure.md](../problems/agent-infrastructure.md), issue #79). +- **Sandbox layer configuration.** Isolation profiles, network policies, + filesystem restrictions (issue #78). +- **Harness assembly configuration.** How the trigger layer, runtime, and + sandbox are composed into a running agent session (issue #74). +- **Org-specific agents and skills.** Additional agent definitions and skills + beyond the base set (issues #71, #72). +- **Per-repo overrides.** Repos within the org that need different + configuration from the org defaults. +- **Org-wide guardrails.** Minimum standards that repos cannot weaken (see + [governance.md](../problems/governance.md)). + +Without a conventional location, every piece of tooling that needs this +information must be told where to find it — or worse, each tool invents its own +convention. A single conventional repo makes the entire system bootstrappable: +tooling knows where to look, and everything else is discovered from there. + +## Options + +### Option 1: `/.fullsend` repo + +Each adopting organization creates a repo named `.fullsend` in their org or +group (GitHub org, GitLab group, Forgejo org, or equivalent). This is the +single entry point for all fullsend configuration in that org. + +The dot-prefix mirrors conventions like GitHub's `.github` repo for org-level +configuration. It signals "infrastructure/meta" rather than application code. +The name is specific enough that it won't collide with other tooling. + +**Pros:** +- Clean, memorable convention. Tooling has exactly one place to look. +- Org-owned — the adopting org controls their own configuration, permissions, + and review process. +- Decoupled from fullsend's release cycle. Org config evolves independently. +- The dot-prefix is a well-established pattern (`.github`, `.gitignore`, + `.editorconfig`). +- CODEOWNERS in this repo can enforce that configuration changes require + appropriate approval, aligning with the governance model. + +**Cons:** +- Dot-prefixed repos can be less visible in some forge UIs (sorted differently, + sometimes hidden in listings). +- Establishes a new convention that adopters need to learn. +- GitLab groups and Forgejo orgs support the same repo naming, but visibility + behavior of dot-prefixed repos may vary across platforms. + +### Option 2: `/fullsend-config` repo + +Same as Option 1 but without the dot-prefix. More explicit and visible. + +**Pros:** +- More discoverable across all forge UIs — appears in normal alphabetical + listings regardless of platform. +- Name is self-documenting. + +**Cons:** +- Doesn't benefit from the dot-prefix convention signaling "meta/infra." +- Slightly more generic name — could theoretically collide, though unlikely. + +### 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 don't have +an exact equivalent convention, which is itself a problem with this option.) + +**Pros:** +- No new repo to create on platforms that have a meta-repo convention. +- Permissions may already be set up. + +**Cons:** +- Mixes concerns. Platform meta-repos have their own established conventions + (issue templates, CI config, default community health files). Adding a full + agent configuration system overloads their purpose. +- Harder for tooling to isolate — must look inside a subdirectory of a repo + that serves other purposes. +- CODEOWNERS for fullsend config would need to coexist with CODEOWNERS for + other content in the same repo. +- As fullsend config grows (agent definitions, skills, workflow overrides), + it could dominate the meta-repo. +- Not portable across forges. GitHub's `.github` repo doesn't have a direct + equivalent on GitLab or Forgejo, so this option only works for some + platforms. + +### Option 4: External configuration management system + +Use a runtime configuration store — Consul, etcd, HashiCorp Vault, AWS +Parameter Store, or similar — as the source of truth for org-level config. + +**Pros:** +- Purpose-built for configuration management. Dynamic updates, access + control, secret storage. +- Some organizations already run these systems. + +**Cons:** +- Breaks the "everything is auditable in version control" principle. No PR + review, no CODEOWNERS, no merge history on config changes. +- Introduces infrastructure dependencies that not every org has and that + vary across environments. +- Not portable — each store has its own API, auth model, and operational + requirements. +- Config changes become opaque to the review and governance processes + that fullsend relies on. A change to agent permissions in Consul doesn't + go through the same governed review as a change in a git repo. +- Secrets and dynamic runtime values (API keys, tokens) belong in systems + like Vault. But structural configuration (what agents exist, what + workflows to use, where the intent repo is) is not secret and benefits + from version control and review. + +### 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. Configuration lives where the org already + manages settings. + +**Cons:** +- Opaque — not version-controlled, not reviewable via merge requests, no + audit trail beyond platform logs. +- Varies across forges. Each platform exposes different settings APIs with + different capabilities. A configuration model that works on GitHub may + not map to GitLab or Forgejo. +- Limited expressiveness. Org settings are key-value or flat structures, + not rich enough for agent definitions, workflow overrides, or layered + inheritance. +- Governed by platform admin permissions, not CODEOWNERS-style path-level + review — less granular control over who can change what. + +### Option 6: Hosted control plane / SaaS + +A hosted web service where orgs configure fullsend via a UI or API. + +**Pros:** +- Could offer a polished configuration experience with validation, + previews, and guided setup. + +**Cons:** +- Introduces a central service dependency — availability, security, and + trust properties are no longer in the org's control. +- Moves configuration out of version control. No PR-based review, no + CODEOWNERS, no git history. +- Creates a high-value attack target. Compromising the control plane + compromises every org's agent configuration. +- Contrary to 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. Simple for the fullsend maintainers to see all + adopters. + +**Cons:** +- Couples org config to fullsend's release cycle and permissions. An org + can't modify their own config without a PR to fullsend. +- Doesn't scale. Every adopting org's config changes create PRs in fullsend. +- Violates the principle that org config is org-owned. +- Conflates the framework with its instances. + +## Decision + +Adopting organizations create a **`/.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 — the harness, trigger layer, agent runtimes, drift scanners — discovers +what it needs starting from this repo. The convention is: + +1. **Tooling looks for `/.fullsend`** to bootstrap. If the repo exists, + the org has adopted fullsend. If it doesn't, there's nothing to configure. +2. **The `.fullsend` repo points to everything else.** It contains or + references: the intent repo, the architecture repo, infrastructure config, + agent definitions, workflow definitions, sandbox profiles, and per-repo + overrides. +3. **The `.fullsend` repo is governed by the adopting org.** Its CODEOWNERS, + branch protection, and review requirements are set by the org according to + their governance model. Changes to this repo are governance-level changes + (see [governance.md](../problems/governance.md) — configuration security). +4. **Agents cannot modify this repo.** This is a hard rule. The `.fullsend` + repo defines agent behavior; agents must not be able to modify their own + configuration. This aligns with the existing principle that CODEOWNERS + files are always human-owned. + +### Repo structure (initial) + +``` +.fullsend/ + config.yaml # Top-level org configuration + agents/ # Org-specific agent definitions (extends base set) + skills/ # Org-specific skills (extends base set) + workflows/ # Workflow overrides/extensions + repos/ # Per-repo configuration overrides + .yaml +``` + +The `config.yaml` contains pointers and org-wide defaults: + +```yaml +# Where to find org-specific resources +intent_repo: /features # or /intent +architecture_repo: /architecture + +# Agent runtime defaults +runtime: + default: 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/.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/.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 (that's a governance enforcement, not a +technical one — CODEOWNERS on the guardrails section of config prevents it). + +## Consequences + +- **Every adopting org gets a single, discoverable configuration root.** No + ambiguity about where config lives or how tooling finds it. +- **Org config is fully org-owned.** No PRs to the fullsend repo needed for + org-specific changes. The org controls permissions, review, and release + cadence for their own config. +- **The `.fullsend` repo becomes a security-critical asset.** It defines what + agents can do. It must be protected accordingly — restricted write access, + required reviews, audit logging. This is called out in the governance doc + as "configuration security." +- **Tooling can be built against a stable convention.** The harness assembly + process, trigger layer, and any CLI tooling can assume `.fullsend` exists + and follow pointers from there. +- **Per-repo overrides are centralized in the org config repo** rather than + scattered across individual repos. This makes it possible to audit and + review the full org configuration in one place. +- **The `docs/problems/applied/` directory in fullsend remains for + problem analysis**, not operational config. This cleanly separates "how we + think about this problem for org X" from "how org X actually configures + fullsend." +- **Adoption has a natural first step.** If a "fullsend installer" or setup + tool is ever built, its first action is walking the user through creating + the `.fullsend` repo in their org and populating it with initial config + values (intent repo pointer, architecture repo pointer, runtime defaults). + Everything else in the setup process flows from that repo existing. The + convention makes bootstrapping deterministic — the installer doesn't need + to ask "where should I put your config?" diff --git a/docs/architecture.md b/docs/architecture.md index 4a37a8b9dd..4cbd5525ed 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -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 `/.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.) @@ -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 `/.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).) @@ -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 `/.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 @@ -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 `/.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).) @@ -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 `/.fullsend` repo holds the pointer to the intent source (e.g., `intent_repo: /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).) @@ -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 `/.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? From 016acb7aaf2be4558ea0ac1254b74092f4056e74 Mon Sep 17 00:00:00 2001 From: Ralph Bean Date: Wed, 25 Mar 2026 16:43:44 -0400 Subject: [PATCH 2/3] Tighten ADR 0003 prose: cut wordiness in context, options, consequences Co-Authored-By: Claude Opus 4.6 --- docs/ADRs/0003-org-config-repo-convention.md | 256 +++++++------------ 1 file changed, 98 insertions(+), 158 deletions(-) diff --git a/docs/ADRs/0003-org-config-repo-convention.md b/docs/ADRs/0003-org-config-repo-convention.md index 12117c36dc..9393adc5aa 100644 --- a/docs/ADRs/0003-org-config-repo-convention.md +++ b/docs/ADRs/0003-org-config-repo-convention.md @@ -24,132 +24,89 @@ Proposed ## Context -Fullsend defines a general framework — agents, workflows, review models, intent -systems, sandbox profiles — but an organization adopting fullsend needs to -configure all of this for their specific context. Today there is no conventional -place for that configuration. Issue #75 identifies the gap: core fullsend -content is organization-agnostic, but adopting organizations need a place for -operational configuration that tooling can discover automatically. - -The configuration an org needs to provide includes: - -- **Pointers to org-specific repos.** Where is the intent/features repo (see - [intent-representation.md](../problems/intent-representation.md))? Where is - the architecture documentation (see - [architectural-invariants.md](../problems/architectural-invariants.md))? -- **Agent runtime defaults.** Which agent runtime to use, which model, what - resource limits. -- **Workflow definitions.** Base workflow overrides or extensions for the org - (see issue #68, #69). -- **Infrastructure layer configuration.** Where agents run — Kubernetes, - CI runners, or other compute (see - [agent-infrastructure.md](../problems/agent-infrastructure.md), issue #79). -- **Sandbox layer configuration.** Isolation profiles, network policies, - filesystem restrictions (issue #78). -- **Harness assembly configuration.** How the trigger layer, runtime, and - sandbox are composed into a running agent session (issue #74). -- **Org-specific agents and skills.** Additional agent definitions and skills - beyond the base set (issues #71, #72). -- **Per-repo overrides.** Repos within the org that need different - configuration from the org defaults. -- **Org-wide guardrails.** Minimum standards that repos cannot weaken (see - [governance.md](../problems/governance.md)). - -Without a conventional location, every piece of tooling that needs this -information must be told where to find it — or worse, each tool invents its own -convention. A single conventional repo makes the entire system bootstrappable: -tooling knows where to look, and everything else is discovered from there. +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: `/.fullsend` repo Each adopting organization creates a repo named `.fullsend` in their org or -group (GitHub org, GitLab group, Forgejo org, or equivalent). This is the -single entry point for all fullsend configuration in that org. +group (GitHub org, GitLab group, Forgejo org, or equivalent) — the single +entry point for all fullsend configuration. -The dot-prefix mirrors conventions like GitHub's `.github` repo for org-level -configuration. It signals "infrastructure/meta" rather than application code. -The name is specific enough that it won't collide with other tooling. +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 has exactly one place to look. -- Org-owned — the adopting org controls their own configuration, permissions, - and review process. -- Decoupled from fullsend's release cycle. Org config evolves independently. -- The dot-prefix is a well-established pattern (`.github`, `.gitignore`, - `.editorconfig`). -- CODEOWNERS in this repo can enforce that configuration changes require - appropriate approval, aligning with the governance model. +- 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`, `.editorconfig`). +- CODEOWNERS enforces appropriate approval on configuration changes. **Cons:** -- Dot-prefixed repos can be less visible in some forge UIs (sorted differently, - sometimes hidden in listings). -- Establishes a new convention that adopters need to learn. -- GitLab groups and Forgejo orgs support the same repo naming, but visibility - behavior of dot-prefixed repos may vary across platforms. +- 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: `/fullsend-config` repo -Same as Option 1 but without the dot-prefix. More explicit and visible. +Same as Option 1, without the dot-prefix. **Pros:** -- More discoverable across all forge UIs — appears in normal alphabetical - listings regardless of platform. +- Appears in normal alphabetical listings on all forges. - Name is self-documenting. **Cons:** -- Doesn't benefit from the dot-prefix convention signaling "meta/infra." -- Slightly more generic name — could theoretically collide, though unlikely. +- 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 don't have -an exact equivalent convention, which is itself a problem with this option.) +meta-repo (GitHub's `.github` or equivalent). GitLab and Forgejo lack an +equivalent convention — itself a problem with this option. **Pros:** -- No new repo to create on platforms that have a meta-repo convention. -- Permissions may already be set up. +- No new repo on platforms that already have a meta-repo. +- Permissions may already exist. **Cons:** -- Mixes concerns. Platform meta-repos have their own established conventions - (issue templates, CI config, default community health files). Adding a full - agent configuration system overloads their purpose. -- Harder for tooling to isolate — must look inside a subdirectory of a repo - that serves other purposes. -- CODEOWNERS for fullsend config would need to coexist with CODEOWNERS for - other content in the same repo. -- As fullsend config grows (agent definitions, skills, workflow overrides), - it could dominate the meta-repo. -- Not portable across forges. GitHub's `.github` repo doesn't have a direct - equivalent on GitLab or Forgejo, so this option only works for some - platforms. +- 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, or similar — as the source of truth for org-level config. +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 management. Dynamic updates, access - control, secret storage. +- Purpose-built for configuration: dynamic updates, access control, secret + storage. - Some organizations already run these systems. **Cons:** -- Breaks the "everything is auditable in version control" principle. No PR - review, no CODEOWNERS, no merge history on config changes. -- Introduces infrastructure dependencies that not every org has and that - vary across environments. -- Not portable — each store has its own API, auth model, and operational - requirements. -- Config changes become opaque to the review and governance processes - that fullsend relies on. A change to agent permissions in Consul doesn't - go through the same governed review as a change in a git repo. -- Secrets and dynamic runtime values (API keys, tokens) belong in systems - like Vault. But structural configuration (what agents exist, what - workflows to use, where the intent repo is) is not secret and benefits - from version control and review. +- 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 @@ -157,37 +114,33 @@ 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. Configuration lives where the org already - manages settings. +- No additional repo or system. **Cons:** -- Opaque — not version-controlled, not reviewable via merge requests, no - audit trail beyond platform logs. -- Varies across forges. Each platform exposes different settings APIs with - different capabilities. A configuration model that works on GitHub may - not map to GitLab or Forgejo. -- Limited expressiveness. Org settings are key-value or flat structures, - not rich enough for agent definitions, workflow overrides, or layered - inheritance. -- Governed by platform admin permissions, not CODEOWNERS-style path-level - review — less granular control over who can change what. +- 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 configuration experience with validation, - previews, and guided setup. +- Could offer a polished experience with validation, previews, and guided + setup. **Cons:** -- Introduces a central service dependency — availability, security, and - trust properties are no longer in the org's control. -- Moves configuration out of version control. No PR-based review, no - CODEOWNERS, no git history. -- Creates a high-value attack target. Compromising the control plane - compromises every org's agent configuration. -- Contrary to fullsend's design philosophy: the repo is the coordinator, +- 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 @@ -195,13 +148,11 @@ A hosted web service where orgs configure fullsend via a UI or API. Each adopting org gets a directory in the fullsend repo (e.g., `orgs/nonflux/`). **Pros:** -- Everything in one place. Simple for the fullsend maintainers to see all - adopters. +- Everything in one place; maintainers see all adopters. **Cons:** -- Couples org config to fullsend's release cycle and permissions. An org - can't modify their own config without a PR to fullsend. -- Doesn't scale. Every adopting org's config changes create PRs in fullsend. +- 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. @@ -211,23 +162,21 @@ Adopting organizations create a **`/.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 — the harness, trigger layer, agent runtimes, drift scanners — discovers -what it needs starting from this repo. The convention is: +tooling — harness, trigger layer, agent runtimes, drift scanners — starts here. +The convention is: 1. **Tooling looks for `/.fullsend`** to bootstrap. If the repo exists, - the org has adopted fullsend. If it doesn't, there's nothing to configure. -2. **The `.fullsend` repo points to everything else.** It contains or - references: the intent repo, the architecture repo, infrastructure config, - agent definitions, workflow definitions, sandbox profiles, and per-repo - overrides. -3. **The `.fullsend` repo is governed by the adopting org.** Its CODEOWNERS, - branch protection, and review requirements are set by the org according to - their governance model. Changes to this repo are governance-level changes - (see [governance.md](../problems/governance.md) — configuration security). -4. **Agents cannot modify this repo.** This is a hard rule. The `.fullsend` - repo defines agent behavior; agents must not be able to modify their own - configuration. This aligns with the existing principle that CODEOWNERS - files are always human-owned. + 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. This aligns with + the principle that CODEOWNERS files are always human-owned. ### Repo structure (initial) @@ -286,29 +235,20 @@ technical one — CODEOWNERS on the guardrails section of config prevents it). ## Consequences -- **Every adopting org gets a single, discoverable configuration root.** No - ambiguity about where config lives or how tooling finds it. -- **Org config is fully org-owned.** No PRs to the fullsend repo needed for - org-specific changes. The org controls permissions, review, and release - cadence for their own config. -- **The `.fullsend` repo becomes a security-critical asset.** It defines what - agents can do. It must be protected accordingly — restricted write access, - required reviews, audit logging. This is called out in the governance doc - as "configuration security." -- **Tooling can be built against a stable convention.** The harness assembly - process, trigger layer, and any CLI tooling can assume `.fullsend` exists - and follow pointers from there. -- **Per-repo overrides are centralized in the org config repo** rather than - scattered across individual repos. This makes it possible to audit and - review the full org configuration in one place. -- **The `docs/problems/applied/` directory in fullsend remains for - problem analysis**, not operational config. This cleanly separates "how we - think about this problem for org X" from "how org X actually configures - fullsend." -- **Adoption has a natural first step.** If a "fullsend installer" or setup - tool is ever built, its first action is walking the user through creating - the `.fullsend` repo in their org and populating it with initial config - values (intent repo pointer, architecture repo pointer, runtime defaults). - Everything else in the setup process flows from that repo existing. The - convention makes bootstrapping deterministic — the installer doesn't need - to ask "where should I put your config?" +- **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. From 426d4338a26b532b798d2d334ae2e9acc15de0e1 Mon Sep 17 00:00:00 2001 From: Ralph Bean Date: Wed, 25 Mar 2026 19:07:36 -0400 Subject: [PATCH 3/3] Address review feedback: guardrails file, agent enforcement, config clarity - Separate guardrails into dedicated `guardrails.yaml` so CODEOWNERS can gate changes (CODEOWNERS operates on file paths, not YAML sections) - Clarify agent modification enforcement: bot exclusion + CODEOWNERS - Add secrets management note (structural config only, not secrets) - Add `version: 1` schema version field to config example - Rename `runtime.default` to `runtime.harness` to avoid redundancy - Replace `.editorconfig` (a file) with `.gitlab` (a repo) as precedent - Call out guardrail override gap as explicit limitation and consequence - Filed #84 to track guardrail protection mechanism design Resolves review feedback from waynesun09 and ralphbean on PR #80. Co-Authored-By: Claude Opus 4.6 --- docs/ADRs/0003-org-config-repo-convention.md | 33 +++++++++++++++----- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/docs/ADRs/0003-org-config-repo-convention.md b/docs/ADRs/0003-org-config-repo-convention.md index 9393adc5aa..352902af23 100644 --- a/docs/ADRs/0003-org-config-repo-convention.md +++ b/docs/ADRs/0003-org-config-repo-convention.md @@ -48,7 +48,7 @@ with other tooling. - 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`, `.editorconfig`). +- Dot-prefix follows an established pattern (`.github`, `.gitlab`). - CODEOWNERS enforces appropriate approval on configuration changes. **Cons:** @@ -175,14 +175,17 @@ The convention is: 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. This aligns with - the principle that CODEOWNERS files are always human-owned. + 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 @@ -190,16 +193,20 @@ The convention is: .yaml ``` -The `config.yaml` contains pointers and org-wide defaults: +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: /features # or /intent architecture_repo: /architecture # Agent runtime defaults runtime: - default: claude-code # or opencode + harness: claude-code # or opencode model: claude-sonnet-4-6 # Infrastructure @@ -230,8 +237,15 @@ 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 (that's a governance enforcement, not a -technical one — CODEOWNERS on the guardrails section of config prevents 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/.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 @@ -252,3 +266,8 @@ technical one — CODEOWNERS on the guardrails section of config prevents it). - **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).