@ai-outfitter/outfitter 1.1.2 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/dist/agents/PiSessionDirectory.d.ts +16 -0
  2. package/dist/agents/PiSessionDirectory.js +41 -0
  3. package/dist/agents/PiSessionDirectory.js.map +1 -0
  4. package/dist/cli/commands/DumpCommand.js +1 -1
  5. package/dist/cli/commands/DumpCommand.js.map +1 -1
  6. package/dist/cli/commands/RunAgentCommand.js +11 -3
  7. package/dist/cli/commands/RunAgentCommand.js.map +1 -1
  8. package/dist/cli/commands/ValidateCommand.js +1 -1
  9. package/dist/cli/commands/ValidateCommand.js.map +1 -1
  10. package/dist/composer/Composer.d.ts +7 -5
  11. package/dist/composer/Composer.js +280 -64
  12. package/dist/composer/Composer.js.map +1 -1
  13. package/dist/composer/Composition.d.ts +34 -3
  14. package/dist/composer/PromptSource.d.ts +44 -0
  15. package/dist/composer/PromptSource.js +113 -0
  16. package/dist/composer/PromptSource.js.map +1 -0
  17. package/dist/dump/Dump.d.ts +1 -1
  18. package/dist/dump/Dump.js +111 -20
  19. package/dist/dump/Dump.js.map +1 -1
  20. package/dist/projection/Materialize.d.ts +1 -5
  21. package/dist/projection/Materialize.js +57 -13
  22. package/dist/projection/Materialize.js.map +1 -1
  23. package/dist/projection/ProjectHarness.js +19 -4
  24. package/dist/projection/ProjectHarness.js.map +1 -1
  25. package/dist/projection/Projection.d.ts +2 -0
  26. package/dist/resolver/AgentDefinition.d.ts +9 -0
  27. package/dist/resolver/AgentDefinition.js +17 -0
  28. package/dist/resolver/AgentDefinition.js.map +1 -1
  29. package/dist/resolver/ResolverValidation.d.ts +1 -1
  30. package/dist/resolver/ResolverValidation.js +25 -15
  31. package/dist/resolver/ResolverValidation.js.map +1 -1
  32. package/dist/schemas/agent.schema.json +32 -0
  33. package/docs/documentation/agents.md +81 -26
  34. package/docs/documentation/migration.md +18 -9
  35. package/docs/documentation/profiles.md +24 -7
  36. package/docs/documentation/state.md +28 -1
  37. package/package.json +1 -1
  38. package/src/schemas/agent.schema.json +32 -0
@@ -1,6 +1,11 @@
1
1
  # Agents
2
2
 
3
- An agent is the protocol's identity resource — and, in Outfitter, the thing you run. A directory under `agents/<id>/` holds an `agent.md` definition and an optional `config.json`. Together they carry both _who the agent is_ and _what it runs with_: its skills, MCP servers, subagents, extensions, plugins, model, thinking level, and tool policy. That whole bundle — identity plus loadout — is what earlier drafts called a "profile." There is no separate profile resource; **an agent is the profile**. See [Profiles](./profiles.md).
3
+ An agent is the protocol's identity resource — and, in Outfitter, the thing you run.
4
+ A directory under `agents/<id>/` holds an `agent.md` definition and an optional `config.json`.
5
+ Together they carry both _who the agent is_ and _what it runs with_: its skills, MCP servers, subagents, extensions, plugins, model, thinking level, and tool policy.
6
+ That whole bundle — identity plus loadout — is what earlier drafts called a "profile."
7
+ There is no separate profile resource; **an agent is the profile**.
8
+ See [Profiles](./profiles.md).
4
9
 
5
10
  ```text
6
11
  .agents/
@@ -33,6 +38,8 @@ model: gpt-5.2
33
38
  thinking: high
34
39
  tools:
35
40
  allow: [read, edit, bash]
41
+ append_system_prompt:
42
+ - repo_file: docs/architecture.md
36
43
  ---
37
44
 
38
45
  # Engineer
@@ -40,11 +47,12 @@ tools:
40
47
  You implement changes directly, keep diffs small, and verify before claiming done...
41
48
  ```
42
49
 
43
- `name` is the stable slug used for resolution. The optional `label` is the human-readable profile
44
- name shown during setup and in interactive harness UI. When `label` is omitted, Outfitter uses the
45
- first level-one Markdown heading, then falls back to the slug.
50
+ `name` is the stable slug used for resolution.
51
+ The optional `label` is the human-readable profile name shown during setup and in interactive harness UI.
52
+ When `label` is omitted, Outfitter uses the first level-one Markdown heading, then falls back to the slug.
46
53
 
47
- Keep the prose focused on durable identity and behavior. Per-capability procedures belong in [skills](./skills.md); the frontmatter only _selects_ resources by slug — it never copies their content.
54
+ Keep the prose focused on durable identity and behavior.
55
+ Per-capability procedures belong in [skills](./skills.md); the frontmatter only _selects_ resources by slug — it never copies their content.
48
56
 
49
57
  ### Loadout fields
50
58
 
@@ -59,13 +67,59 @@ Keep the prose focused on durable identity and behavior. Per-capability procedur
59
67
  | `thinking` | Thinking/effort level. |
60
68
  | `tools` | Allowed/denied tool policy for the run. |
61
69
 
62
- Every value is a slug resolved across layers. Skills first check `agents/<agent>/skills/<slug>/` across layer precedence, then fall back to catalog-wide `skills/<slug>/`. This lets an agent own private implementation capabilities without exposing them to every agent in the catalog. See [Skills](./skills.md#agent-local-skills).
70
+ Every value is a slug resolved across layers.
71
+ Skills first check `agents/<agent>/skills/<slug>/` across layer precedence, then fall back to catalog-wide `skills/<slug>/`.
72
+ This lets an agent own private implementation capabilities without exposing them to every agent in the catalog.
73
+ See [Skills](./skills.md#agent-local-skills).
63
74
 
64
- `knowledge` and `commands` resolve the same way — an agent may keep private files under `agents/<agent>/knowledge/` and `agents/<agent>/commands/`, local-first over the catalog-wide trees. `subagents` are always catalog-wide (a delegate is a shared agent). `extensions`/`plugins` are harness-native passthroughs with no on-disk namespace, and `model`/`thinking`/`tools` are per-agent already via `config.json` merge.
75
+ `knowledge` and `commands` resolve the same way — an agent may keep private files under `agents/<agent>/knowledge/` and `agents/<agent>/commands/`, local-first over the catalog-wide trees.
76
+ `subagents` are always catalog-wide (a delegate is a shared agent).
77
+ `extensions`/`plugins` are harness-native passthroughs with no on-disk namespace, and `model`/`thinking`/`tools` are per-agent already via `config.json` merge.
78
+
79
+ ## Inheritance and prompt fragments
80
+
81
+ An agent may specialize one or more base agents with `inherits`.
82
+ Parents compose recursively, parent-first, and multiple parents keep the order written in the child.
83
+ Diamond graphs include each ancestor once.
84
+ Outfitter fails validation and composition for missing parents, self-inheritance, or indirect cycles.
85
+
86
+ ```markdown
87
+ ---
88
+ name: platform-engineer
89
+ inherits: engineer
90
+ skills: [nix, kubernetes]
91
+ system_prompt:
92
+ file: prompts/platform-system.md
93
+ append_system_prompt:
94
+ - file: prompts/platform-review.md
95
+ - repo_file: docs/architecture.md
96
+ prompt_template:
97
+ file: prompt-templates/implementation.md
98
+ ---
99
+
100
+ # Platform Engineer
101
+
102
+ You specialize the base engineer for NixOS and Kubernetes work.
103
+ ```
104
+
105
+ Merge policy is deterministic: Markdown bodies append ancestor-first and child-last; list fields (`skills`, `subagents`, `mcp`, `extensions`, `plugins`, `append_system_prompt`) de-duplicate parent-first; scalar controls (`system_prompt`, `prompt_template`, `model`, `thinking`, `label`, `description`) use the nearest child declaration.
106
+ Parent-declared skills resolve against that parent's local skill namespace before catalog fallback, so a child cannot accidentally capture a parent's private loadout.
107
+
108
+ Prompt sources are explicit objects.
109
+ `file` reads trusted catalog content relative to the `.agents` layer that owns the declaring agent and must stay inside that layer.
110
+ `repo_file` reads active-repository content relative to the project root, remains contained after symlink resolution, and is treated as untrusted repository context; missing optional repository files warn so reusable catalog agents do not become brittle across projects.
111
+ Named prompt slugs are intentionally not accepted yet.
112
+
113
+ Effective prompt order is: selected `system_prompt` or root `system-prompt.md`; root `agents.md`; inherited then child `append_system_prompt`; inherited then child agent bodies; any runtime passthrough append prompts.
114
+
115
+ Inheritance is not delegation.
116
+ Inheritance composes one selected agent's identity and loadout before launch.
117
+ `subagents` expose other agents as delegates the selected agent may call at runtime.
65
118
 
66
119
  ## Pi configuration overlay
67
120
 
68
- An agent may own native Pi configuration under `agents/<agent>/pi/`. Outfitter overlays that folder into the temporary `PI_CODING_AGENT_DIR` before launching Pi, so native files keep their standard names and formats:
121
+ An agent may own native Pi configuration under `agents/<agent>/pi/`.
122
+ Outfitter overlays that folder into the temporary `PI_CODING_AGENT_DIR` before launching Pi, so native files keep their standard names and formats:
69
123
 
70
124
  ```text
71
125
  agents/founder/
@@ -77,26 +131,24 @@ agents/founder/
77
131
  └── themes/
78
132
  ```
79
133
 
80
- The overlay is file-based. Source layers are applied from lowest to highest precedence, so a workspace `agents/founder/pi/keybindings.json` replaces the same file from a global or remote catalog while unrelated lower-layer files remain present. Outfitter does not follow symlinks from the overlay. The folder is ignored when the selected harness is not Pi.
134
+ The overlay is file-based.
135
+ Source layers are applied from lowest to highest precedence, so a workspace `agents/founder/pi/keybindings.json` replaces the same file from a global or remote catalog while unrelated lower-layer files remain present.
136
+ Outfitter does not follow symlinks from the overlay.
137
+ The folder is ignored when the selected harness is not Pi.
81
138
 
82
- Outfitter writes generated identity, composed skills, selected delegates, and
83
- selected MCP servers after applying the native overlay, and seeds durable Pi
84
- credentials immediately before launch. Those runtime-owned resources therefore
85
- cannot be replaced accidentally by a profile overlay.
139
+ Outfitter writes generated identity, composed skills, selected delegates, and selected MCP servers after applying the native overlay, and seeds durable Pi credentials immediately before launch.
140
+ Those runtime-owned resources therefore cannot be replaced accidentally by a profile overlay.
86
141
 
87
- `agents/<agent>/mcp.json` merges by server id over layered tree-root `mcp.json`
88
- files. The Pi projection writes only the servers selected by the active
89
- agent's `mcp` loadout into the runtime `mcp.json`.
142
+ `agents/<agent>/mcp.json` merges by server id over layered tree-root `mcp.json` files.
143
+ The Pi projection writes only the servers selected by the active agent's `mcp` loadout into the runtime `mcp.json`.
90
144
 
91
- The per-agent `agents/<agent>/hooks/` namespace remains reserved and is not yet
92
- projected (adapter parity is tracked in
93
- [#183](https://github.com/ai-outfitter/outfitter/issues/183)). Its presence
94
- surfaces a validation warning so content placed there is never silently
95
- dropped.
145
+ The per-agent `agents/<agent>/hooks/` namespace remains reserved and is not yet projected (adapter parity is tracked in [#183](https://github.com/ai-outfitter/outfitter/issues/183)).
146
+ Its presence surfaces a validation warning so content placed there is never silently dropped.
96
147
 
97
148
  ## config.json
98
149
 
99
- The optional `config.json` carries structured or harness-specific configuration that is awkward in frontmatter, following the protocol's schema for the pinned revision. JSON files merge across layers per the protocol's JSON merge behavior, so a workspace layer can adjust one field of a globally defined agent — swap the model, add an extension — without copying the whole definition.
150
+ The optional `config.json` carries structured or harness-specific configuration that is awkward in frontmatter, following the protocol's schema for the pinned revision.
151
+ JSON files merge across layers per the protocol's JSON merge behavior, so a workspace layer can adjust one field of a globally defined agent — swap the model, add an extension — without copying the whole definition.
100
152
 
101
153
  ## Tree-level context
102
154
 
@@ -118,10 +170,13 @@ outfitter run engineer --harness claude
118
170
 
119
171
  ## Resolution
120
172
 
121
- Agents resolve by slug across layers — workspace, global, then remote sources — with merge-by-ID semantics: a workspace `agents/engineer/` overrides a global or remote one. Agent-local skills merge by their owner and slug using the same layer order. `outfitter list agents` shows every resolvable agent and its winning source; `outfitter list skills --agent engineer` shows its effective skill namespace; `outfitter validate` reports broken loadout slugs and shadowed definitions.
173
+ Agents resolve by slug across layers — workspace, global, then remote sources — with merge-by-ID semantics: a workspace `agents/engineer/` overrides a global or remote one.
174
+ Agent-local skills merge by their owner and slug using the same layer order.
175
+ `outfitter list agents` shows every resolvable agent and its winning source; `outfitter list skills --agent engineer` shows its effective skill namespace; `outfitter validate` reports broken loadout slugs and shadowed definitions.
122
176
 
123
177
  ## Agents as delegates
124
178
 
125
- The same agent definition can also be selected as a [subagent](./subagents.md) in another agent's `subagents` list — a delegate the run can hand focused work to. A leader agent's loadout is where that delegation is declared.
126
- For Pi runs, Outfitter also resolves and materializes the delegate's selected skills. Those skills
127
- are available to the delegate without being loaded into the leader's active skill set.
179
+ The same agent definition can also be selected as a [subagent](./subagents.md) in another agent's `subagents` list — a delegate the run can hand focused work to.
180
+ A leader agent's loadout is where that delegation is declared.
181
+ For Pi runs, Outfitter also resolves and materializes the delegate's selected skills.
182
+ Those skills are available to the delegate without being loaded into the leader's active skill set.
@@ -1,18 +1,21 @@
1
1
  # Migration from legacy profiles
2
2
 
3
- Earlier Outfitter versions used an authored profile system: `.outfitter/` directories, `profile.yml` files, profile inheritance, and `--profile` pointing at profile definitions. [RFC #165](https://github.com/ai-outfitter/outfitter/issues/165) replaces that system with the Dotagents `.agents` protocol as a hard cut: the end-state runtime has **no knowledge of the old format** — no compatibility reader, no migration command, no deprecated aliases. (These docs describe that target; the released CLI still runs the legacy profile format during the transition.) This page is the manual migration reference, and the bundled Outfitter skill can walk an agent session through it interactively.
3
+ Earlier Outfitter versions used an authored profile system: `.outfitter/` directories, `profile.yml` files, profile inheritance, and `--profile` pointing at profile definitions.
4
+ [RFC #165](https://github.com/ai-outfitter/outfitter/issues/165) replaces that system with the Dotagents `.agents` protocol as a hard cut: the end-state runtime has **no knowledge of the old format** — no compatibility reader, no migration command, no deprecated aliases.
5
+ (These docs describe that target; the released CLI still runs the legacy profile format during the transition.)
6
+ This page is the manual migration reference, and the bundled Outfitter skill can walk an agent session through it interactively.
4
7
 
5
8
  ## Mapping
6
9
 
7
10
  | Legacy | End state |
8
11
  | ------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
9
12
  | `.outfitter/profiles/<id>/profile.yml` (or `<id>.yml`) | Split into resources: identity → `agents/<id>/agent.md`, procedures → `skills/`; the loadout lives in that [agent](./profiles.md)'s frontmatter / `config.json` — there is no separate selection |
10
- | `controls.system_prompt` / `append_system_prompt` | `system-prompt.md`, `agents.md`, and the agent's `agent.md` body |
13
+ | `controls.system_prompt` / `append_system_prompt` | Agent frontmatter `system_prompt` / `append_system_prompt` with explicit `{ file }` or `{ repo_file }` sources; use root `system-prompt.md` / `agents.md` for tree-wide context |
11
14
  | `controls.model`, `provider`, `thinking` | `models.json` (and per-agent `config.json`) |
12
15
  | `controls.skills` | The agent's `skills:` loadout; skills live at `skills/<id>/` |
13
16
  | `controls.extensions`, `args`, `environment` | Harness configuration projected by adapters; MCP servers → `mcp.json` |
14
- | Profile inheritance (`inherits:`) | Layer merge-by-ID, plus shared context in `system-prompt.md` / `agents.md` |
15
- | `template: true` base profiles | A base agent whose shared context lives in `system-prompt.md` / `agents.md` (or a base agent selected as a delegate) |
17
+ | Profile inheritance (`inherits:`) | Agent frontmatter `inherits:` naming one parent slug or an ordered parent list; manually translate the old profile into an agent first |
18
+ | `template: true` base profiles | A base agent referenced with agent `inherits`; there is no separate template flag |
16
19
  | `~/.outfitter/settings.yml` | `~/.agents/settings.yml` |
17
20
  | `<project>/.outfitter/settings.yml` | `<project>/.agents/settings.yml` |
18
21
  | `<project>/.outfitter/local/settings.yml` (nested dir) | `<project>/.agents/settings.local.yml` (flat, gitignored) |
@@ -25,14 +28,20 @@ Earlier Outfitter versions used an authored profile system: `.outfitter/` direct
25
28
 
26
29
  ## Procedure
27
30
 
28
- 1. **Inventory** your `.outfitter/profiles`. For each profile, separate what it contains: identity/policy prose, capability procedures, model/provider config, tool wiring.
29
- 2. **Create resources**: one `agents/<id>/agent.md` per durable identity; one `skills/<id>/` per capability (most `append_system_prompt` procedure text belongs in skills); shared context into `agents.md`; model config into `models.json`; MCP into `mcp.json`.
30
- 3. **Rebuild as agents**: for each profile people actually ran, create an `agents/<id>/agent.md` whose frontmatter (or `config.json`) loadout selects the new resources by slug. Set `default_agent` to the one you run most. Inheritance chains become shared context in `system-prompt.md` / `agents.md` (or a base agent selected as a delegate), not an ordered selection.
31
- 4. **Move settings**: relocate `~/.outfitter/settings.yml` content into `~/.agents/settings.yml`, project settings into `<project>/.agents/settings.yml`, and anything under `.outfitter/local/` into a flat `.agents/settings.local.yml` (gitignore it). Rename `profile_sources` to `sources`; sources must now publish `.agents` payloads.
31
+ 1. **Inventory** your `.outfitter/profiles`.
32
+ For each profile, separate what it contains: identity/policy prose, capability procedures, model/provider config, tool wiring.
33
+ 2. **Create resources**: one `agents/<id>/agent.md` per durable identity; one `skills/<id>/` per capability; shared context into `agents.md`; model config into `models.json`; MCP into `mcp.json`.
34
+ Move prompt fragments that must load eagerly into catalog-contained `file` sources or project-contained `repo_file` sources.
35
+ 3. **Rebuild as agents**: for each profile people actually ran, create an `agents/<id>/agent.md` whose frontmatter (or `config.json`) loadout selects the new resources by slug.
36
+ Translate reusable base profiles into base agents and preserve intentional inheritance order with agent `inherits`.
37
+ Set `default_agent` to the one you run most.
38
+ 4. **Move settings**: relocate `~/.outfitter/settings.yml` content into `~/.agents/settings.yml`, project settings into `<project>/.agents/settings.yml`, and anything under `.outfitter/local/` into a flat `.agents/settings.local.yml` (gitignore it).
39
+ Rename `profile_sources` to `sources`; sources must now publish `.agents` payloads.
32
40
  5. **Validate**: `outfitter validate --strict`, then `outfitter dump` and review the tree.
33
41
  6. **Delete** the `.outfitter/` directory once the dump matches expectations.
34
42
 
35
- A remote repository _named_ `.outfitter` remains a supported convention for organization control repos — but only when it publishes the new protocol payload. The name is supported; the previous profile layout inside it is not.
43
+ A remote repository _named_ `.outfitter` remains a supported convention for organization control repos — but only when it publishes the new protocol payload.
44
+ The name is supported; the previous profile layout inside it is not.
36
45
 
37
46
  ## Claude Code users
38
47
 
@@ -1,30 +1,47 @@
1
1
  # Agent profiles
2
2
 
3
- "Profile" is a description, not a resource or a settings key. There is no `profile.yml`, no `profiles:` map, and no profile file format. What earlier drafts modeled as a standalone profile — a named selection of skills, subagents, model, and so on — is now just an [agent](./agents.md) and its loadout.
3
+ "Profile" is a description, not a resource or a settings key.
4
+ There is no `profile.yml`, no `profiles:` map, and no profile file format.
5
+ What earlier drafts modeled as a standalone profile — a named selection of skills, subagents, model, and so on — is now just an [agent](./agents.md) and its loadout.
4
6
 
5
7
  ## Profiles are agents
6
8
 
7
- An **agent profile** is the whole bundle an agent carries: its identity (`agent.md`) plus the loadout declared in that agent's frontmatter or `config.json` — skills, MCP servers, subagents, extensions, plugins, model, thinking level, and tool policy. When someone says "the engineer profile," they mean the `engineer` agent with everything it composes.
9
+ An **agent profile** is the whole bundle an agent carries: its identity (`agent.md`) plus the loadout declared in that agent's frontmatter or `config.json` — skills, MCP servers, subagents, extensions, plugins, model, thinking level, and tool policy.
10
+ When someone says "the engineer profile," they mean the `engineer` agent with everything it composes.
8
11
 
9
- Folding profiles into agents removes a layer of indirection. Instead of a settings map that points at resources that point at an identity, one agent directory holds identity and loadout together, resolves by slug like any other resource, and is what you run:
12
+ Folding profiles into agents removes a layer of indirection.
13
+ Instead of a settings map that points at resources that point at an identity, one agent directory holds identity and loadout together, resolves by slug like any other resource, and is what you run:
10
14
 
11
15
  ```bash
12
16
  outfitter run engineer
13
17
  outfitter run engineer --harness claude
14
18
  ```
15
19
 
16
- `outfitter list agents` shows every resolvable agent and where each resolves from, including shadowed IDs. Set `default_agent` in [settings](./settings.md) to choose what plain `outfitter` runs.
20
+ `outfitter list agents` shows every resolvable agent and where each resolves from, including shadowed IDs.
21
+ Set `default_agent` in [settings](./settings.md) to choose what plain `outfitter` runs.
17
22
 
18
23
  ## Where the loadout lives
19
24
 
20
- The loadout lives on the agent, not in settings. Add or change what an agent composes by editing that agent's `agents/<id>/agent.md` frontmatter or `config.json` — see [Agents](./agents.md#loadout-fields) for the field list. To override just one field from a higher layer (swap the model, add an extension) without redefining the agent, put it in the agent's `config.json`: JSON files shallow-merge by key across layers. An `agent.md` resolves whole-resource by ID — the winning layer's `agent.md` replaces lower ones rather than field-merging — so a partial `agent.md` would discard the base identity.
25
+ The loadout lives on the agent, not in settings.
26
+ Add or change what an agent composes by editing that agent's `agents/<id>/agent.md` frontmatter or `config.json` — see [Agents](./agents.md#loadout-fields) for the field list.
27
+ To override just one field from a higher layer (swap the model, add an extension) without redefining the agent, put it in the agent's `config.json`: JSON files shallow-merge by key across layers.
28
+ An `agent.md` resolves whole-resource by ID — the winning layer's `agent.md` replaces lower ones rather than field-merging — so a partial `agent.md` would discard the base identity.
21
29
 
22
30
  Settings ([settings.md](./settings.md)) is left with just resolution and launch concerns — `default_agent`, `default_harness`, `sources`, and state policy — not resource selection.
23
31
 
24
32
  ## Composing from a base
25
33
 
26
- To share behavior across several agents, keep shared operating context in the tree's `system-prompt.md` and `agents.md` — every agent in the tree inherits those — and put shared procedures in [skills](./skills.md) each agent selects. Selecting an agent as a subagent does _not_ share its policy; it only makes that agent available as a delegation target. The [persona](./personas.md) convention builds on the shared-context idea: one shared review agent, many single-file persona documents appended at launch.
34
+ Use `inherits` when one agent is a specialization of another.
35
+ The base agent's body and additive loadout compose first; child bodies append, child scalar controls override, and inherited parent-local resources retain their parent ownership.
36
+ For example, `platform-engineer` can `inherits: engineer` and add `skills: [nix, kubernetes]`.
37
+ Multiple parents are ordered left-to-right, recursively, with diamond ancestors included once.
38
+
39
+ Use tree-level `system-prompt.md` and `agents.md` for context shared by every agent, and [skills](./skills.md) for reusable procedures.
40
+ Selecting an agent as a `subagent` is different from inheritance: it exposes a runtime delegation target and does not merge that delegate's identity into the leader.
41
+ See [Agents](./agents.md#inheritance-and-prompt-fragments) for the exact merge and prompt-source rules.
27
42
 
28
43
  ## Migrating from authored profiles
29
44
 
30
- Earlier Outfitter versions defined profiles as authored YAML files (`.outfitter/profiles/`, `profile.yml`, inheritance, `controls`). That system is removed with no compatibility mode. See the [migration reference](./migration.md) for the manual mapping from the legacy format to agents and their loadouts.
45
+ Earlier Outfitter versions defined profiles as authored YAML files (`.outfitter/profiles/`, `profile.yml`, inheritance, `controls`).
46
+ That system is removed with no compatibility mode.
47
+ See the [migration reference](./migration.md) for the manual mapping from the legacy format to agents and their loadouts.
@@ -152,7 +152,7 @@ state_persistence:
152
152
  trust.json: symlink # Pi trust decisions.
153
153
  plugins/: symlink # Pi plugins.
154
154
  cache/: symlink # Pi cache data.
155
- sessions/: symlink # Pi sessions.
155
+ sessions/: symlink # Pi sessions; the "Pi sessions" section covers how this works today.
156
156
  npm/: symlink # Pi npm package installs.
157
157
  git/: symlink # Pi git package checkouts.
158
158
  tmp/: symlink # Pi temporary runtime tree; allowed: symlink, discard.
@@ -161,6 +161,33 @@ state_persistence:
161
161
  unknown: warn # Undeclared writes; allowed: discard, warn, error, prompt.
162
162
  ```
163
163
 
164
+ ## Pi sessions
165
+
166
+ Pi stores conversation transcripts under its agent directory, and Outfitter points `PI_CODING_AGENT_DIR` at a baked composition that is deleted when the run ends. So that sessions are not deleted with it, every Pi launch sets `PI_CODING_AGENT_SESSION_DIR` to Pi's own durable per-project session folder:
167
+
168
+ ```text
169
+ ~/.pi/agent/sessions/--<your-project-path>--/
170
+ ```
171
+
172
+ This is the same folder a standalone `pi` uses in that project, so history is shared both ways and resuming works after the baked composition is gone:
173
+
174
+ ```sh
175
+ outfitter run # first session
176
+ outfitter run -- --continue # picks up where the previous run left off
177
+ ```
178
+
179
+ The default applies to every Pi launch, interactive or not, so `outfitter run -p '…'` in a script or CI job records a session in the same place. Nothing is copied back after the run: Pi writes straight to the durable directory.
180
+
181
+ To change or turn off session storage, pass Pi's native flags through, or set the environment variable yourself — Outfitter never overrides a session directory you have already chosen:
182
+
183
+ ```sh
184
+ outfitter run -- --no-session # ephemeral: record nothing
185
+ outfitter run -- --session-dir ./.pi/sessions # keep this project's sessions in the repo
186
+ PI_CODING_AGENT_SESSION_DIR=/workspace/.pi/agent/sessions outfitter run
187
+ ```
188
+
189
+ The last form is how a resident or in-cluster agent keeps continuity across restarts: point the variable at a persistent volume.
190
+
164
191
  ## Claude Code state paths
165
192
 
166
193
  The Claude Code adapter declares these paths:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-outfitter/outfitter",
3
- "version": "1.1.2",
3
+ "version": "1.3.0",
4
4
  "description": "Profile-oriented wrapper for launching pi, Claude Code, and future agent CLIs with reproducible configuration.",
5
5
  "type": "module",
6
6
  "repository": {
@@ -8,6 +8,29 @@
8
8
  "name": { "type": "string", "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$", "maxLength": 64 },
9
9
  "label": { "type": "string", "minLength": 1 },
10
10
  "description": { "type": "string" },
11
+ "inherits": {
12
+ "oneOf": [
13
+ { "type": "string", "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$", "maxLength": 64 },
14
+ {
15
+ "type": "array",
16
+ "minItems": 1,
17
+ "items": { "type": "string", "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$", "maxLength": 64 }
18
+ }
19
+ ],
20
+ "description": "Parent agent slug or ordered parent slug list composed parent-first before this agent."
21
+ },
22
+ "system_prompt": {
23
+ "$ref": "#/$defs/promptSource",
24
+ "description": "Prompt fragment that replaces the winning root system-prompt.md; file is trusted catalog content and repo_file is untrusted repository content."
25
+ },
26
+ "append_system_prompt": {
27
+ "oneOf": [{ "$ref": "#/$defs/promptSource" }, { "type": "array", "items": { "$ref": "#/$defs/promptSource" } }],
28
+ "description": "Prompt fragments appended after root agents.md and before inherited agent bodies."
29
+ },
30
+ "prompt_template": {
31
+ "$ref": "#/$defs/promptSource",
32
+ "description": "Harness prompt-template source projected only by harnesses that support templates."
33
+ },
11
34
  "skills": {
12
35
  "$ref": "#/$defs/slugList",
13
36
  "description": "Skill slugs resolved from agents/<name>/skills first, then catalog-wide skills."
@@ -44,6 +67,15 @@
44
67
  "slugList": {
45
68
  "type": "array",
46
69
  "items": { "type": "string", "minLength": 1 }
70
+ },
71
+ "promptSource": {
72
+ "type": "object",
73
+ "oneOf": [{ "required": ["file"] }, { "required": ["repo_file"] }],
74
+ "properties": {
75
+ "file": { "type": "string", "minLength": 1 },
76
+ "repo_file": { "type": "string", "minLength": 1 }
77
+ },
78
+ "additionalProperties": false
47
79
  }
48
80
  }
49
81
  }