Skip to content
Open
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
11 changes: 11 additions & 0 deletions docs/ADRs/0045-forge-portable-harness-schema.md
Original file line number Diff line number Diff line change
Expand Up @@ -588,6 +588,17 @@ forge-specific artifact. The harness and agent definition are portable.
removing an agent is deleting a file, adding one is creating a thin
wrapper with `base:`.

- **Bidirectional composition.** The `base:` merge semantics (scalars
override, slices concatenate, maps merge, security fields never inherited)
have an inverse: `DiffHarness` in `internal/harness/diff.go` computes
the minimal child harness that reproduces a full harness when composed
with a given base. This powers
[ADR 0064](0064-deprecate-customized-directory-overlay.md)'s
`migrate-customizations` command, which converts `customized/` directory
overlays into `base:` composition harnesses. The diff engine mirrors
`mergeBaseIntoChild` semantics exactly — changes to merge rules must be
reflected in both directions.

- **Default URL allowlist for `base` composition.** `fullsend install`
sets `allowed_remote_resources` in `config.yaml` to include the
fullsend scaffold URL prefix
Expand Down
2 changes: 2 additions & 0 deletions docs/ADRs/0064-deprecate-customized-directory-overlay.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@ implemented and in production.

- Users who placed files in `customized/` must migrate to `base:`
composition, URL references, or config-based registration.
`fullsend agent migrate-customizations` automates this conversion and
delivers the changes via pull request.
- Deprecation warnings during install and updated documentation will guide
migration.
- The reusable workflows become simpler — no overlay loop, no
Expand Down
2 changes: 1 addition & 1 deletion docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ Fullsend provides a base set of agent definitions. The adopting organization's *
- Config-level agent registration: an `agents` list in both `OrgConfig` and `PerRepoConfig` declares agent harness sources as pinned URLs or local paths, replacing compiled-in agent discovery ([ADR 0058](ADRs/0058-agent-registration.md)).
- Runtime resolution: `fullsend run <name>` looks up the agent in config and loads the harness directly from the URL or path — no intermediate wrapper files on disk. Role and slug come from the harness content itself.
- Additive merge: config entries overlay scaffold-discovered agents (config wins on name collision), enabling gradual extraction of first-party agents without disrupting existing installations. Builds on [ADR 0045](ADRs/0045-forge-portable-harness-schema.md) harness identity model.
- CLI management: `fullsend agent add/list/update/remove` manages config entries and auto-pins URLs to a commit SHA with an integrity hash.
- CLI management: `fullsend agent add/list/update/remove/migrate-customizations` manages config entries and auto-pins URLs to a commit SHA with an integrity hash.

**Open questions:**

Expand Down
2 changes: 1 addition & 1 deletion docs/cli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ Download the latest binary from [GitHub Releases](https://github.com/fullsend-ai
| Command | Description |
|---------|-------------|
| `fullsend run` | Execute an agent locally in a sandbox. See [running agents locally](../guides/user/running-agents-locally.md). |
| `fullsend agent` | Manage agent registrations in config (add, list, update, remove) |
| `fullsend agent` | Manage agent registrations in config (add, list, update, remove, migrate-customizations) |
| `fullsend lock [agent-name]` | Pin remote dependencies to `lock.yaml` |
| `fullsend scan` | Run security scanners on agent input/output |

Expand Down
29 changes: 28 additions & 1 deletion docs/guides/dev/cli-internals.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,11 @@ fullsend
│ ├── add <url-or-path> # Register an agent (URL auto-pinned)
│ ├── list # List registered agents
│ ├── update <name> [sha] # Re-pin URL agent to new commit SHA
│ └── remove <name> # Unregister agent from config
│ ├── remove <name> # Unregister agent from config
│ └── migrate-customizations # Migrate customized/ → config agents
│ ├── --fullsend-dir <dir> # Base directory with .fullsend layout
│ ├── --repo <owner/repo> # Target repo for migration PR
│ └── --dry-run # Preview changes without PR
├── lock [agent-name] # Pin remote deps to lock.yaml
│ ├── --all # Lock all harnesses in the harness directory
│ ├── --fullsend-dir <path> # Base directory with .fullsend layout
Expand Down Expand Up @@ -85,6 +89,28 @@ fullsend
└── --role <string> # Agent role for minting (required with --mint-url)
```

### Migrate Customizations

The `fullsend agent migrate-customizations` command converts `customized/` directory overlays (deprecated by [ADR-0064](../../ADRs/0064-deprecate-customized-directory-overlay.md)) into config-driven agents with `base:` composition harnesses. It scans the local `customized/` directory, classifies each override, and delivers changes via PR:

```bash
# Preview what would change (no PR created)
fullsend agent migrate-customizations --fullsend-dir .fullsend --dry-run

# Create a migration PR
fullsend agent migrate-customizations --fullsend-dir .fullsend --repo owner/repo
```

Migration actions per agent:

| Override type | Detection | Action |
|---------------|-----------|--------|
| Dead | Agent already registered in config | Delete customized files |
| Custom | Not in upstream scaffold | Move files, register local path in config |
| Modified | Standard scaffold agent, not in config | Compute `base:` composition harness via `DiffHarness`, register in config |

The diff engine (`internal/harness/diff.go`) computes the minimal child harness that reproduces the customized version when composed with the upstream base. It mirrors `mergeBaseIntoChild` semantics: scalar overrides, slice concatenation extras, map merge deltas, and security fields always included.

### Command Decomposition

The `mint`, `inference`, and `github` subcommands decompose setup into role-specific operations for organizations that separate GCP and GitHub responsibilities:
Expand Down Expand Up @@ -549,6 +575,7 @@ var executableFiles = map[string]struct{}{
|------|-------|---------|
| `internal/cli/root.go` | ~34 | CLI entry point, command registration |
| `internal/cli/admin.go` | ~2415 | Install/uninstall/analyze/enable/disable |
| `internal/cli/migrate.go` | ~520 | Migrate customized/ overrides to config-driven agents |
| `internal/cli/mint.go` | ~1022 | Mint deploy/enroll/unenroll/status |
| `internal/cli/inference.go` | ~408 | Inference WIF provision/status |
| `internal/cli/github.go` | ~966 | GitHub setup/set/status/uninstall/sync-scaffold/enroll/unenroll |
Expand Down
1 change: 1 addition & 0 deletions docs/guides/getting-started/operations.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ For organizations that separate GCP and GitHub responsibilities across teams, fu
| Developer | `fullsend agent list` | List registered agents and their sources |
| Developer | `fullsend agent update <name> [sha]` | Re-pin a URL agent to a new commit SHA |
| Developer | `fullsend agent remove <name>` | Unregister an agent from config |
| Developer | `fullsend agent migrate-customizations` | Migrate `customized/` overlays to config-driven agents via PR |

The typical handoff: a GCP admin runs `mint deploy` + `mint enroll` + `inference provision`, then passes the mint URL and WIF provider resource name to a GitHub maintainer who runs `github setup --mint-url=... --inference-wif-provider=...`.

Expand Down
6 changes: 6 additions & 0 deletions docs/guides/user/building-custom-agents.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Building custom agents

> **Deprecated:** This guide uses the `customized/` directory overlay, which is
> deprecated per [ADR-0064](../../ADRs/0064-deprecate-customized-directory-overlay.md).
> For new custom agents, register them in `config.yaml` with a local `source:`
> path instead. Run `fullsend agent migrate-customizations --dry-run` to
> preview migrating existing customizations.

This guide walks through creating a new custom agent from scratch on a per-repo fullsend installation.

For customizing existing agents (overriding harnesses, skills, or policies), see [Customizing agents](customizing-agents.md).
Expand Down
18 changes: 18 additions & 0 deletions docs/guides/user/customizing-agents.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,17 @@ security: # Security is enabled by default with fail_mode

## Layered Configuration Resolution

> **Deprecated:** The `customized/` directory overlay mechanism described
> below is deprecated per [ADR-0064](../../ADRs/0064-deprecate-customized-directory-overlay.md).
> Use `base:` composition instead: register agents in `config.yaml` with a
> `base:` URL pointing to the upstream harness, and override only the fields
> that differ. See [ADR-0045](../../ADRs/0045-forge-portable-harness-schema.md)
> for the composition model and [ADR-0058](../../ADRs/0058-agent-registration.md)
> for config-driven registration.
> Run `fullsend agent migrate-customizations --dry-run` to preview the
> migration, then `fullsend agent migrate-customizations --repo owner/repo`
> to apply it.

Fullsend uses a three-tier configuration inheritance model for all configuration: agent definitions, skills, policies, harness definitions, and guardrails. Each configuration tier can extend or override the one below it.

```
Expand Down Expand Up @@ -149,6 +160,9 @@ For per-repo mode, the same structure lives at `.fullsend/customized/` within th

### How Override Resolution Works

> **Deprecated:** This section describes the deprecated `customized/` overlay.
> See the [deprecation notice above](#layered-configuration-resolution).

**File-level replacement, not field-level merging.** When you place a file in `customized/harness/code.yaml`, it completely replaces the upstream `harness/code.yaml`. There is no YAML field merging.

**Example: Adding a skill to the code agent**
Expand Down Expand Up @@ -190,6 +204,10 @@ To add a custom skill to the code agent's harness:

### Customizing Pre-commit Tool Dependencies

> **Note:** The `customized/scripts/.pre-commit-tools.yaml` L1 overlay path
> referenced below uses the deprecated `customized/` mechanism.
> The per-repo L2 path (`.pre-commit-tools.yaml` at repo root) is unaffected.

Fullsend auto-detects and installs tools required by a target repo's pre-commit hooks. The resolver reads `.pre-commit-config.yaml`, matches hooks against a tools registry, and installs missing dependencies before the authoritative pre-commit check runs.

Only hooks that pre-commit **cannot self-serve** need registry entries:
Expand Down
3 changes: 2 additions & 1 deletion docs/guides/user/customizing-with-agents-md.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,8 @@ takes precedence.
cannot write files regardless of what AGENTS.md says)
- Remove or replace built-in skills — use
[`customized/skills/`](customizing-with-skills.md#overriding-built-in-skills)
for that
for that (note: `customized/` is deprecated per ADR-0064; use
config-driven agents instead — see `fullsend agent migrate-customizations`)
- Change the agent's model or execution parameters

### Injection handling
Expand Down
4 changes: 4 additions & 0 deletions docs/guides/user/customizing-with-skills.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,10 @@ when available.

## Overriding built-in skills

> **Deprecated:** The `customized/` overlay described below is deprecated per
> [ADR-0064](../../ADRs/0064-deprecate-customized-directory-overlay.md).
> Use `base:` composition and config-driven agent registration instead.

To intentionally **replace** a built-in skill with your own version, use the
`customized/` overlay ([ADR 0035](../../ADRs/0035-layered-content-resolution.md)).
This replaces the skill at the config layer before the agent starts — the
Expand Down
5 changes: 5 additions & 0 deletions docs/guides/user/running-agents-locally.md
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,11 @@ cp -r /tmp/fullsend-ai_fullsend/internal/scaffold/fullsend-repo/. /tmp/agents/

Then apply your organization customizations, if any:

> **Note:** The `customized/` overlay mechanism is deprecated per
> [ADR-0064](../../ADRs/0064-deprecate-customized-directory-overlay.md).
> Orgs that have migrated to config-driven agents should skip these
> `cp -r customized/` steps and use the registered harness paths directly.

```bash
git clone --depth 1 https://github.com/{org}/.fullsend.git /tmp/org-fullsend/
cp -r /tmp/org-fullsend/customized/. /tmp/agents/
Expand Down
6 changes: 6 additions & 0 deletions docs/plans/agent-registration.md
Original file line number Diff line number Diff line change
Expand Up @@ -440,3 +440,9 @@ PRs 2 and 3 can be developed in parallel after PR 1 merges. PR 4
is the cleanup that depends on everything else. Phase 5 is a
follow-up tracked by a GitHub issue, filed once all first-party
agents have been extracted from the scaffold.

**Related:** `fullsend agent migrate-customizations` (implemented in
ADR-0064 / PR #2954) migrates existing `customized/` overrides into
config-driven agents. It uses `DiffHarness` to compute minimal `base:`
composition harnesses and registers agents via the same config schema
defined in Phase 1.
2 changes: 2 additions & 0 deletions docs/plans/deprecate-customized-directory-overlay.md
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,8 @@ directories. The scaffold embed no longer contains them.
- Remove all references to `customized/` directories.
- Add examples of thin harness wrappers with `base:` URLs.
- Add migration guidance for users who had files in `customized/`.
- Reference the `fullsend agent migrate-customizations` CLI command
that automates the conversion and delivers changes via PR.

**`docs/agents/triage.md`, `docs/agents/review.md`:**

Expand Down
3 changes: 3 additions & 0 deletions docs/runtimes.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,9 @@ slots:
│ fullsend wins, repo version shadowed) │
│ Repo skills extend the agent; customized/skills/ │
│ overrides at the config layer before upload │
│ ⚠ customized/ is deprecated per ADR-0064; use │
│ config-driven agents instead (see `fullsend agent │
│ migrate-customizations`) │
└────────────────────────────────────────────────────────┘
```

Expand Down
1 change: 1 addition & 0 deletions internal/cli/agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ func newAgentCmd() *cobra.Command {
cmd.AddCommand(newAgentListCmd())
cmd.AddCommand(newAgentUpdateCmd())
cmd.AddCommand(newAgentRemoveCmd())
cmd.AddCommand(newAgentMigrateCustomizationsCmd())
return cmd
}

Expand Down
3 changes: 2 additions & 1 deletion internal/cli/agent_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1182,7 +1182,7 @@ allowed_remote_resources:

func TestNewAgentCmd_HasSubcommands(t *testing.T) {
cmd := newAgentCmd()
assert.Len(t, cmd.Commands(), 4)
assert.Len(t, cmd.Commands(), 5)
names := make([]string, len(cmd.Commands()))
for i, c := range cmd.Commands() {
names[i] = c.Name()
Expand All @@ -1191,4 +1191,5 @@ func TestNewAgentCmd_HasSubcommands(t *testing.T) {
assert.Contains(t, names, "list")
assert.Contains(t, names, "update")
assert.Contains(t, names, "remove")
assert.Contains(t, names, "migrate-customizations")
}
Loading
Loading