diff --git a/.outfitter/skills/outfitter/SKILL.md b/.outfitter/skills/outfitter/SKILL.md index 505caafd..b5b3fa41 100644 --- a/.outfitter/skills/outfitter/SKILL.md +++ b/.outfitter/skills/outfitter/SKILL.md @@ -1,6 +1,6 @@ --- name: outfitter -description: Explain Outfitter and help users compose, inspect, and maintain .agents resources, agents and their loadouts, personas, skills, and settings. Use when a user asks about Outfitter itself — the .agents protocol, agent profiles and personas, catalogs, skills, state persistence, launch configuration — or asks to set up, change, debug, or migrate an Outfitter-managed launch. +description: Outfitter's always-on advisor. Explain Outfitter and compose/inspect/maintain .agents resources, agents and their loadouts, personas, skills, and settings — and, proactively, recognize which agentic-design patterns fit the user's project and apply them with Outfitter's primitives, so the user need not be an expert in agentic design. Use when a user asks about Outfitter itself (the .agents protocol, profiles, personas, catalogs, skills, settings, launches) or asks to set up/change/debug/migrate a launch; also engage proactively while composing agents, CI, or deployments, and when asked to audit a project for agentic-pattern opportunities. # TODO: once directory reference materialization lands, collapse the list # below to a single `- file: docs/documentation` entry so the whole @@ -30,14 +30,27 @@ references: - file: docs/documentation/migration.md - file: docs/documentation/first-time-cli-agent-users.md - file: docs/documentation/iterating-on-profiles.md + - file: docs/documentation/conventions.md + - file: docs/documentation/recurring-runs.md + - file: docs/documentation/in-cluster.md + - file: docs/documentation/channels.md + - file: docs/documentation/usecases/organization-profile-catalog.md --- # Outfitter -Use this skill to answer questions about Outfitter and to guide changes to -`.agents` resources, agents and their loadouts, and launches. Classify the -request, read only the relevant reference, and follow its cross-references -before answering or editing configuration. +Use this skill to answer questions about Outfitter, to make changes to `.agents` +resources and launches, and — proactively — to recognize when an agentic-design +**pattern** fits the user's project and offer to apply it. The user should not have +to be an expert in agentic design: that expertise lives in these references, and +your job is to bring the right pattern to their situation. Classify the request, +read only the relevant reference, and follow its cross-references before answering +or editing configuration. + +Be proactive but not noisy: when a project signal in **Agentic patterns** appears +while you work — or when the user asks for help without a specific request, or asks +you to **audit** their project — surface the fitting pattern and offer to apply it. +Suggest the one or two highest-value patterns, not every possibility. ## Routing @@ -69,6 +82,16 @@ before answering or editing configuration. - Structuring agent identity versus skills, keeping instructions in one place: read `references/best-practices.md`. - Running tasks headlessly in GitHub Actions: read `references/actions.md`. +- Recurring or scheduled work, and the local-loop → Actions-cron → cluster + graduation ladder: read `references/recurring-runs.md`. +- Running agents in Kubernetes — resident, CronJob, or subagent Jobs via the + operator: read `references/in-cluster.md`. +- Channel intake (email, Signal, GitHub notifications) that wakes an agent on new + work: read `references/channels.md`. +- Ambient, always-true rules and "place once, specialize downward": read + `references/conventions.md`. +- An organization adopting Outfitter — a control catalog and shared defaults: read + `references/usecases/organization-profile-catalog.md`. - Getting hooks working per harness: read `references/hooks.md`. - Migrating from another agent CLI setup: read `references/switching-to-outfitter.md`. @@ -87,6 +110,52 @@ before answering or editing configuration. `references/README.md` is the documentation index if no entry above fits. +## Agentic patterns + +Watch for these project signals. When one appears, name the fitting pattern, read +its reference, then propose the concrete change and offer to apply it (see +*Applying changes*). Bring the pattern to the user — don't require them to know it. + +- **Repo receives issues or PRs** → a headless CI agent that triages, labels, and + comments (`actions-agent` + an `issue-triage`-style skill). Reference: + `references/actions.md`. Apply: scaffold the workflow and the agent. +- **"Every N", "nightly", "watch", a recurring chore** → the graduation ladder: + local loop → Actions cron → in-cluster CronJob/resident. Reference: + `references/recurring-runs.md`. Apply: pick the surface matching how often and + where it must run; the composition stays the same, only the trigger changes. +- **Inbound messages — email, Signal, GitHub notifications** → channel intake: the + `channels` extension wakes the agent, paired with a channel skill. Reference: + `references/channels.md`. +- **Always-on or cluster-local access** → an in-cluster resident agent with Secrets + and quota. Reference: `references/in-cluster.md`. Apply: compose an + `Organization` + `Agent`. +- **One agent per task, or a profile carrying every capability** → few agents, many + skills; make broad skills routers. References: `references/best-practices.md`, + `references/skills.md`. Apply: split capabilities into skills selected by loadout. +- **Cross-context, parallelizable, or review work** → subagent delegation (a leader + with bounded delegates). Reference: `references/subagents.md`. +- **A rule that should always hold — commit style, secret hygiene** → author it once + in the tree's shared `agents.md` and inherit down; never paste it per-agent or + make it a skill. Reference: `references/conventions.md`. +- **An organization adopting Outfitter** → an `owner/.outfitter` control catalog + with shared conventions and pinned revisions. References: + `references/usecases/organization-profile-catalog.md`, `references/catalogs.md`. + +## Audit a project + +When the user asks you to audit their project — or asks for help without a specific +request — do a quick pass and surface the highest-value opportunities: + +1. **Survey signals:** repo type and languages; existing `.agents` (agents, skills, + settings); CI workflows (`.github/workflows`); Kubernetes manifests; credentials + or channel configuration; and the user's stated goal. +2. **Match** them against *Agentic patterns* above. +3. **Present a prioritized shortlist** — the two or three highest-value patterns, + not every match — each as: the opportunity, the pattern, and the concrete change + you would make. +4. **Offer to apply** the top one, and apply it per *Applying changes* on + confirmation. + ## Working on Outfitter configuration 1. Inspect the current configuration before editing: @@ -103,8 +172,19 @@ before answering or editing configuration. 3. Keep each instruction in one place: durable identity belongs in the agent definition, per-capability procedure belongs in a skill (`references/best-practices.md`). -4. Validate changes with `outfitter validate --strict` and, when possible, a - smoke test such as `outfitter run -- --help`. +4. Apply patterns end to end — don't stop at describing them: + - **Compose:** write/edit the `.agents` resources directly (agents, skills, + loadouts, shared `agents.md`) — what `outfitter` governs. + - **CI:** scaffold the workflow and open it with `gh` (`references/actions.md`). + - **In-cluster:** apply the `Organization`/`Agent` custom resources with + `kubectl` (`references/in-cluster.md`). + - **Catalog:** pin a revision or open a catalog PR (`references/catalogs.md`). +5. Validate before applying: `outfitter validate --strict`, and when possible a + dry `outfitter dump --out ` or `outfitter run -- --help` smoke + test. +6. **Confirm before any outward or irreversible action** — opening a PR, pushing, + applying cluster resources, or anything that leaves the local workspace. State + exactly what you will run, then act only on approval. ## Default behavior @@ -112,5 +192,6 @@ If the user asks for help with Outfitter without a specific request: 1. Run `outfitter list agents` to show resolvable agents and resources. 2. Summarize the agents by name, scope or source, and default status. -3. Ask whether the user wants to compose or change an agent, and read - `references/profiles.md` and `references/agents.md` before editing. +3. Offer to **audit the project** for agentic-pattern opportunities (see *Audit a + project*), or to compose or change an agent — reading `references/profiles.md` + and `references/agents.md` before editing. diff --git a/README.md b/README.md index f1c5fee1..1bd239f5 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,34 @@ # Outfitter -Outfitter is the toolchain for the [Dotagents `.agents` protocol](https://dotagentsprotocol.com/): it resolves agent configuration from local and remote `.agents` trees, composes personas, skills, and tasks by slug, bakes tasks into deterministic execution artifacts, and launches the result through wrapped agent CLIs like [`pi`](https://github.com/earendil-works/pi-coding-agent) and Claude Code. +Outfitter is the toolchain for the [Dotagents `.agents` protocol](./docs/documentation/concepts.md): it resolves agent configuration from local and remote `.agents` trees, composes agents, skills, and knowledge by slug, and launches the result through wrapped agent CLIs like [`pi`](https://github.com/earendil-works/pi-coding-agent) and Claude Code. Outfitter does not own a configuration format. Your `.agents/` directory is the source of truth — useful without Outfitter, committed and reviewed like any other code. -> **Status:** these docs describe the target architecture of [RFC #165](https://github.com/ai-outfitter/outfitter/issues/165) (protocol revision `502a9d5`). Implementation is landing as a chain of PRs; the released CLI still runs the legacy profile system until then. +> These docs are the authoritative description of the `.agents` model Outfitter implements — start with [Concepts](./docs/documentation/concepts.md). For interchange, Outfitter pins draft protocol revision `502a9d5` of the referenced [external protocol site](https://dotagentsprotocol.com/). Implementation is rolling out across releases — a published CLI may lag these docs; [Migration](./docs/documentation/migration.md) covers the legacy profile format. For the design history, see [RFC #165](https://github.com/ai-outfitter/outfitter/issues/165). + +## Why + +Your agent setup is configuration: prompts, skills, MCP servers, model choices, permissions. Left alone it lives per tool and per laptop, gets pasted between repos, and drifts. Outfitter treats it like the rest of your infrastructure — layered, composed by slug, pinned by SHA, reviewed through pull requests. + +That turns one person's improvement into everyone's default. On Monday a platform engineer writes a `grafana-alert-investigate` skill in their own `~/.agents` tree and uses it at their desk. By Friday it is merged into the org catalog, pinned by version, and selected by slug from an agent that also runs on a CI schedule and in the cluster. Nobody else configured anything — their next run composes the new skill, and it costs their context window one line of routing metadata until it activates. + +Two ideas carry most of that leverage: + +- **The ladder.** Resources start personal and graduate upward — and every layer below inherits them back: + + ```mermaid + flowchart LR + personal["~/.agents
(you)"] -->|port up| project["project/.agents
(your repo)"] + project -->|port up| org["org catalog
(pinned by SHA)"] + org -->|contribute| community["community catalogs"] + community -. "inherited back, specialized downward" .-> personal + ``` + + ID-addressed resources — agents, skills, knowledge — override by ID across layers, and root shared context is selected by layer precedence, so you author a rule or skill once at the most general layer where it holds and specialize downward — never copy. See [Conventions](./docs/documentation/conventions.md). + +- **The surfaces.** The same composition runs everywhere work happens: interactively at your desk, [in GitHub Actions](./docs/documentation/actions.md) on any trigger, as [recurring loops](./docs/documentation/recurring-runs.md) — locally, on a CI cron, or on a cluster schedule — and as resident or job-based agents [in Kubernetes](./docs/documentation/in-cluster.md). Surface availability varies by release; each page notes its status. + +For the full argument, read the [Philosophy](./docs/philosophy.md). ## Quick start @@ -64,30 +88,27 @@ Managed porting and persistent harness symlinks are deferred to commands/ # slash commands ``` -Layers merge by ID: `/.agents/` over `~/.agents/` over pinned remote [catalogs](./docs/documentation/catalogs.md). An [agent](./docs/documentation/agents.md) carries both its identity and its loadout — an [agent profile](./docs/documentation/profiles.md) — and is what you run; a [persona](./docs/documentation/personas.md) is a review convention layered on a base agent; a [subagent](./docs/documentation/subagents.md) is an agent a run delegates to, including through [GitHub Actions](./docs/documentation/actions.md). - -Agents can also run headlessly in GitHub Actions via [`ai-outfitter/actions`](https://github.com/ai-outfitter/actions). +Layers merge by ID: `/.agents/` over `~/.agents/` over pinned remote [catalogs](./docs/documentation/catalogs.md). An [agent](./docs/documentation/agents.md) carries both its identity and its loadout — an [agent profile](./docs/documentation/profiles.md) — and is what you run; a [persona](./docs/documentation/personas.md) is a review convention layered on a base agent; a [subagent](./docs/documentation/subagents.md) is an agent a run delegates to, across [four delegation boundaries](./docs/documentation/subagents.md#the-four-delegation-boundaries) from an in-session helper to a Kubernetes Job. ## Documentation -- [Getting started](./docs/documentation/getting-started.md) -- [Concepts](./docs/documentation/concepts.md) -- [Settings](./docs/documentation/settings.md) -- [Agents](./docs/documentation/agents.md) · [Agent profiles](./docs/documentation/profiles.md) · [Personas](./docs/documentation/personas.md) · [Subagents](./docs/documentation/subagents.md) -- [Skills](./docs/documentation/skills.md) · [Tasks (future RFC)](./docs/documentation/tasks.md) -- [Catalogs](./docs/documentation/catalogs.md) · [Dump](./docs/documentation/dump-and-bake.md) -- [Running an agent in GitHub Actions](./docs/documentation/actions.md) -- [Hooks](./docs/documentation/hooks.md) · [State persistence](./docs/documentation/state.md) -- [Adapter support matrix](./docs/documentation/support-matrix.md) -- [Local dotagents development](./docs/documentation/local-development.md) -- [Switching to Outfitter](./docs/documentation/switching-to-outfitter.md) · [Migration from legacy profiles](./docs/documentation/migration.md) -- [Documentation index](./docs/documentation/README.md) - -Use cases: - -- [Organization catalog](./docs/documentation/usecases/organization-profile-catalog.md) — Publish shared org resources and defaults through an `owner/.outfitter` control repository. -- [Engineering catalog](./docs/documentation/usecases/engineering.md) — Package engineering personas, skills, and tasks for repeatable workflows. -- [Persona reviews](./docs/documentation/usecases/persona-reviews.md) — Compose customer personas to get feedback on ideas, documentation, and designs. +The [documentation index](./docs/documentation/README.md) is organized as a journey — start personal, understand the model, grow across your org, automate more surfaces, contribute back: + +- **Start:** [Getting started](./docs/documentation/getting-started.md) · [First-time CLI agent users](./docs/documentation/first-time-cli-agent-users.md) · [Switching to Outfitter](./docs/documentation/switching-to-outfitter.md) +- **Understand:** [Concepts](./docs/documentation/concepts.md) · [Agents](./docs/documentation/agents.md) · [Skills](./docs/documentation/skills.md) · [Personas](./docs/documentation/personas.md) · [Subagents and delegation](./docs/documentation/subagents.md) +- **Grow:** [Catalogs](./docs/documentation/catalogs.md) · [Conventions](./docs/documentation/conventions.md) · [Organization catalog](./docs/documentation/usecases/organization-profile-catalog.md) · [Best practices](./docs/documentation/best-practices.md) +- **Automate:** [GitHub Actions](./docs/documentation/actions.md) · [Recurring runs](./docs/documentation/recurring-runs.md) · [In-cluster agents](./docs/documentation/in-cluster.md) · [Hooks](./docs/documentation/hooks.md) · [State persistence](./docs/documentation/state.md) +- **Reference:** [CLI](./docs/documentation/cli.md) · [Settings](./docs/documentation/settings.md) · [Adapter support matrix](./docs/documentation/support-matrix.md) · [Philosophy](./docs/philosophy.md) + +Use cases, story first: + +- [Shared conventions without duplication](./docs/documentation/usecases/shared-conventions.md) — one conventional-commits rule for every user, org, and project; zero copies. +- [Flaky-test post-mortems in CI](./docs/documentation/usecases/flaky-test-postmortems.md) — an on-failure step that classifies flake vs. regression and comments with evidence. +- [Grafana alert investigations in-cluster](./docs/documentation/usecases/grafana-alert-investigator.md) — a webhook turns each firing alert into one bounded investigation Job. +- [Self-improving skills](./docs/documentation/usecases/self-improving-skills.md) — a weekly loop that proposes skill edits and ships only measured improvements. +- [Persona reviews](./docs/documentation/usecases/persona-reviews.md) — customer personas your whole team can ask for feedback. +- [Organization catalog](./docs/documentation/usecases/organization-profile-catalog.md) — shared org resources and defaults through a control repository. +- [Engineering catalog](./docs/documentation/usecases/engineering.md) — engineering agents and skills for repeatable workflows. For local development, repository structure, and release workflow details, see [Contributing](./CONTRIBUTING.md). diff --git a/docs/architecture/diagrams.md b/docs/architecture/diagrams.md index 095853cd..7b7619b9 100644 --- a/docs/architecture/diagrams.md +++ b/docs/architecture/diagrams.md @@ -8,32 +8,32 @@ Resources come from layered `.agents` trees: the project workspace overlay, the ```mermaid flowchart LR - subgraph layers [.agents layers - precedence high to low] - PJ[Workspace
project/.agents/] - US[Global
~/.agents/] - CA[Cached catalogs
pinned remote sources] + subgraph layers [".agents layers — precedence high to low"] + workspace["Workspace
project/.agents/"] + global["Global
~/.agents/"] + catalogs["Cached catalogs
pinned remote sources"] end - subgraph resources [Protocol resources] - AG[Agents + loadouts] - SK[Skills] - KN[Knowledge / commands] - JS[mcp.json / models.json] + subgraph resources ["Protocol resources"] + agents["Agents + loadouts"] + skills["Skills"] + knowledge["Knowledge / commands"] + config["mcp.json / models.json"] end - layers --> RESOLVE[Resolver
merge by ID] - resources -.stored in.- layers + layers --> resolver["Resolver
merge by ID"] + resources -. stored in .- layers - RESOLVE --> SELECT[Composed agent
identity + skills, subagents, mcp, model] + resolver --> composed["Composed agent
identity + skills, subagents, mcp, model"] - SELECT --> AD{Adapter} - AD -->|full projection| PI[Pi CLI
primary adapter] - AD -->|partial, warns on gaps| CC[Claude Code CLI] + composed --> adapter{Adapter} + adapter -->|full projection| pi["Pi CLI
primary adapter"] + adapter -->|partial, warns on gaps| claude["Claude Code CLI"] - SELECT --> DUMP[outfitter dump
deterministic .agents/ output] + composed --> dump["outfitter dump
deterministic .agents/ output"] - PI --> RUN([Launched agent process]) - CC --> RUN + pi --> run(["Launched agent process"]) + claude --> run ``` ## Sequence: `outfitter run ` @@ -42,6 +42,7 @@ flowchart LR ```mermaid sequenceDiagram + autonumber actor User participant CLI as outfitter run participant Resolver as Resolver @@ -77,23 +78,23 @@ sequenceDiagram ```mermaid flowchart TB - subgraph declare [Source declarations in settings.yml] - GH[github: owner/.agent
+ pinned ref, optional path] - URI[uri: git+https://...] - PATH[path: ../local-checkout] + subgraph declare ["Source declarations in settings.yml"] + githubsrc["github: owner/.agent
+ pinned ref, optional path"] + urisrc["uri: git+https://..."] + pathsrc["path: ../local-checkout"] end - SETUP[outfitter setup source] --> DETECT{Existing config?} - DETECT -->|.agents tree| ADOPT[Adopt as-is] - DETECT -->|~/.claude| PORT[Port + symlink back] - DETECT -->|none| ONBOARD[Bootstrap from default catalog] - - GH --> SYNCOP[outfitter sync] - URI --> SYNCOP - SYNCOP --> CACHE[(Local cache)] - SYNCOP --> STATUS[Per-source status:
updated / unchanged / skipped / failed] - CACHE --> VALIDATE[Validate payloads] - PATH -->|read live, no cache| LAYERS - VALIDATE --> LAYERS[.agents layer stack] - LAYERS --> RUN[outfitter run / list / validate / dump] + setup["outfitter setup source"] --> detect{"Existing config?"} + detect -->|.agents tree| adopt["Adopt as-is"] + detect -->|~/.claude| port["Port + symlink back"] + detect -->|none| onboard["Bootstrap from default catalog"] + + githubsrc --> sync["outfitter sync"] + urisrc --> sync + sync --> cache[("Local cache")] + sync --> status["Per-source status:
updated / unchanged / skipped / failed"] + cache --> validate["Validate payloads"] + pathsrc -->|read live, no cache| stack + validate --> stack[".agents layer stack"] + stack --> consumers["outfitter run / list / validate / dump"] ``` diff --git a/docs/documentation/README.md b/docs/documentation/README.md index b31c82f1..43ae1edc 100644 --- a/docs/documentation/README.md +++ b/docs/documentation/README.md @@ -1,45 +1,60 @@ # Outfitter documentation -User-facing Outfitter documentation. These docs describe the [RFC #165](https://github.com/ai-outfitter/outfitter/issues/165) dotagents end state. +User-facing Outfitter documentation, organized as a journey: **start** personal, **understand** the model, **grow** it across projects and your org, **automate** it on more surfaces, then contribute back. The docs practice the same progressive disclosure that [skills](./skills.md) do — each page keeps to one concept and links onward when you need the next one, so nothing here has to be read up front. -## Getting started +## Start (you) -- [Getting started](./getting-started.md) -- [Concepts](./concepts.md) -- [CLI reference](./cli.md) -- [First-time CLI agent users](./first-time-cli-agent-users.md) +- [Getting started](./getting-started.md) — install, first run, default agent. +- [First-time CLI agent users](./first-time-cli-agent-users.md) — new to agent CLIs entirely. +- [Switching to Outfitter](./switching-to-outfitter.md) — adopt from an existing agent-CLI setup. +- [Porting a Claude Code setup](./porting-claude.md) — `~/.claude` into `~/.agents/` with symlinks back. + +## Understand (the model) + +- [Concepts](./concepts.md) — resolve → compose → adapt; layers and precedence. +- [Agents](./agents.md) — the `agents//agent.md` resource and its loadout — what you run. +- [Agent profiles](./profiles.md) — why an agent and its loadout _is_ the profile. +- [Skills](./skills.md) — capability packages with progressive disclosure, references, and routing. +- [Personas](./personas.md) — the base-agent-plus-persona-documents review convention. +- [Subagents and delegation](./subagents.md) — the four delegation boundaries, from in-session helpers to Kubernetes Jobs. +- [Settings](./settings.md) — scopes, schema, and the flat `settings.local.yml` override file. +- [Tasks](./tasks.md) — placeholder for a separate upcoming RFC. + +## Grow (project → org → community) -## Core concepts +- [Catalogs](./catalogs.md) — publish and consume shareable `.agents` payloads; standalone and colocated layouts. +- [Conventions](./conventions.md) — place a resource once, specialize downward, never copy. +- [Local dotagents development](./local-development.md) — a personal standalone `.agents` repo that trickles upstream. +- [Iterating on an agent](./iterating-on-profiles.md) — the edit-run-inspect loop. +- [Best practices](./best-practices.md) — few agents, many skills. -- [Settings](./settings.md) — Scopes, schema, and the flat `settings.local.yml` override file. -- [Agents](./agents.md) — The `agents//agent.md` resource and its loadout — what you run. -- [Agent profiles](./profiles.md) — Why an agent and its loadout _is_ the profile. -- [Personas](./personas.md) — The base-agent-plus-persona-documents review convention. -- [Subagents](./subagents.md) — Agents projected as harness delegates; leader-agent delegation. -- [Skills](./skills.md) — Capability packages with progressive disclosure, references, and routing. -- [Tasks](./tasks.md) — Placeholder for a separate upcoming RFC. +## Automate (surfaces) -## Operations +The same composition runs on every surface; only the trigger changes. -- [Catalogs](./catalogs.md) — Publish and consume shareable `.agents` payloads; standalone and colocated layouts. -- [Dump](./dump-and-bake.md) — Deterministic, self-contained `.agents/` dumps. -- [Running an agent in GitHub Actions](./actions.md) -- [Hooks](./hooks.md) — Harness hook wiring and the protocol gap. +- [Running an agent in GitHub Actions](./actions.md) — headless runs on any workflow trigger. +- [Recurring runs](./recurring-runs.md) — loops three ways: the local loop extension, Actions cron, cluster schedules. +- [In-cluster agents](./in-cluster.md) — resident agents, CronJobs, and subagent Jobs via Link Operator. +- [Channels](./channels.md) — watch a mailbox, Signal, or GitHub notifications; wake an agent on real work via the `channels` extension plus per-channel skills. +- [Hooks](./hooks.md) — harness hook wiring and the protocol gap. +- [Dump](./dump-and-bake.md) — deterministic, self-contained `.agents/` dumps. - [State persistence](./state.md) - [Adapter support matrix](./support-matrix.md) -## Adopting Outfitter +## Use cases (stories) -- [Switching to Outfitter](./switching-to-outfitter.md) -- [Porting a Claude Code setup](./porting-claude.md) — Port `~/.claude` into `~/.agents/` with a symlink back. -- [Local dotagents development](./local-development.md) — A personal standalone `.agents` repo that trickles upstream. -- [Migration from legacy profiles](./migration.md) -- [Iterating on an agent](./iterating-on-profiles.md) -- [Best practices](./best-practices.md) -- [Philosophy](../philosophy.md) +Each use case is a worked story — a problem, the composition that answers it, and the payoff — with links back to the concepts it uses. + +- [Shared conventions without duplication](./usecases/shared-conventions.md) — one conventional-commits rule for every user, org, and project; zero copies. +- [Flaky-test post-mortems in CI](./usecases/flaky-test-postmortems.md) — an on-failure step that classifies flake vs. regression and comments with evidence. +- [Grafana alert investigations in-cluster](./usecases/grafana-alert-investigator.md) — a webhook turns each firing alert into one bounded investigation Job. +- [Self-improving skills](./usecases/self-improving-skills.md) — a weekly loop that proposes skill edits and ships only measured improvements. +- [Persona reviews](./usecases/persona-reviews.md) — a base review agent plus customer-persona documents for feedback on ideas, docs, and designs. +- [Organization catalog](./usecases/organization-profile-catalog.md) — publish shared org resources and defaults through an `owner/.outfitter` control repository. +- [Engineering catalog](./usecases/engineering.md) — package engineering agents and skills for repeatable workflows. -## Use cases +## Reference -- [Organization catalog](./usecases/organization-profile-catalog.md) — Publish shared org resources and defaults through an `owner/.outfitter` control repository. -- [Engineering catalog](./usecases/engineering.md) — Package engineering agents and skills for repeatable workflows. -- [Persona reviews](./usecases/persona-reviews.md) — A base review agent plus customer-persona documents for feedback on ideas, docs, and designs. +- [CLI reference](./cli.md) +- [Migration from legacy profiles](./migration.md) +- [Philosophy](../philosophy.md) — why Outfitter exists. diff --git a/docs/documentation/channels.md b/docs/documentation/channels.md new file mode 100644 index 00000000..2442c3e7 --- /dev/null +++ b/docs/documentation/channels.md @@ -0,0 +1,93 @@ +# Channels + +A **channel** is an external source of work an agent watches — a mailbox, Signal, +GitHub notifications. The [`ai-outfitter/channels`](https://github.com/ai-outfitter/channels) +Pi extension turns each channel's native push into an **idle-gated wake**, so an +agent runs a turn only when a channel has real work instead of polling on a timer. +Multiple channels run at once and feed one notification queue. + +Channels split cleanly across two resources you compose in a loadout: + +- the **extension** (`channels`) — *when* to wake the agent (the push transport); +- a **skill** per channel — *how* the agent reads and replies (`mail`, + `signal-responder`, `slack-responder`, … from the community catalog). + +The wake is a trusted, body-free ping; the skill fetches the untrusted message +content, so channel data never enters the session as instructions (the same trust +rule as [skill references](./skills.md)). + +## Add channels to an agent + +Select the extension and the channel's skill in the agent's [loadout](./agents.md): + +```markdown +--- +name: email-assistant +skills: [mail] +extensions: [git:github.com/ai-outfitter/channels] +model: your-model +--- +``` + +Because an [agent *is* the profile](./profiles.md) and loadout slugs **merge by ID +across layers**, selecting several channels reuses the **one** `channels` +extension — it is deduplicated to a single load. A multi-channel agent is just +more skills plus the same extension: + +```markdown +--- +name: personal-assistant +skills: [mail, slack-responder, signal-responder] +extensions: [git:github.com/ai-outfitter/channels] +--- +``` + +All configured channels feed a single notification queue; each wake names the +channels with activity and the agent drains them with the matching skill. The +[`community-profiles`](https://github.com/ai-outfitter/community-profiles) catalog +publishes ready-made `email-assistant` / `slack-assistant` / `signal-assistant` +profiles and a composed `personal-assistant`. + +## Select which channels run + +`OUTFITTER_CHANNELS` chooses the active channels; unset means **auto-detect** — +every channel whose credentials are present starts. So composing a channel into an +agent is really just supplying its credentials. + +| `OUTFITTER_CHANNELS` | Behavior | +| --- | --- | +| unset | Auto-detect by credentials | +| `jmap,signal` | Exactly those channels | +| `off` / `none` | Disabled | + +## Credentials per channel + +Each channel reads the same environment variables as its skill. Supply them the +Outfitter way for where the agent runs: + +- **Local runs** — export them in the shell before `outfitter run` (see the + [channels README](https://github.com/ai-outfitter/channels) for the bare-pi + flow). +- **In-cluster** — project them as env from Secrets via the Kubernetes operator; + the operator exposes referenced Secrets without inspecting them, and the keys + inside are each channel's contract. + +| Channel | Skill | Variables | +| --- | --- | --- | +| `jmap` (email over JMAP) | `mail` | `XIN_BASE_URL`, `XIN_BASIC_USER`, `XIN_BASIC_PASS` | +| `signal` | `signal-responder` | `SIGNAL_NUMBER`, `SIGNAL_CLI_CONFIG` | +| `github` | `gh` / a GitHub skill | `GITHUB_TOKEN`, optional `GITHUB_NOTIFY_FILTERS` (default `review_requested,assigned_issue`), `GITHUB_NOTIFY_POLL_MS` | + +## Running resident + +A channel watcher opens push connections for the life of a session, so it needs a +long-running agent — an interactive session, `--mode rpc`, or an always-on +in-cluster deployment. Session switches reopen the connections; one-shot print runs +are not suitable. + +## See also + +- [`ai-outfitter/channels`](https://github.com/ai-outfitter/channels) — the + extension, its sources, per-channel setup, and design. +- [Skills](./skills.md) — the channel skills the agent pairs with. +- [Agents](./agents.md) / [Profiles](./profiles.md) — loadout and composition. diff --git a/docs/documentation/concepts.md b/docs/documentation/concepts.md index 55bf5b09..aa0cbf4a 100644 --- a/docs/documentation/concepts.md +++ b/docs/documentation/concepts.md @@ -4,12 +4,12 @@ How an `outfitter` launch goes from configuration files to a running agent: ```mermaid flowchart LR - A[Settings] --> B[Sources] - B --> C[.agents layers] - C --> D[Resolver] - D --> E[Composed agent] - E --> F[Adapter] - F --> G[Harness] + settings[Settings] --> sources[Sources] + sources --> layers[".agents layers"] + layers --> resolver[Resolver] + resolver --> composed["Composed agent"] + composed --> adapter[Adapter] + adapter --> harness[Harness] ``` Settings tell Outfitter where `.agents` resources come from; sources supply protocol resource trees; the resolver merges the layered trees into one effective resource set; the selected agent composes its loadout — skills, subagents, model, and so on — from that set by slug; and an adapter projects the composed agent into harness-specific files, flags, and environment variables before launching the harness (pi or Claude Code). diff --git a/docs/documentation/conventions.md b/docs/documentation/conventions.md new file mode 100644 index 00000000..daebbcc3 --- /dev/null +++ b/docs/documentation/conventions.md @@ -0,0 +1,55 @@ +# Conventions + +A resource that "belongs everywhere" is a _placement_ problem, not a duplication problem. This page names the convention that keeps a growing `.agents` ecosystem from collapsing into copies: **place a resource once, specialize downward, never copy.** + +The mechanisms already exist — layer inheritance, merge-by-ID overrides, [loadout-added references](./skills.md#loadout-added-references), and progressive disclosure. The convention is agreeing to use them in order: + +1. **Author once at the most general layer where the resource is true**, then let lower layers inherit it. +2. **Specialize downward** via same-ID overrides and loadout-added references, instead of forking or copying. +3. **Split by whether the agent should _decide_.** Ambient rules an agent should never think about belong in always-on shared context; situational capabilities belong in [skills](./skills.md), where progressive disclosure keeps them to roughly one line of context until they activate. + +## Layer homes + +Each layer inherits the one above it. ID-addressed resources — agents, skills, knowledge — merge and override by ID; root shared context (`agents.md` / `system-prompt.md`) is selected whole-file by layer precedence (see the [roadmap note](#roadmap-a-shareable-prompt-fragment) below): + +| Layer | Location | Holds | +| ---------------- | ----------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- | +| Community | e.g. `ai-outfitter/community-profiles` | Reviewed building blocks — skills and reference agents anyone can mix and match. | +| Curated defaults | e.g. `ai-outfitter/default-profiles` | The pinned, curated assembly — starter agents users adopt as-is. | +| Organization | `owner/.outfitter` [control repo](./usecases/organization-profile-catalog.md) | Bespoke org agents, shared `agents.md`, org-specific skills (brand voice, RBAC, endpoints). | +| User / project | `~/.agents`, `/.agents` | Personal and repo overrides, loadout-added references, same-ID resource overrides. | + +Generalized: **community publishes the parts, curated catalogs pin an assembly, org and project bind values and override by ID.** + +## Where each kind of rule lives + +| Rule type | Home | Agent decides? | +| ------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- | ------------------ | +| Ambient, always-true (conventional commits, secret hygiene, small reversible changes) | Shared context: the tree's `agents.md` / `system-prompt.md`, inherited per layer | Never | +| Situational capability or procedure (release notes, incident response, SEO audit) | A [skill](./skills.md) selected by slug (progressive disclosure) | Yes, on activation | +| Mechanically checkable (commit format, lint, formatting) | A [hook](./hooks.md) or CI check, plus the one-line ambient rule | Never | + +The first row is the one teams get wrong most often: an ambient rule made into a skill forces every agent to _notice and choose_ it, and an ambient rule pasted into every `agent.md` becomes N drifting copies. Keep it in shared context, once, at the highest layer where it holds. When a selected skill already defines a capability, an agent definition MUST NOT copy or paraphrase it — the [skills doc](./skills.md#where-context-and-instructions-live) draws the same boundary. + +## Worked example: conventional commits + +Conventional commits "belongs in every profile" — the engineer, the marketing agent that occasionally commits copy, the CI bot — yet must never be pasted into every profile. It is the canonical ambient rule: + +- **Author once** — one line in the shared `agents.md` of the highest layer where it holds (the org tree, or your `~/.agents/system-prompt.md` for everything on one machine). +- **Inherit downward** — every agent composed from that tree carries the rule with zero per-agent cost and no activation decision. +- **Override downward** — a project with a different commit convention ships its own shared context in `/.agents/`; workspace precedence wins. Today the root file wins _whole_, not line by line — fragment-level override is the [roadmap primitive](#roadmap-a-shareable-prompt-fragment) — so keep shared context lean enough that a deliberate replacement stays cheap and reviewable. +- **Enforce deterministically** — a `commit-msg` hook or release tooling is the backstop; the ambient line keeps the model writing them right the first time. + +The full story, including projection into native harness files, is the [Shared conventions use case](./usecases/shared-conventions.md). + +## Worked example: a role profile + +The same convention builds a role-scoped profile — a `platform` or `marketing` agent ([#197](https://github.com/ai-outfitter/outfitter/issues/197)): + +- **Inherit the shared baseline** (the tree's `agents.md`), then add role skills on top — `brand-voice`, `content-drafting`, `seo-audit` for marketing; provisioning and observability skills for platform. _Few agents, many skills_ ([Best practices](./best-practices.md)). +- **Bespoke per org two ways:** as a [subagent](./subagents.md) other agents delegate role work to, or via one org-specific skill (a `brand` or `platform` skill) carrying the values — endpoints, voice, RBAC — that make the shared profile bespoke without duplicating it. +- **Role separation is the point.** An engineer or a marketer doesn't want the other's machinery in context; they work expeditiously in their own lane and delegate across lanes when needed. Cross-cutting work stays _available_ through inheritance and delegation, not by stuffing every profile. + +## Roadmap: a shareable prompt fragment + +Today the always-on vehicle is a tree's root `agents.md` / `system-prompt.md` — one file per layer. It inherits and overrides _per layer_, but you cannot yet publish one named fragment from a community catalog and override just that fragment by ID. A first-class, slug-composable shared prompt fragment is the missing primitive; until it lands, a single line per layer's shared context still deduplicates by inheritance — just not as a publishable unit. [Hooks](./hooks.md) carry the analogous gap for portable hook definitions. diff --git a/docs/documentation/in-cluster.md b/docs/documentation/in-cluster.md new file mode 100644 index 00000000..8670bc62 --- /dev/null +++ b/docs/documentation/in-cluster.md @@ -0,0 +1,35 @@ +# In-cluster agents + +The Link Operator runs Outfitter-composed agents inside a Kubernetes cluster. The operator provides **primitives only** — namespace, quota, secrets exposure, pinned catalog resolution, and starting the runtime — while everything behavioral (which agent, which skills, which channels) stays ordinary `.agents` composition, reviewed and pinned like anywhere else. + +> **Status:** the Link Operator is under active development and not yet publicly released. This page is the design contract for the in-cluster surface; treat it as a preview until the operator ships. + +## The primitives + +- **`Organization`** — ownership plus one commit-pinned catalog source. The operator writes the pin into the runtime's `.agents/settings.yml`; agents resolve their composition from it exactly as a local run would. +- **`Agent`** — a namespace of its own (`agent-`), a service account bound only within that namespace, operator-owned quota and limits, a durable volume, and a long-running Deployment for the resident runtime. + +The operator never interprets a profile, reads a secret's contents, or invokes the model — it provisions and starts; the agent layer does the rest. + +## Execution shapes + +| Shape | Kubernetes resource | Trigger | +| ---------------------- | ------------------- | ----------------------------------------------------------------------------------------------- | +| Resident agent | Deployment | The [loop extension](./recurring-runs.md) tick (default 10m): survey channels, work or delegate | +| Scheduled recurrence | CronJob | The cluster's clock — recurring one-shots in the agent's namespace | +| Delegated / event work | Job (subagent) | Spawned by the resident agent, or one Job per incoming event (e.g. a firing alert via webhook) | + +Subagent Jobs share the owning agent's service account and quota, so delegation never escalates privilege — the cluster-backed entry in the [four delegation boundaries](./subagents.md#the-four-delegation-boundaries). + +## Channels + +A **channel** is an adapter to an external event or message source — email, GitHub notifications, Signal — that supplies the agent's work intake. Channels are agent-runtime concerns, composed as skills, MCP servers, or extensions in the catalog; they are never operator primitives. Two intake styles: + +- **Poll** — the resident loop's tick surveys the channel (an inbox, a notifications feed) for new items. +- **Push** — a webhook receiver materializes one bounded subagent Job per event. + +Treat channel content — email bodies, issue text, alert annotations — as untrusted data, never instructions, the same trust rule as [skill references](./skills.md#trust-boundary). + +## Worked story + +[Grafana alert investigations in-cluster](./usecases/grafana-alert-investigator.md): an Alertmanager webhook turns each firing alert into one investigation Job that reads dashboards and logs through the Grafana MCP plus a read-only Kubernetes view, classifies expected vs. anomaly, and posts exactly one diagnosis comment — never mutating a workload. diff --git a/docs/documentation/recurring-runs.md b/docs/documentation/recurring-runs.md new file mode 100644 index 00000000..e69e1b88 --- /dev/null +++ b/docs/documentation/recurring-runs.md @@ -0,0 +1,27 @@ +# Recurring runs + +Recurring agent work — "check this every N minutes", "review what landed overnight", "regenerate the weekly report" — runs three ways in the Outfitter ecosystem. All three run the **same composition** — the agent, its skills, its catalog pins — under the same contract: wake, survey your inputs, work, stop. What differs is the clock and the lifecycle: a loop extension re-invokes a live session on a tick (locally, and inside resident in-cluster agents), while the cron surfaces launch a fresh one-shot process per tick. + +| Mechanism | Clock | Shape | Use when | +| ------------------------------------------------- | ---------------- | ------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- | +| **Local loop extension** | Your own session | The agent ticks inside a session on your machine (`/loop 10m`), surveying its inputs each tick | Watching something during your workday; developing a recurring behavior before automating it | +| **[GitHub Actions](./actions.md) cron** | The CI scheduler | `on: schedule:` workflow runs a fresh headless one-shot per tick | Repo-scoped recurrences: nightly commit review, weekly KPI reports, scheduled audits | +| **[In-cluster](./in-cluster.md) (Link Operator)** | Kubernetes | A scheduled recurring CronJob, or a resident Deployment that bootstraps the same `/loop` extension in-cluster | Always-on agents with channels (email, GitHub, chat) and cluster-local access; recurrences that shouldn't depend on a repo's CI | + +The graduation path mirrors [the ladder](./conventions.md): prototype the behavior with the local loop extension, move it to an Actions cron when it should run without your laptop, move it in-cluster when it needs to be resident or cluster-local. The composition — agent, skills, catalog pins — stays the same; only the trigger changes. + +## Local: the loop extension + +The loop extension re-invokes the agent at an interval inside a session. It is not bundled with a default install — select a loop extension in the agent's loadout (`extensions:`) and pin it like any other extension. Each tick, a well-shaped looping agent surveys its available inputs, turns new items into tasks, and works or delegates them — rather than carrying a growing transcript of stale context. This is also how the in-cluster resident agent runs: the Link Operator runtime bootstraps its long-lived session with the same `/loop` command, defaulting to a 10-minute tick. + +## CI: scheduled one-shots + +An Actions cron externalizes the clock to GitHub's scheduler. Each tick is a fresh, stateless headless run — compose, work once, exit — which makes it deterministic and reviewable, with a session transcript uploadable as a workflow artifact. See [`ai-outfitter/actions`](https://github.com/ai-outfitter/actions) — its `examples/scheduled-commit-review.yml` reviews the last 24 hours of commits each weekday morning and files an issue on findings. + +## Cluster: CronJobs and residents + +Kubernetes supplies two shapes through the [Link Operator](./in-cluster.md): a **CronJob** for scheduled recurring one-shots in the agent's namespace, and a **resident Deployment** for an always-on agent whose `/loop` tick surveys its [channels](./in-cluster.md#channels) — email, GitHub notifications, chat — for new work. + +## Not a loop: event-driven runs + +A webhook- or event-triggered run — one investigation Job per firing alert, one post-mortem per failed workflow — is triggered by the world, not a clock. It complements loops rather than replacing them: use a loop when work accumulates and should be swept up on a tick; use an event trigger when each unit of work announces itself. See [Grafana alert investigations](./usecases/grafana-alert-investigator.md) and [Flaky-test post-mortems](./usecases/flaky-test-postmortems.md). diff --git a/docs/documentation/subagents.md b/docs/documentation/subagents.md index 85918016..ec01f33f 100644 --- a/docs/documentation/subagents.md +++ b/docs/documentation/subagents.md @@ -16,14 +16,25 @@ Each slug resolves to an `agents//` definition across layers like any other See the [adapter support matrix](./support-matrix.md) for current coverage. -## Leader agents and delegation targets +## The four delegation boundaries -The reason to give an agent subagents is to make it a **leader**: an agent that coordinates work and delegates the bounded pieces. A leader can delegate two ways, and the two compose: +Delegation is one concept — an agent hands a unit of work to another agent identity — with four boundaries it can cross. The composition being delegated to is ordinary `.agents` resources in every case; what changes is where the delegate runs and how it reports back. -- **To local coding-harness subagents** — agents projected into the running harness (Claude Code's agents directory, Pi's subagent extension). The leader hands off exploration, review, or parallelizable work to a fresh context on the same machine and gets the result back inline. -- **To issue- and action-backed subagents** — work dispatched asynchronously, backed by a GitHub issue and an [Outfitter action](./actions.md). The leader files the unit of work as an issue; an action runs the delegate agent headlessly and reports back on the issue or PR. This is how a leader parallelizes across machines and across time rather than within one session. +| Boundary | Mechanism | Reports back via | Use when | +| ------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------- | +| **In-run** | Harness-native subagents (Claude Code's agents directory, Pi's subagent extension), declared in the leader's `subagents` loadout | Inline, same session | Exploration, review, parallelizable work needing a fresh context now | +| **CI-backed** | A [GitHub Actions run](./actions.md): dispatch a workflow that does the work, or **assignment-as-trigger** — assign the issue/PR to a machine account whose events start the workflow (runs on hosted or self-hosted runners) | A comment or PR from the run; optionally a session-transcript artifact (adapter-dependent) | Work that should run asynchronously with its own token scope and an auditable trail | +| **Cluster-backed** | A Kubernetes subagent Job in the delegating agent's namespace, sharing its service account and quota ([in-cluster agents](./in-cluster.md)) | The tracking issue/PR, or the delegating agent's next tick | Cluster-local work; one bounded Job per delegated unit or per incoming event | +| **Peer agent** | Notify or assign a _persistent_ resident agent — its notifications channel is the intake | Wherever the peer works: the issue, the PR, the thread | Standing responsibilities owned by an always-on identity rather than one-off runs | -A leader's loadout is where both are declared: local delegates as `subagents`, remote work routed through the action it triggers. Keep each delegate bounded — one job, clear inputs, a defined deliverable back to the caller. +A leader's loadout declares in-run delegates as `subagents`; the other three boundaries are reached through the tools the leader already has (dispatching a workflow, assigning an issue, filing work where a peer listens). Keep each delegate bounded — one job, clear inputs, a defined deliverable back to the caller. + +## Delegation patterns + +Two patterns recur on top of the boundaries; each deserves its own use-case treatment as the ecosystem matures: + +- **Adversarial review.** Delegate critique to a _differently composed_ identity than the author — a different model, persona, or loadout, often a machine account, so the review carries no author bias and a visibly separate identity. The [personas convention](./personas.md) supplies the reviewer shape; the CI-backed boundary supplies the separate identity and audit trail. +- **Singleton coordinator.** Invert the fan-out: you always talk to **one** persistent agent (a machine account listening to its GitHub notifications), which keeps a bounded, prioritized queue and always chooses what to work on next. Everything else — CI runs, cluster Jobs, in-run subagents — is _its_ delegation target. The human interface stays one conversation; concurrency lives below it. "Assign the PR to the agent" becomes the entire UX. ## When to give an agent subagents diff --git a/docs/documentation/usecases/flaky-test-postmortems.md b/docs/documentation/usecases/flaky-test-postmortems.md new file mode 100644 index 00000000..f3363a67 --- /dev/null +++ b/docs/documentation/usecases/flaky-test-postmortems.md @@ -0,0 +1,20 @@ +# Flaky-test post-mortems in CI + +Slow system tests tax a team twice: once waiting for the run, and again when a red X lands and someone has to decide whether it is a real regression or last week's timing flake. Most of that second tax is mechanical — fetch the logs, compare against the diff, remember whether this failure signature has appeared before — which makes it delegable. + +## The composition + +One optional on-failure step hands the event to the shared CI agent the repository already runs through [`ai-outfitter/actions`](https://github.com/ai-outfitter/actions) — no new workflow, no new agent: + +- **Trigger.** The test workflow's failure (`if: failure()`) invokes the shared agent with structured `trigger_context` — workflow name, run id, a `failure_kind` — as opaque routing metadata, never as instructions ([Running an agent in GitHub Actions](../actions.md)). +- **Routing.** The agent maps `failure_kind: system-tests` to exactly one skill, a `test-postmortem` capability; the skill then fetches logs and the diff with trusted tools. This is the _few agents, many skills_ shape from [Best practices](../best-practices.md) — adding release-note triage later adds a skill and an activation rule, not another agent. +- **Verdict.** The skill classifies flake vs. real regression with a confidence level and posts one comment on the PR with its evidence. Comment-only is the safe default mode. +- **Audit.** The run uploads its session transcript as a workflow artifact, so anyone can read exactly how the agent reached its verdict. + +## Escalation, governed + +Auto-fixing is opt-in and label-gated: with the label present, the agent may push a single fix commit under a machine-account token (the default `GITHUB_TOKEN` deliberately cannot re-trigger CI). Stacked guards keep the loop bounded — a recursion guard, an attempt cap that hands off to a human, workflow `concurrency` with `cancel-in-progress` and `timeout-minutes`, and the label itself limiting blast radius. The machine-account and token-scoping decisions are documented in the [`ai-outfitter/actions`](https://github.com/ai-outfitter/actions) credential guides. + +## Payoff + +The red X arrives already triaged: a verdict, a confidence, the evidence, and a transcript — and the team decides only what to do about it. The delegation crosses the [CI-backed boundary](../subagents.md#the-four-delegation-boundaries); the same event-driven shape powers [alert investigations in-cluster](./grafana-alert-investigator.md). diff --git a/docs/documentation/usecases/grafana-alert-investigator.md b/docs/documentation/usecases/grafana-alert-investigator.md new file mode 100644 index 00000000..e51c456e --- /dev/null +++ b/docs/documentation/usecases/grafana-alert-investigator.md @@ -0,0 +1,18 @@ +# Grafana alert investigations in-cluster + +Resource alerts are noisy: CPU pinned where it is always pinned, a pod that quietly died and restarted, an OOMKill that actually matters. A human triages every one, or the channel gets muted. The triage itself — scope to the resource, read the dashboards and logs for the alert window, decide expected vs. anomaly — is bounded work an agent can do per alert. + +## The composition + +- **Trigger.** A `kube-prometheus-stack` Alertmanager webhook receiver (added with `continue: true`, so human paging is untouched) turns each firing alert into one bounded headless run; alert labels travel as `trigger_context` routing metadata, treated as untrusted data. +- **Agent.** The community-catalog `grafana-alert-investigator` agent ([community-profiles#8](https://github.com/ai-outfitter/community-profiles/pull/8)) composes two skills — investigate and issue-triage — plus one MCP declaration for the already-running [`grafana/mcp-grafana`](https://github.com/grafana/mcp-grafana) server, giving it Loki, Prometheus, Tempo, and Pyroscope, alongside a read-only Kubernetes view. +- **Verdict.** The investigation is scoped to the alerting resource and the alert window, and classifies the alert `expected` (known-noisy — recommend tuning or ignoring the rule) or `anomaly` (OOMKill, non-zero exit, a new hot path) with a confidence level. +- **Safe default.** The agent posts exactly one diagnosis comment on the existing tracking issue. It never mutates a workload and never edits the issue — comment-only is the only mode. + +## The wiring + +The agent itself is deliberately deployment-agnostic; the Link Operator's webhook-driven design supplies the in-cluster wiring ([In-cluster agents](../in-cluster.md) — a design preview until the operator ships): a webhook receiver channel materializes **one subagent Job per firing alert** in the agent's namespace, sharing its service account and quota — bounded, timeout-enforced, read-only RBAC. This is the push style of channel intake; the same agent could instead be swept up by a resident agent's [loop tick](../recurring-runs.md). + +## Payoff + +Every alert arrives with a diagnosis already attached: what fired, what the dashboards and logs show for the window, expected or anomaly, and with what confidence — and the on-call human spends attention only on the anomalies. Setting up the observability stack this rides on (provisioning Grafana alerting, the MCP server, read-only RBAC) is platform-profile work — the convention discussed in [#197](https://github.com/ai-outfitter/outfitter/issues/197). diff --git a/docs/documentation/usecases/self-improving-skills.md b/docs/documentation/usecases/self-improving-skills.md new file mode 100644 index 00000000..78a6e3f5 --- /dev/null +++ b/docs/documentation/usecases/self-improving-skills.md @@ -0,0 +1,19 @@ +# Self-improving skills + +A skill is a markdown file — which means it can be _trained_. [`ai-outfitter/autoimprove`](https://github.com/ai-outfitter/autoimprove) treats a skill as the trainable parameter of a frozen agent: replay real tasks against the current skill text, propose small edits, and accept only the edits that measurably improve a held-out score. + +## The loop + +1. **Rollout** — run the agent with the current skill over a batch of tasks, scoring each result. +2. **Reflect** — an optimizer model reads the failures and proposes bounded `add`/`delete`/`replace` edits, capped per step (a textual learning rate). +3. **Gate** — candidate skills are evaluated on a held-out validation split; an edit is accepted only on _strict_ improvement, and a never-touched test split keeps the final numbers honest. + +The worked example is a parametric CAD skill ([autoimprove#2](https://github.com/ai-outfitter/autoimprove/pull/2)): a `generate-replicad-cad` skill scored by executable CAD and assembly checks — the failures that matter (fused parts, broken clearances) are exactly the ones executable evaluation catches, and deterministic non-regression gates keep a clever edit from breaking working cases. + +## Scheduling and review + +The training loop is itself a [recurring run](../recurring-runs.md): a weekly GitHub Actions cron replays the benchmark, and when the gate accepts an improvement, the automation refreshes a single draft PR with the new skill text and its before/after scores. **The skill never self-merges** — a human reviews a readable diff of the skill's actual instructions, with the measurement attached. The blast radius of "the agent got smarter" is a pull request. + +## Graduation + +A skill that keeps passing its gate is a candidate for [the ladder](../conventions.md): promote the pinned, validated revision from the personal or project tree into a shared catalog, and every engineer's agent can select it by slug — without owning the trainer, the benchmark, or the credentials that produced it. Training infrastructure stays where it ran; only the proven capability graduates. diff --git a/docs/documentation/usecases/shared-conventions.md b/docs/documentation/usecases/shared-conventions.md new file mode 100644 index 00000000..e7310368 --- /dev/null +++ b/docs/documentation/usecases/shared-conventions.md @@ -0,0 +1,47 @@ +# Shared conventions without duplication + +Every agent that touches a repository should write [Conventional Commits](https://www.conventionalcommits.org/): the engineer agent, the marketing agent that occasionally commits copy, the CI bot that opens automated PRs. The rule is universal — and that is exactly what makes it dangerous to manage naively. + +## The failure mode + +The naive path pastes the rule into every `agent.md`, every project's `CLAUDE.md`, every teammate's personal prompt. Now there are N copies: they drift as people tweak wording, every copy occupies every context window on every run, and a new agent starts without the rule until someone remembers. Making it a skill is the subtler mistake — a skill implies an _activation decision_, and no agent should ever spend a thought deciding whether commit formatting applies. It should simply always be true. + +## The composition + +Author the rule **once, at the most general layer where it holds**, and let every layer below inherit it: + +```markdown + + +Use Conventional Commits for every commit message, with scopes +(for example `fix(setup): ...`, `docs(runtime): ...`). +``` + +- **Every user, every project, every agent** composed from the org catalog now carries the rule — one authored copy, zero activation cost, no per-agent duplication. +- **A single user** who wants it everywhere on one machine before the org adopts it drops the same line in `~/.agents/system-prompt.md` — the quickest way to give everything you run a shared rule. +- **A project that differs** (say, a repo that squash-merges with its own title format) ships its own shared context in `/.agents/` — workspace precedence wins for that repo only. Note the granularity: today the root shared-context file wins _whole_, not line by line (fragment-level override is the [roadmap primitive](../conventions.md#roadmap-a-shareable-prompt-fragment)), so the project file deliberately carries the shared context it still wants — a reviewable replacement in the repo it affects. +- **Enforcement stays deterministic** — a `commit-msg` [hook](../hooks.md) or release tooling backstops the rule mechanically; the ambient line keeps the model writing it right the first time. + +The same placement works for every ambient rule: secret hygiene, small reversible changes, "write decisions into repository files." The test is the [conventions](../conventions.md) split — if the agent should never _decide_ about it, it belongs in shared context, not in a skill. + +## A second fragment: repository layout + +A second convention of the same shape — illustrative here, and the kind of rule a default catalog adopts as `project-repos` — standardizes where code lives on a machine: + +```markdown + + +Repositories are checked out at `~/repos///`; +linked worktrees live beside them at +`~/repos//.worktrees/`. +``` + +The value is ambiguity reduction: every agent — and every skill that clones, opens a worktree, or navigates between projects — knows where a repository lives without asking or guessing, and automation composed from the catalog can rely on the same paths on every machine. A user who keeps a different layout supplies their own amended shared context in `~/.agents` (a whole-file replacement today — per-fragment override is the [roadmap primitive](../conventions.md#roadmap-a-shareable-prompt-fragment)) and keeps using the shared profiles unchanged — or builds their own profiles from scratch. Either way the catalog never forks over a filesystem preference. + +## Reaching native harness runs + +Composition only helps runs that go through it — the rule should also reach a bare `claude` session that never touches Outfitter. The porting design ([Porting a Claude Code setup](../porting-claude.md)) maps `~/.claude/CLAUDE.md` to `~/.agents/agents.md` with a symlink back, so native Claude Code reads the protocol tree and editing either view edits the same file; managed porting and persistent harness symlinks — including the generalization of projecting composed shared context into each harness's home-level memory file — are deferred to [#187](https://github.com/ai-outfitter/outfitter/issues/187). + +## Payoff + +One rule, authored once, inherited by every user, org, and project layer; overridable exactly where it should differ; enforced mechanically; visible in native harnesses. The context cost across the whole fleet is a single line — and when the org rewords the rule, one PR to one file updates every agent's next run.