@ai-outfitter/outfitter 1.4.0 → 1.6.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.
- package/README.md +11 -2
- package/code/pi-extension/src/outfitter-extension.js +9 -1
- package/dist/agents/AgentLaunch.d.ts +2 -2
- package/dist/agents/AgentLaunch.js +4 -3
- package/dist/agents/AgentLaunch.js.map +1 -1
- package/dist/agents/ClaudeStatePersistence.d.ts +18 -0
- package/dist/agents/ClaudeStatePersistence.js +225 -0
- package/dist/agents/ClaudeStatePersistence.js.map +1 -0
- package/dist/cli/OutfitterCli.js +1 -1
- package/dist/cli/OutfitterCli.js.map +1 -1
- package/dist/cli/commands/RunAgentCommand.js +76 -15
- package/dist/cli/commands/RunAgentCommand.js.map +1 -1
- package/dist/cli/commands/SyncCommand.d.ts +7 -3
- package/dist/cli/commands/SyncCommand.js +110 -20
- package/dist/cli/commands/SyncCommand.js.map +1 -1
- package/dist/extensions/PiExtensionCache.d.ts +11 -1
- package/dist/extensions/PiExtensionCache.js +129 -13
- package/dist/extensions/PiExtensionCache.js.map +1 -1
- package/dist/projection/CodexMcp.d.ts +11 -0
- package/dist/projection/CodexMcp.js +143 -0
- package/dist/projection/CodexMcp.js.map +1 -0
- package/dist/projection/Materialize.d.ts +3 -1
- package/dist/projection/Materialize.js +10 -7
- package/dist/projection/Materialize.js.map +1 -1
- package/dist/projection/ProjectHarness.js +75 -32
- package/dist/projection/ProjectHarness.js.map +1 -1
- package/dist/projection/Projection.d.ts +2 -0
- package/dist/projection/Tools.d.ts +91 -0
- package/dist/projection/Tools.js +129 -0
- package/dist/projection/Tools.js.map +1 -0
- package/dist/resolver/AgentDefinition.d.ts +11 -0
- package/dist/resolver/AgentDefinition.js +91 -12
- package/dist/resolver/AgentDefinition.js.map +1 -1
- package/dist/resolver/Layer.d.ts +5 -2
- package/dist/resolver/Layer.js +47 -8
- package/dist/resolver/Layer.js.map +1 -1
- package/dist/resolver/ResolverContext.d.ts +1 -1
- package/dist/resolver/ResolverContext.js +1 -1
- package/dist/resolver/ResolverContext.js.map +1 -1
- package/dist/resolver/ResolverValidation.d.ts +12 -1
- package/dist/resolver/ResolverValidation.js +30 -20
- package/dist/resolver/ResolverValidation.js.map +1 -1
- package/dist/schemas/agent.schema.json +8 -2
- package/dist/schemas/settings.schema.json +1 -1
- package/dist/schemas/system-extension-hook.schema.json +38 -0
- package/dist/settings/Settings.d.ts +1 -1
- package/dist/settings/Settings.js +1 -1
- package/dist/settings/Settings.js.map +1 -1
- package/dist/settings/SettingsLoader.js.map +1 -1
- package/dist/setup/DefaultCatalog.d.ts +18 -0
- package/dist/setup/DefaultCatalog.js +74 -13
- package/dist/setup/DefaultCatalog.js.map +1 -1
- package/dist/sources/SourceCache.d.ts +20 -0
- package/dist/sources/SourceCache.js +31 -1
- package/dist/sources/SourceCache.js.map +1 -1
- package/dist/sources/TransitiveSources.d.ts +43 -0
- package/dist/sources/TransitiveSources.js +177 -0
- package/dist/sources/TransitiveSources.js.map +1 -0
- package/dist/system/SystemExtensionHook.d.ts +34 -0
- package/dist/system/SystemExtensionHook.js +190 -0
- package/dist/system/SystemExtensionHook.js.map +1 -0
- package/dist/validation/SchemaValidator.d.ts +1 -1
- package/dist/validation/SchemaValidator.js +2 -0
- package/dist/validation/SchemaValidator.js.map +1 -1
- package/docs/architecture/state_writeback_strategy.md +15 -3
- package/docs/documentation/README.md +15 -2
- package/docs/documentation/catalogs.md +61 -2
- package/docs/documentation/cli.md +2 -1
- package/docs/documentation/concepts.md +2 -2
- package/docs/documentation/containers.md +63 -14
- package/docs/documentation/hooks.md +33 -0
- package/docs/documentation/in-cluster.md +2 -0
- package/docs/documentation/migration.md +1 -1
- package/docs/documentation/personas.md +1 -1
- package/docs/documentation/settings.md +1 -1
- package/docs/documentation/state.md +27 -0
- package/docs/documentation/support-matrix.md +36 -23
- package/docs/documentation/usecases/org-onboarding-sdlc-report.md +143 -0
- package/docs/documentation/usecases/persona-reviews.md +1 -1
- package/docs/philosophy.md +20 -0
- package/package.json +1 -1
- package/src/schemas/agent.schema.json +8 -2
- package/src/schemas/settings.schema.json +1 -1
- package/src/schemas/system-extension-hook.schema.json +38 -0
|
@@ -11,6 +11,8 @@ The Link Operator runs Outfitter-composed agents inside a Kubernetes cluster. Th
|
|
|
11
11
|
|
|
12
12
|
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.
|
|
13
13
|
|
|
14
|
+
Because the operator does not look inside a Secret, the credentials a resident agent carries are the deployment's decision. A resident agent needs two forge tokens rather than one: the notification wake path accepts only a classic token, while its repository work should carry the narrowest credential available. [Give the agent a residence](../runbooks/give-the-agent-a-residence.md) is the procedure; [the forge credential model](../architecture/forge-credential-model.md) is the reasoning.
|
|
15
|
+
|
|
14
16
|
## Execution shapes
|
|
15
17
|
|
|
16
18
|
| Shape | Kubernetes resource | Trigger |
|
|
@@ -21,7 +21,7 @@ This page is the manual migration reference, and the bundled Outfitter skill can
|
|
|
21
21
|
| `<project>/.outfitter/local/settings.yml` (nested dir) | `<project>/.agents/settings.local.yml` (flat, gitignored) |
|
|
22
22
|
| `profile_sources` | `sources` supplying `.agents` payloads ([catalogs](./catalogs.md)) |
|
|
23
23
|
| `default_profile` | `default_agent` naming an agent slug |
|
|
24
|
-
| `outfitter run --profile <file-based id>` | `outfitter run <agent-id>` (choose the harness with `--harness pi\|claude`)
|
|
24
|
+
| `outfitter run --profile <file-based id>` | `outfitter run <agent-id>` (choose the harness with `--harness pi\|claude\|codex`) |
|
|
25
25
|
| `outfitter profile list` / `create` / `lint` | `outfitter list agents` / author files directly / `outfitter validate` |
|
|
26
26
|
| `profile_export` / `generated-system-prompt.md` | `outfitter dump` ([Dump and bake](./dump-and-bake.md)) |
|
|
27
27
|
| Free-form CI prompt + profile in `ai-outfitter/actions` | An agent run with structured inputs ([Actions](./actions.md)); the task/bake surface is a [future RFC](./tasks.md) |
|
|
@@ -32,7 +32,7 @@ Neither tier is a resource Outfitter resolves; both are ordinary directories of
|
|
|
32
32
|
|
|
33
33
|
## Three ways to consume the same file
|
|
34
34
|
|
|
35
|
-
- **Appended at launch**: `outfitter run persona-reviewer --append-prompt docs/personas/platform-lead.md -- …` — the direct run is the underlying interface, and the reviewer adopts the file as its identity for that session only. Pass `--append-prompt` rather than spelling the harness flag yourself after `--`: pi and Claude Code take append-prompt documents through different flags
|
|
35
|
+
- **Appended at launch**: `outfitter run persona-reviewer --append-prompt docs/personas/platform-lead.md -- …` — the direct run is the underlying interface, and the reviewer adopts the file as its identity for that session only. Pass `--append-prompt` rather than spelling the harness flag yourself after `--`: pi and Claude Code take append-prompt documents through different native flags. Codex has no native append flag yet, so its adapter warns that the document is dropped. An agent using the [`persona-review`](https://github.com/ai-outfitter/community-profiles/tree/main/skills/persona-review) skill can drive the same run in the background or synchronously and capture its report in a durable file. See [Persona reviews](./usecases/persona-reviews.md) for the runnable form of both supported identity projections.
|
|
36
36
|
- **Pasted into a web agent**: upload or paste the file unchanged into claude.ai project knowledge or a ChatGPT project as stakeholder context. Same artifact, zero conversion.
|
|
37
37
|
- **Ordinary reading context**: any agent doing product planning, research, or writing can read the file to know who the work is for.
|
|
38
38
|
|
|
@@ -22,7 +22,7 @@ In a standalone `.agents` repository the repository root is the tree, so the fil
|
|
|
22
22
|
```yaml
|
|
23
23
|
# .agents/settings.yml
|
|
24
24
|
default_agent: engineer # which agent runs by default
|
|
25
|
-
default_harness: pi # which harness to launch: pi or
|
|
25
|
+
default_harness: pi # which harness to launch: pi, claude, or codex
|
|
26
26
|
|
|
27
27
|
# Where protocol resources come from, beyond this tree and ~/.agents.
|
|
28
28
|
sources:
|
|
@@ -190,6 +190,33 @@ The last form is how a resident or in-cluster agent keeps continuity across rest
|
|
|
190
190
|
|
|
191
191
|
## Claude Code state paths
|
|
192
192
|
|
|
193
|
+
Claude credentials need a narrow adapter bridge in addition to the path-keyed state below. Claude
|
|
194
|
+
reads `.credentials.json` and `.claude.json` directly from `CLAUDE_CONFIG_DIR`; the ephemeral
|
|
195
|
+
projection gives `.credentials.json` no durable home, and `.claude.json`'s native location
|
|
196
|
+
(`~/.claude.json`, outside `~/.claude`) does not share its config-dir-relative path. Outfitter
|
|
197
|
+
seeds `.credentials.json` before launch. It seeds `oauthAccount` and `hasCompletedOnboarding` when
|
|
198
|
+
those keys exist in durable state. It also seeds the current working directory's accepted-trust bit
|
|
199
|
+
only when that exact trust decision already exists in durable state. Afterward it copies back the
|
|
200
|
+
whole `.credentials.json` when changed and atomically merges `oauthAccount`. If the durable
|
|
201
|
+
credentials also changed after seeding, Outfitter preserves that concurrent refresh and warns
|
|
202
|
+
instead of copying the projected credentials back. Claude MCP OAuth tokens
|
|
203
|
+
live under `mcpOAuth` in `.credentials.json`, keyed by `<serverName>|<hash>`, so server
|
|
204
|
+
authorizations acquired in an Outfitter-launched Claude session persist across runs through that
|
|
205
|
+
whole-file copy-back. Outfitter never copies the full machine-local `~/.claude.json` into a
|
|
206
|
+
projection or merges its other projected state back. Trust accepted inside an Outfitter session is
|
|
207
|
+
therefore discarded, so Claude prompts for trust on every run in a workspace that was never trusted
|
|
208
|
+
natively.
|
|
209
|
+
|
|
210
|
+
Claude session history has a second narrow bridge because `CLAUDE_CONFIG_DIR` also redirects
|
|
211
|
+
Claude's native `projects/` tree into the temporary projection. Before launch, Outfitter derives
|
|
212
|
+
Claude's project slug from the absolute working directory and copies only that slug directory from
|
|
213
|
+
`~/.claude/projects/`. This keeps other projects' transcripts out of the projection while making
|
|
214
|
+
`claude --continue` and `claude --resume` see earlier native or Outfitter-launched sessions. After
|
|
215
|
+
the run exits or throws, Outfitter merges every new or content-changed regular session file from
|
|
216
|
+
the projection's slug directories back into `~/.claude/projects/` atomically with mode `0600`.
|
|
217
|
+
Durable files are never deleted. A seed or copy-back failure emits a warning and does not replace
|
|
218
|
+
Claude's exit code or error.
|
|
219
|
+
|
|
193
220
|
The Claude Code adapter declares these paths:
|
|
194
221
|
|
|
195
222
|
```yaml
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Adapter support matrix
|
|
2
2
|
|
|
3
|
-
What Outfitter can project per agent CLI. Pi is the primary and most complete adapter; Claude Code
|
|
3
|
+
What Outfitter can project per agent CLI. Pi is the primary and most complete adapter; Claude Code and Codex CLI are supported with gaps.
|
|
4
4
|
|
|
5
5
|
Status values:
|
|
6
6
|
|
|
@@ -12,35 +12,47 @@ When a composition requests something an adapter cannot project, Outfitter warns
|
|
|
12
12
|
|
|
13
13
|
Tasks and bake are not in this matrix — they are the subject of a [separate upcoming RFC](./tasks.md).
|
|
14
14
|
|
|
15
|
-
| What Outfitter projects | Pi | Claude Code |
|
|
16
|
-
| ------------------------------------------------------------------------ | --------- | ----------- |
|
|
17
|
-
| Agent config directory | Supported | Supported |
|
|
18
|
-
| Session directory | Supported | Supported |
|
|
19
|
-
| Agent identity (`system-prompt.md`, `agents.md`, `agents/<id>/agent.md`) | Supported | Supported |
|
|
20
|
-
| Subagents (`agents/<id>` as harness delegates) | Supported | Supported |
|
|
21
|
-
| Skills (`skills/<id>`) | Supported | Partial |
|
|
22
|
-
| Commands (`commands/`) | Supported | Partial |
|
|
23
|
-
| Knowledge (`knowledge/`) | Supported | Partial |
|
|
24
|
-
| Model selection (`models.json`) | Supported | Partial |
|
|
25
|
-
| MCP servers (`mcp.json`) | Supported | Supported |
|
|
26
|
-
| Extensions (agent `extensions:` loadout) | Supported | Roadmap |
|
|
27
|
-
| Plugins (agent `plugins:` loadout) | Supported | Roadmap |
|
|
28
|
-
| Credentials and environment | Supported | Supported |
|
|
29
|
-
| DeepWork job selection | Supported | Roadmap |
|
|
30
|
-
| Hooks | Partial | Partial |
|
|
31
|
-
| Tool availability
|
|
32
|
-
| Theme / UI presentation | Roadmap | Roadmap |
|
|
33
|
-
| Working directory | Roadmap | Roadmap |
|
|
34
|
-
| Pass-through arguments | Supported | Supported |
|
|
35
|
-
| Bootstrap hook | Supported | Roadmap |
|
|
15
|
+
| What Outfitter projects | Pi | Claude Code | Codex CLI |
|
|
16
|
+
| ------------------------------------------------------------------------ | --------- | ----------- | --------- |
|
|
17
|
+
| Agent config directory | Supported | Supported | Roadmap |
|
|
18
|
+
| Session directory | Supported | Supported | Roadmap |
|
|
19
|
+
| Agent identity (`system-prompt.md`, `agents.md`, `agents/<id>/agent.md`) | Supported | Supported | Roadmap |
|
|
20
|
+
| Subagents (`agents/<id>` as harness delegates) | Supported | Supported | Roadmap |
|
|
21
|
+
| Skills (`skills/<id>`) | Supported | Partial | Roadmap |
|
|
22
|
+
| Commands (`commands/`) | Supported | Partial | Roadmap |
|
|
23
|
+
| Knowledge (`knowledge/`) | Supported | Partial | Roadmap |
|
|
24
|
+
| Model selection (`models.json`) | Supported | Partial | Partial |
|
|
25
|
+
| MCP servers (`mcp.json`) | Supported | Supported | Partial |
|
|
26
|
+
| Extensions (agent `extensions:` loadout) | Supported | Roadmap | Roadmap |
|
|
27
|
+
| Plugins (agent `plugins:` loadout) | Supported | Roadmap | Roadmap |
|
|
28
|
+
| Credentials and environment | Supported | Supported | Roadmap |
|
|
29
|
+
| DeepWork job selection | Supported | Roadmap | Roadmap |
|
|
30
|
+
| Hooks | Partial | Partial | Roadmap |
|
|
31
|
+
| Tool availability (agent `tools:` loadout) | Supported | Supported | Roadmap |
|
|
32
|
+
| Theme / UI presentation | Roadmap | Roadmap | Roadmap |
|
|
33
|
+
| Working directory | Roadmap | Roadmap | Roadmap |
|
|
34
|
+
| Pass-through arguments | Supported | Supported | Supported |
|
|
35
|
+
| Bootstrap hook | Supported | Roadmap | Roadmap |
|
|
36
|
+
|
|
37
|
+
## Codex CLI notes
|
|
38
|
+
|
|
39
|
+
- **Launch mode** — Outfitter launches `codex` directly. Pass-through arguments choose the native mode: no subcommand keeps the interactive CLI shape, while `-- exec ...` selects non-interactive `codex exec`.
|
|
40
|
+
- **Agent identity and appended prompts** — Codex has no native identity projection yet: launches drop the composed identity/system prompt and any `--append-prompt` documents, supplied documents produce a separate warning, and `--strict` aborts before execution.
|
|
41
|
+
- **Model selection (Partial)** — an agent's model maps to `-m`. Provider maps have no projection element and produce no warning. Thinking, tools, skills, subagents, extensions, plugins, and prompt templates remain unsupported and warn when selected.
|
|
42
|
+
- **MCP servers (Partial)** — selected stdio fields (`command`, `args`, `env`, `cwd`) and streamable HTTP fields (`url`, `headers`) become repeated TOML-valued `-c mcp_servers.<id>.<key>=...` overrides. Server ids must contain only letters, digits, `_`, or `-`; other ids cannot be expressed by Codex `-c` key paths and are skipped with a warning. Legacy SSE and other HTTP transport types are also skipped with a warning. User and project `config.toml` servers remain active because Codex has no strict MCP isolation mode, so every launch warns that projection is additive, even when no servers are selected.
|
|
43
|
+
- **Stdio environment safety** — `${ENV_NAME}` becomes an `env_vars` reference only when the stdio `env` key is also `ENV_NAME`; a reference that would rename the variable is dropped with a warning. Literal values pass through `env` and are visible in process arguments.
|
|
44
|
+
- **HTTP header safety** — `${ENV_NAME}` becomes an `env_http_headers` reference, while `Authorization: Bearer ${ENV_NAME}` becomes `bearer_token_env_var`. Other header values pass through `http_headers` and are visible in process arguments. Outfitter warns for every literal stdio environment or HTTP header entry exposed in argv, so use environment references for secrets.
|
|
36
45
|
|
|
37
46
|
## Claude Code notes
|
|
38
47
|
|
|
39
|
-
- **Config and session state** — Outfitter points `CLAUDE_CONFIG_DIR` at the baked composition, declares Claude state paths (`settings.json`, `agents/`, `skills/`, `commands/`, `plugins/`, `projects/`) for [state persistence](./state.md), and can [symlink a ported `~/.claude`](./porting-claude.md) so native use keeps working.
|
|
48
|
+
- **Config and session state** — Outfitter points `CLAUDE_CONFIG_DIR` at the baked composition. Before launch it copies only the current working directory's history from `~/.claude/projects/<project-slug>/` into the projection, so native `--continue` and `--resume` work without exposing other projects. After every successful or failed launch it atomically merges new or changed session files from every projected slug back into `~/.claude/projects/` with mode `0600`, never deleting durable history. Session bridge failures warn without masking the Claude exit. Outfitter also declares Claude state paths (`settings.json`, `agents/`, `skills/`, `commands/`, `plugins/`, `projects/`) for [state persistence](./state.md), and can [symlink a ported `~/.claude`](./porting-claude.md) so native use keeps working. MCP configuration from that port is no longer auto-discovered by Outfitter-launched Claude runs; those servers apply only when an agent selects them by slug. See the next bullet.
|
|
49
|
+
- **Credentials, onboarding, and workspace trust** — before launch, Outfitter copies `~/.claude/.credentials.json` to the temporary root as `.credentials.json` with mode `0600`. The projected `.claude.json` contains `oauthAccount` and `hasCompletedOnboarding` when those keys are present in durable `~/.claude.json`. It also contains `projects[<cwd>].hasTrustDialogAccepted: true` only when that exact accepted trust decision already exists there; other projects and unrelated machine state are not copied. After any successful or failed launch, a `.credentials.json` changed by the run is copied back wholesale and `oauthAccount` is atomically merged into durable `.claude.json` without replacing unrelated keys. If the durable credentials also changed after seeding, Outfitter preserves that concurrent refresh and warns instead of copying back. MCP OAuth tokens live under `mcpOAuth` in `.credentials.json`, keyed by `<serverName>|<hash>`, so authorizations acquired in an Outfitter-launched Claude session persist across runs. Other projected `.claude.json` state, including trust accepted during the session, is discarded; a workspace that has never been trusted by native Claude therefore prompts again on every run.
|
|
50
|
+
- **MCP servers** — every Claude launch passes the generated `mcp.json` through `--mcp-config` with `--strict-mcp-config`. MCP servers from user or project configuration, `.claude.json`, and plugins are therefore excluded; only servers selected by the composition are active.
|
|
40
51
|
- **Subagents** — selected `agents/<id>` definitions are materialized into Claude's native agents directory.
|
|
41
52
|
- **Skills (Partial)** — selected skills are materialized into the config directory's skills surface; remaining gaps are tracked per release. The bundled Outfitter skill ships through the plugin channel.
|
|
42
53
|
- **Model selection (Partial)** — model maps to `--model` and thinking level to `--effort`; provider selection is not projected for Claude and warns if requested.
|
|
43
54
|
- **Hooks (Partial)** — hook configuration is projected into the generated `settings.json`; there is no portable protocol hooks resource yet. See [Hooks](./hooks.md).
|
|
55
|
+
- **Tool availability** — `tools.allow` (after `tools.deny` removes entries) maps to both `--tools` (_availability_: an unlisted builtin is not in the session) and `--allowedTools` (_permission_: the granted tools are pre-approved, so a headless session is not stopped by a prompt); `tools.deny` always maps to `--disallowedTools`, including when both are declared, and a bare denied name removes the tool from context per Claude's docs. An allowlist that `tools.deny` empties maps to `--tools ""`, Claude's documented "disable all tools" form. Caveat: per the CLI reference, `--tools` governs the built-in set only — MCP tools (`mcp__server__*`) are unaffected and are governed by which MCP servers the loadout selects, so `--tools ""` is not exactly pi's zero-tool session when MCP servers are present. Claude's behavior here comes from `claude --help` and the CLI reference, not local measurement.
|
|
44
56
|
- **DeepWork jobs** — job selection is Pi-only today and warns on Claude.
|
|
45
57
|
- **Bundled Outfitter skill** — every launch also publishes Outfitter's own self-documentation skill as a bundled plugin, so the agent can explain Outfitter and this launch's configuration.
|
|
46
58
|
|
|
@@ -49,6 +61,7 @@ Tasks and bake are not in this matrix — they are the subject of a [separate up
|
|
|
49
61
|
- Pi projects the full resource set: agent identity, subagents (via the subagent extension), skills (`--skill`), commands, model configuration, MCP, extensions (`--extension`) and plugins as first-class loadout elements, environment, pass-through args, session directory, and DeepWork job selection.
|
|
50
62
|
- Selected skills resolve across layers following [layer precedence](./concepts.md#layer-precedence); `references`, `scripts`, and `assets` frontmatter materialize into a generated skill passed via `--skill`. `outfitter validate` checks selections and references before launch.
|
|
51
63
|
- **Hooks (Partial)** — bootstrap behavior uses an explicit Pi extension via `--extension`; recurring per-event hooks are extension territory. See [Hooks](./hooks.md).
|
|
64
|
+
- **Tool availability** — `tools.allow` (after `tools.deny` removes entries) maps to `--no-tools --tools a,b,c`, and `tools.deny` maps to `--exclude-tools a,b,c`. `--tools` is a hard allowlist across built-in, extension, and custom tools, so the session's tool set is exactly that list. An allowlist that `tools.deny` empties maps to `--no-tools` alone, a session with no tools at all. Note that `--no-builtin-tools` is deliberately not used: it keeps extension and custom tools enabled, so it does not express an empty tool set.
|
|
52
65
|
- Every launch also passes Outfitter's own self-documentation skill through `--skill`.
|
|
53
66
|
|
|
54
67
|
For the architecture-level definitions behind each row, see [Controllable elements](../architecture/controllable-elements.md).
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
# Onboard an organization with an SDLC report
|
|
2
|
+
|
|
3
|
+
A runbook for the first engineer who brings agentic engineering to their
|
|
4
|
+
organization. The output is two artifacts: a baseline **SDLC report** that
|
|
5
|
+
says where the org sits on the [adoption ramp](../../philosophy.md), and the
|
|
6
|
+
org's **`.agents` repository** with that report as its first commit. The
|
|
7
|
+
report's gaps become the backlog; the repository becomes the place the org's
|
|
8
|
+
agent configuration lives from day one.
|
|
9
|
+
|
|
10
|
+
Who runs this: an engineer with read access to the org's repositories. No
|
|
11
|
+
org-wide rollout, approval, or infrastructure is required, and no agent
|
|
12
|
+
session either — the scan is one command. The whole runbook is one person,
|
|
13
|
+
one sitting, read-only until you create the repository.
|
|
14
|
+
|
|
15
|
+
## 1. Prerequisites
|
|
16
|
+
|
|
17
|
+
- `npx` (node 20.19+) or Docker.
|
|
18
|
+
- An authenticated `gh` CLI with read access to the org.
|
|
19
|
+
- Optional but valuable: your existing local checkouts of org repositories.
|
|
20
|
+
The scanner reads them in addition to the forge API — local working trees
|
|
21
|
+
show practice the forge cannot see, such as `.agents/` trees in progress
|
|
22
|
+
and instruction files that were never committed.
|
|
23
|
+
|
|
24
|
+
## 2. Run the assessment
|
|
25
|
+
|
|
26
|
+
[`@ai-outfitter/link`](https://github.com/ai-outfitter/link) audits the org
|
|
27
|
+
against the catalog's governance baseline. Write the report straight into
|
|
28
|
+
the dated directory it will be committed from:
|
|
29
|
+
|
|
30
|
+
```sh
|
|
31
|
+
npx @ai-outfitter/link@1 report <org> \
|
|
32
|
+
--out ~/repos/<org>/.agents/reports/sdlc/$(date +%F)-initial
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Or with Docker, if you would rather not install anything:
|
|
36
|
+
|
|
37
|
+
```sh
|
|
38
|
+
docker run --rm -e GH_TOKEN="$(gh auth token)" -v "$PWD:/work" \
|
|
39
|
+
ghcr.io/ai-outfitter/link:1 report <org>
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Add your local checkouts as sources to widen the evidence — a single repo, an
|
|
43
|
+
owner folder of clones, or a whole `~/repos/` root:
|
|
44
|
+
|
|
45
|
+
```sh
|
|
46
|
+
npx @ai-outfitter/link@1 report <org> ~/repos/<org>
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
The scan is read-only: it lists repositories, reads git trees, and reads
|
|
50
|
+
effective branch rules. It never clones and never writes to the forge. It
|
|
51
|
+
samples at most the 30 most recently pushed repositories, and takes seconds
|
|
52
|
+
rather than minutes.
|
|
53
|
+
|
|
54
|
+
Naming a target scopes the report to it, so the file you are about to commit
|
|
55
|
+
into `<org>`'s repository describes `<org>` and nothing else.
|
|
56
|
+
|
|
57
|
+
You get one file, `report.json`, plus a copy in
|
|
58
|
+
`$XDG_DATA_HOME/outfitter-link/`. It contains, for each repository, a
|
|
59
|
+
maturity-ramp placement (level 0–5), the tree-derived signals behind it
|
|
60
|
+
(instruction files, `.agents/` trees, agent workflows, deploy manifests), and
|
|
61
|
+
a per-rule audit against the governance baseline. At org level it carries the
|
|
62
|
+
milestones that gate each rung, the `gaps` blocking the next one, and
|
|
63
|
+
`evidence_limits` — what the scan could not see, which bounds every claim in
|
|
64
|
+
it.
|
|
65
|
+
|
|
66
|
+
Read the `gaps` before moving on. They name what blocks the next rung, not
|
|
67
|
+
the top of the ramp.
|
|
68
|
+
|
|
69
|
+
To see the report rendered, with the workflow definitions beside it, clone
|
|
70
|
+
the repository and run `link web`.
|
|
71
|
+
|
|
72
|
+
### What the scan does not measure
|
|
73
|
+
|
|
74
|
+
The scanner decides everything from file trees and branch rules, so it is
|
|
75
|
+
fast, free, and reproducible — two runs of the same org agree apart from the
|
|
76
|
+
`generated_at` and `scanned_at` timestamps, which is what makes report diffs
|
|
77
|
+
a progress measure. The cost is that it reads no pull request history and
|
|
78
|
+
makes no judgments: no cycle time, no rework rate, no inventory of which
|
|
79
|
+
harnesses and model vendors are actually in use, and no duplication analysis
|
|
80
|
+
across teams.
|
|
81
|
+
|
|
82
|
+
When you want those, run the `sdlc-report` skill on a local coding harness as
|
|
83
|
+
a second, deeper pass. It answers the same question with an agent's judgment
|
|
84
|
+
instead of a checker's rules, and it emits recommendations. Start with
|
|
85
|
+
`link` — it is the cheap, repeatable baseline, and it is the one you will
|
|
86
|
+
re-run.
|
|
87
|
+
|
|
88
|
+
## 3. Create the org `.agents` repository
|
|
89
|
+
|
|
90
|
+
Create `<org>/.agents` on your forge and commit the report as its first
|
|
91
|
+
content. Repository hygiene, learned the hard way:
|
|
92
|
+
|
|
93
|
+
- The repository MUST NOT be public — private or internal visibility only.
|
|
94
|
+
The report is an honest map of your org's gaps. (This organization
|
|
95
|
+
publishes its own report deliberately, as a worked example. That is a
|
|
96
|
+
choice about a reference; it is not the default.)
|
|
97
|
+
- If the repository already exists, commit only the report files. Leave any
|
|
98
|
+
uncommitted work in the checkout untouched, and if the default branch is
|
|
99
|
+
behind or checked out elsewhere, say so rather than silently moving it.
|
|
100
|
+
|
|
101
|
+
```text
|
|
102
|
+
<org>/.agents/
|
|
103
|
+
README.md # what this repo is; link to the report
|
|
104
|
+
reports/
|
|
105
|
+
sdlc/
|
|
106
|
+
YYYY-MM-DD-initial/
|
|
107
|
+
report.json
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
The initial report is the baseline: re-run the scan after each change (a
|
|
111
|
+
quarterly cadence works, or after each rung climb) into a new dated
|
|
112
|
+
directory, and the diff between reports is your progress measure — milestones
|
|
113
|
+
met and rung movements, not anecdotes.
|
|
114
|
+
|
|
115
|
+
This repository is also where the org's shared agent configuration grows: an
|
|
116
|
+
`agents.md` with shared operating rules, role agents, skills, and a pinned
|
|
117
|
+
`settings.yml`, following the [organization catalog](./organization-profile-catalog.md)
|
|
118
|
+
conventions. Starting it with the report means the catalog's first commit
|
|
119
|
+
explains _why_ the org is adopting agents and what it will measure — every
|
|
120
|
+
later addition traces back to a gap in the baseline.
|
|
121
|
+
|
|
122
|
+
## 4. Act on the report
|
|
123
|
+
|
|
124
|
+
1. Take the first entry in `gaps` and automate that one workflow end to end —
|
|
125
|
+
for example, feature idea → reviewed PR ([Actions](../actions.md),
|
|
126
|
+
[in-cluster](../in-cluster.md)).
|
|
127
|
+
2. Add the shared resources the org lacks, so the next team composes instead
|
|
128
|
+
of rebuilding. A repo whose `signals.catalog` is false is a candidate.
|
|
129
|
+
3. Wire session-log capture into the automated workflow before merge. The
|
|
130
|
+
`session-capture` milestone is unmet in almost every first report, and it
|
|
131
|
+
stays unmeasurable until workflows upload session artifacts behind a
|
|
132
|
+
required check. Owning that record is what makes the next report richer,
|
|
133
|
+
and it is the raw material for evals and improvement
|
|
134
|
+
([philosophy](../../philosophy.md)).
|
|
135
|
+
4. Schedule the re-run ([recurring runs](../recurring-runs.md)) and commit
|
|
136
|
+
each new report beside the baseline.
|
|
137
|
+
|
|
138
|
+
## Boundaries
|
|
139
|
+
|
|
140
|
+
The scan is read-only; creating the `.agents` repository in step 3 is the
|
|
141
|
+
runbook's first write, done by you deliberately. The report contains repo
|
|
142
|
+
names, paths, and counts, never credentials or session content. Treat it as
|
|
143
|
+
internal: it is an honest map of your org's gaps.
|
|
@@ -91,7 +91,7 @@ outfitter run persona-reviewer --append-prompt docs/personas/platform-lead.md --
|
|
|
91
91
|
> docs/persona-reviews/platform-lead-onboarding.md
|
|
92
92
|
```
|
|
93
93
|
|
|
94
|
-
This is the portable interface: it works from the project containing the persona, does not assume a particular catalog checkout path, and
|
|
94
|
+
This is the portable interface for pi and Claude Code: it works from the project containing the persona, does not assume a particular catalog checkout path, and projects `--append-prompt` through the native flag each harness reads. The Codex adapter has no native append flag and warns that the document is dropped. Repeat the option to compose an identity from several documents; see [When one file is not enough](../personas.md#when-one-file-is-not-enough). One shared agent adopts the file as its identity for that session only and writes a first-person, sourced report — evidence cited to the exact page or UI moment, assumptions labeled. The reviewer inherits the caller's configured model; reviews benefit from a strong reasoning model.
|
|
95
95
|
|
|
96
96
|
### Optional orchestration with the skill
|
|
97
97
|
|
package/docs/philosophy.md
CHANGED
|
@@ -2,6 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
Make, share, and switch the agent profiles your coding agents use — manually or programmatically. A profile is just an agent and the loadout it composes; there is no separate profile format.
|
|
4
4
|
|
|
5
|
+
## Trust through evidence
|
|
6
|
+
|
|
7
|
+
An agent is trusted the same way a new teammate is: small scopes, reviewed work, and a paper trail. Outfitter treats all three as configuration. A profile bounds what an agent can do per environment — the planning agent that has write tools at your desk has none in the cluster. Adversarial review is a workflow step rather than a virtue, and workflows are built so that every transition writes to the record.
|
|
8
|
+
|
|
9
|
+
## Own your session data
|
|
10
|
+
|
|
11
|
+
The session record — what was asked, what the agent did, what it touched, what the review found — serves you as much as it serves the auditor. It answers "what happened and was it allowed" for an audit, and the same records are the inputs to evals, policy tuning, and eventually training. Organizations that let session data evaporate at the end of each run discard the asset that makes the whole system improvable. Store clean records first and decide on dashboards later — dashboards can always be built over clean records; records cannot be reconstructed from dashboards.
|
|
12
|
+
|
|
5
13
|
## Expeditious agents
|
|
6
14
|
|
|
7
15
|
An agent is defined by its agency: its ability to make good decisions on the way to completing a task. Outfitter exists to make agents _expeditious_ — not just effective, but fast.
|
|
@@ -23,3 +31,15 @@ The same mechanism scales up a stair-step:
|
|
|
23
31
|
- **Enterprises** publish and pin curated catalogs, keeping agent configuration reviewable, versioned, and consistent across the organization.
|
|
24
32
|
|
|
25
33
|
At every level the goal is the same: the right profile, at the right moment, with nothing extra along for the ride.
|
|
34
|
+
|
|
35
|
+
## The ramp to an autonomous lifecycle
|
|
36
|
+
|
|
37
|
+
Outfitter's destination is a fully autonomous software development lifecycle: humans define goals and acceptance gates, agents own the middle. Nobody jumps there in one step. Adoption is a ramp with five rungs, and each Outfitter component targets a rung, so a user or an organization climbs without discarding the previous rung. This section is the canonical definition; the org README and the `sdlc-report` assessment skill compress or extend it.
|
|
38
|
+
|
|
39
|
+
1. **Assisted** — autocomplete and chat; a human's hands stay on the keyboard.
|
|
40
|
+
2. **Delegated** — a local agent does the task; the human defines the idea and reviews the PR.
|
|
41
|
+
3. **Automated** — a workflow runs without a laptop: an issue, a message, or a schedule triggers agents in CI or a cluster, and adversarial review is part of the pipeline.
|
|
42
|
+
4. **Governed** — the organization shares one pinned catalog of agents, skills, and policy; every agent action lands in an auditable record; resident agents work as onboarded teammates.
|
|
43
|
+
5. **Self-improving** — the audit record feeds evals and model improvement; humans set goals and acceptance gates, agents own the middle.
|
|
44
|
+
|
|
45
|
+
Two rules keep the climb honest. Never automate a workflow you have not first done manually — run it as an agent-assisted skill until you understand it, then promote it. And expand scope by moving the human locus of control outward one layer at a time: first the implementation, then the review, then the idea, until what remains human is the goal and the gate.
|
package/package.json
CHANGED
|
@@ -56,14 +56,20 @@
|
|
|
56
56
|
"tools": {
|
|
57
57
|
"type": "object",
|
|
58
58
|
"properties": {
|
|
59
|
-
"allow": { "type": "array", "items": { "
|
|
60
|
-
"deny": { "type": "array", "items": { "
|
|
59
|
+
"allow": { "type": "array", "items": { "$ref": "#/$defs/toolName" } },
|
|
60
|
+
"deny": { "type": "array", "items": { "$ref": "#/$defs/toolName" } }
|
|
61
61
|
},
|
|
62
62
|
"additionalProperties": false
|
|
63
63
|
}
|
|
64
64
|
},
|
|
65
65
|
"additionalProperties": true,
|
|
66
66
|
"$defs": {
|
|
67
|
+
"toolName": {
|
|
68
|
+
"type": "string",
|
|
69
|
+
"minLength": 1,
|
|
70
|
+
"pattern": "^[^\\s,-][^\\s,]*$",
|
|
71
|
+
"description": "A tool name. A leading '-' would become an independent harness flag when projected, and a comma or whitespace would split the name inside a projected flag value, so all three are rejected."
|
|
72
|
+
},
|
|
67
73
|
"slugList": {
|
|
68
74
|
"type": "array",
|
|
69
75
|
"items": { "type": "string", "minLength": 1 }
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"type": "object",
|
|
6
6
|
"properties": {
|
|
7
7
|
"default_agent": { "type": "string", "minLength": 1 },
|
|
8
|
-
"default_harness": { "enum": ["pi", "claude"] },
|
|
8
|
+
"default_harness": { "enum": ["pi", "claude", "codex"] },
|
|
9
9
|
"cache_directory": { "type": "string", "minLength": 1 },
|
|
10
10
|
"state_persistence": {
|
|
11
11
|
"type": "object",
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://outfitter.dev/schemas/system-extension-hook.schema.json",
|
|
4
|
+
"title": "Outfitter system extension hook",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"required": ["name", "harnesses"],
|
|
7
|
+
"properties": {
|
|
8
|
+
"name": { "type": "string", "minLength": 1 },
|
|
9
|
+
"harnesses": {
|
|
10
|
+
"type": "object",
|
|
11
|
+
"minProperties": 1,
|
|
12
|
+
"properties": {
|
|
13
|
+
"pi": { "$ref": "#/$defs/harnessHook" },
|
|
14
|
+
"claude": { "$ref": "#/$defs/harnessHook" },
|
|
15
|
+
"codex": { "$ref": "#/$defs/harnessHook" }
|
|
16
|
+
},
|
|
17
|
+
"additionalProperties": false
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"additionalProperties": false,
|
|
21
|
+
"$defs": {
|
|
22
|
+
"harnessHook": {
|
|
23
|
+
"type": "object",
|
|
24
|
+
"properties": {
|
|
25
|
+
"extensions": {
|
|
26
|
+
"type": "array",
|
|
27
|
+
"items": { "type": "string", "pattern": "^/" }
|
|
28
|
+
},
|
|
29
|
+
"env": {
|
|
30
|
+
"type": "object",
|
|
31
|
+
"propertyNames": { "pattern": "^[A-Za-z_][A-Za-z0-9_]*$" },
|
|
32
|
+
"additionalProperties": { "type": "string" }
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
"additionalProperties": false
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|