@ai-outfitter/outfitter 0.6.1 → 0.7.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/LICENSE.md +20 -50
- package/README.md +36 -280
- package/code/enterprise/LICENSE +35 -0
- package/code/enterprise/README.md +5 -0
- package/dist/agents/AdapterProfileControls.d.ts +2 -2
- package/dist/agents/AdapterProfileControls.js +8 -1
- package/dist/agents/AdapterProfileControls.js.map +1 -1
- package/dist/agents/AgentAdapter.d.ts +10 -0
- package/dist/agents/AgentLaunch.d.ts +6 -0
- package/dist/agents/AgentLaunch.js +89 -0
- package/dist/agents/AgentLaunch.js.map +1 -0
- package/dist/agents/claude/ClaudeAdapter.js +18 -3
- package/dist/agents/claude/ClaudeAdapter.js.map +1 -1
- package/dist/agents/pi/PiAdapter.js +154 -14
- package/dist/agents/pi/PiAdapter.js.map +1 -1
- package/dist/cli/commands/PiLoginLaunch.d.ts +8 -2
- package/dist/cli/commands/PiLoginLaunch.js +726 -75
- package/dist/cli/commands/PiLoginLaunch.js.map +1 -1
- package/dist/cli/commands/RunCommand.d.ts +20 -3
- package/dist/cli/commands/RunCommand.js +102 -20
- package/dist/cli/commands/RunCommand.js.map +1 -1
- package/dist/cli/commands/SetupCommand.d.ts +11 -2
- package/dist/cli/commands/SetupCommand.js +266 -52
- package/dist/cli/commands/SetupCommand.js.map +1 -1
- package/dist/cli/commands/SyncCommand.d.ts +8 -1
- package/dist/cli/commands/SyncCommand.js +2 -1
- package/dist/cli/commands/SyncCommand.js.map +1 -1
- package/dist/cli/commands/WelcomeCommand.js +1 -1
- package/dist/cli/commands/WelcomeCommand.js.map +1 -1
- package/dist/cli/commands/assets/outfitter-ascii.txt +5 -0
- package/dist/cli/commands/profile/Command.d.ts +1 -0
- package/dist/cli/commands/profile/Command.js +3 -0
- package/dist/cli/commands/profile/Command.js.map +1 -1
- package/dist/cli/commands/profile/LintCommand.d.ts +19 -0
- package/dist/cli/commands/profile/LintCommand.js +123 -0
- package/dist/cli/commands/profile/LintCommand.js.map +1 -0
- package/dist/cli.js +8 -2
- package/dist/cli.js.map +1 -1
- package/dist/merge/ArrayMergePolicy.js.map +1 -1
- package/dist/merge/SettingsValueMerger.js.map +1 -1
- package/dist/profiles/Profile.d.ts +13 -1
- package/dist/profiles/Profile.js.map +1 -1
- package/dist/profiles/ProfileLoader.d.ts +4 -0
- package/dist/profiles/ProfileLoader.js +117 -17
- package/dist/profiles/ProfileLoader.js.map +1 -1
- package/dist/profiles/ProfileMerger.js +3 -0
- package/dist/profiles/ProfileMerger.js.map +1 -1
- package/dist/profiles/PromptIncludes.d.ts +32 -0
- package/dist/profiles/PromptIncludes.js +147 -0
- package/dist/profiles/PromptIncludes.js.map +1 -0
- package/dist/prompts/SystemPromptExport.d.ts +16 -0
- package/dist/prompts/SystemPromptExport.js +81 -0
- package/dist/prompts/SystemPromptExport.js.map +1 -0
- package/dist/schemas/profile.schema.json +37 -2
- package/dist/schemas/settings.schema.json +12 -0
- package/dist/settings/Settings.d.ts +5 -0
- package/dist/settings/Settings.js.map +1 -1
- package/dist/settings/SettingsLoader.js +3 -0
- package/dist/settings/SettingsLoader.js.map +1 -1
- package/dist/settings/SettingsMerger.js +8 -0
- package/dist/settings/SettingsMerger.js.map +1 -1
- package/package.json +8 -11
- package/src/schemas/profile.schema.json +37 -2
- package/src/schemas/settings.schema.json +12 -0
- package/doc/.deepreview +0 -30
- package/doc/architecture.md +0 -856
- package/doc/controllable-elements.md +0 -162
- package/doc/file_structure.md +0 -141
- package/doc/integration_test_system.md +0 -214
- package/doc/specs/validating_requirements_with_rules.md +0 -55
- package/doc/state_writeback_strategy.md +0 -342
- package/requirements/OFTR-001-project-foundation.md +0 -53
- package/requirements/OFTR-002-settings.md +0 -65
- package/requirements/OFTR-003-profiles.md +0 -60
- package/requirements/OFTR-004-sync-and-setup.md +0 -67
- package/requirements/OFTR-005-run-and-composite-profile.md +0 -60
- package/requirements/OFTR-006-agent-adapters.md +0 -66
- package/requirements/OFTR-007-controllable-elements.md +0 -32
- package/requirements/OFTR-008-requirements-governance.md +0 -42
- package/requirements/OFTR-009-release-publishing.md +0 -35
- package/requirements/OFTR-010-onboarding-welcome.md +0 -48
|
@@ -1,162 +0,0 @@
|
|
|
1
|
-
# Controllable Elements
|
|
2
|
-
|
|
3
|
-
This document defines cross-agent-CLI concepts that Outfitter profiles may control.
|
|
4
|
-
Pi is the first supported CLI, and Claude Code is supported as an additional adapter.
|
|
5
|
-
Other CLIs may be added later while keeping the profile model generic.
|
|
6
|
-
|
|
7
|
-
Status values:
|
|
8
|
-
|
|
9
|
-
- **Supported**: Outfitter supports this control for the CLI.
|
|
10
|
-
- **Roadmap**: the CLI appears to support this concept, but Outfitter does not support it yet.
|
|
11
|
-
- **Unsupported**: the agent CLI cannot meaningfully support the concept or no known native mechanism exists.
|
|
12
|
-
|
|
13
|
-
## How to Read This Matrix
|
|
14
|
-
|
|
15
|
-
A `Supported` entry means Outfitter can control that concept for the agent CLI through at least one native mechanism: a config-directory boundary, state-path placement, generated files, environment variables, command-line flags, or pass-through arguments.
|
|
16
|
-
It does not always mean there is a one-to-one native CLI flag or that every generic profile selector has been mapped.
|
|
17
|
-
|
|
18
|
-
For example, Claude Code session/project state lives under Claude's config home rather than a standalone `--session-dir` flag.
|
|
19
|
-
Outfitter supports that session-directory concept for Claude by setting `CLAUDE_CONFIG_DIR` to the composite profile root, declaring Claude `projects/` state for persistence, and allowing `controls.session_directory` or `controls.claude.session_directory` to choose where that state is symlinked from.
|
|
20
|
-
Likewise, Claude skills and commands are supported as native directories under the profiled `CLAUDE_CONFIG_DIR`, even though the generic `controls.skills` and `controls.prompt_template` selectors are not yet translated into Claude-specific selection flags.
|
|
21
|
-
|
|
22
|
-
## Defined Terms
|
|
23
|
-
|
|
24
|
-
### Agent Config Directory
|
|
25
|
-
|
|
26
|
-
The root directory that stores agent-global configuration, credentials, installed resources, and related state.
|
|
27
|
-
|
|
28
|
-
- Pi name: `PI_CODING_AGENT_DIR` / agent dir
|
|
29
|
-
- Claude name: `CLAUDE_CONFIG_DIR` / Claude config home
|
|
30
|
-
|
|
31
|
-
### Session Directory
|
|
32
|
-
|
|
33
|
-
The directory where conversation sessions, transcripts, or run state are stored.
|
|
34
|
-
|
|
35
|
-
- Pi name: `PI_CODING_AGENT_SESSION_DIR` / `--session-dir`
|
|
36
|
-
- Claude name: session/project state under `CLAUDE_CONFIG_DIR`, including `projects/` state managed by Outfitter state persistence
|
|
37
|
-
|
|
38
|
-
### Extensions
|
|
39
|
-
|
|
40
|
-
Executable/plugin modules that add tools, providers, hooks, or runtime behavior.
|
|
41
|
-
|
|
42
|
-
- Pi name: extensions, `--extension` / `-e`
|
|
43
|
-
- Claude name: plugins via `--plugin-dir`
|
|
44
|
-
|
|
45
|
-
### Skills
|
|
46
|
-
|
|
47
|
-
Reusable task instructions, workflows, or resource bundles exposed to the agent.
|
|
48
|
-
|
|
49
|
-
- Pi name: skills, `--skill`
|
|
50
|
-
- Claude name: skills under the Claude config directory; Outfitter can profile native Claude skills through `cli_specific/claude/skills`, but generic `skills` selection is not mapped yet
|
|
51
|
-
|
|
52
|
-
### Prompt Templates
|
|
53
|
-
|
|
54
|
-
Named reusable prompts/templates available to the agent runtime.
|
|
55
|
-
|
|
56
|
-
- Pi name: prompt templates, `--prompt-template`
|
|
57
|
-
- Claude name: commands/prompts under the Claude config directory; Outfitter can profile native Claude commands through `cli_specific/claude/commands`, but generic `prompt_template` selection is not mapped yet
|
|
58
|
-
|
|
59
|
-
### System Prompt
|
|
60
|
-
|
|
61
|
-
The primary instruction text supplied to the agent.
|
|
62
|
-
|
|
63
|
-
- Pi name: `--system-prompt`, `SYSTEM.md`
|
|
64
|
-
- Claude name: `--system-prompt`
|
|
65
|
-
|
|
66
|
-
### Appended System Prompt
|
|
67
|
-
|
|
68
|
-
Additional instruction text layered onto the primary system prompt.
|
|
69
|
-
|
|
70
|
-
- Pi name: `--append-system-prompt`, `APPEND_SYSTEM.md`
|
|
71
|
-
- Claude name: `--append-system-prompt`
|
|
72
|
-
|
|
73
|
-
### Model Selection
|
|
74
|
-
|
|
75
|
-
The selected provider/model and related inference options.
|
|
76
|
-
|
|
77
|
-
- Pi name: `--provider`, `--model`, `--models`, `--thinking`
|
|
78
|
-
- Claude name: `--model`, `--effort`
|
|
79
|
-
|
|
80
|
-
### Credentials and Environment
|
|
81
|
-
|
|
82
|
-
Environment variables, API keys, auth files, and related secret material needed by providers or tools.
|
|
83
|
-
|
|
84
|
-
- Pi name: provider env vars, `auth.json`, `--api-key`
|
|
85
|
-
- Claude name: environment variables and config files under `CLAUDE_CONFIG_DIR`
|
|
86
|
-
|
|
87
|
-
### Tool Availability
|
|
88
|
-
|
|
89
|
-
Configuration that enables, disables, or filters tools exposed to the agent.
|
|
90
|
-
|
|
91
|
-
- Pi name: tool settings and extension-provided tools
|
|
92
|
-
- Claude name: allowed/disallowed tools, roadmap adapter mapping
|
|
93
|
-
|
|
94
|
-
### Context Files
|
|
95
|
-
|
|
96
|
-
Project or profile files automatically loaded into context.
|
|
97
|
-
|
|
98
|
-
- Pi name: context files, `--no-context-files`
|
|
99
|
-
- Claude name: project memory/context files, roadmap adapter mapping
|
|
100
|
-
|
|
101
|
-
### Theme / UI Presentation
|
|
102
|
-
|
|
103
|
-
Terminal UI theme and presentation settings.
|
|
104
|
-
|
|
105
|
-
- Pi name: themes, `--theme`, `--no-themes`
|
|
106
|
-
- Claude name: UI/theme controls, roadmap adapter mapping
|
|
107
|
-
|
|
108
|
-
### Project Override Policy
|
|
109
|
-
|
|
110
|
-
Whether project-local agent configuration is allowed, ignored, or constrained.
|
|
111
|
-
|
|
112
|
-
- Pi name: project `.pi/` resources and settings
|
|
113
|
-
- Claude name: project-local config, roadmap adapter mapping
|
|
114
|
-
|
|
115
|
-
### Working Directory
|
|
116
|
-
|
|
117
|
-
The directory from which the inner agent CLI is launched.
|
|
118
|
-
|
|
119
|
-
- Pi name: cwd/session cwd
|
|
120
|
-
- Claude name: cwd/project directory
|
|
121
|
-
|
|
122
|
-
### Pass-through Arguments
|
|
123
|
-
|
|
124
|
-
Arguments not recognized by Outfitter that are forwarded unmodified to the inner agent CLI.
|
|
125
|
-
|
|
126
|
-
- Pi name: native pi CLI args
|
|
127
|
-
- Claude name: native Claude CLI args
|
|
128
|
-
|
|
129
|
-
### Bootstrap Hook
|
|
130
|
-
|
|
131
|
-
An early-startup customization used to register providers, tools, hooks, or additional runtime behavior.
|
|
132
|
-
|
|
133
|
-
- Pi name: explicit bootstrap extension via `--extension` / `-e`
|
|
134
|
-
- Claude name: startup hook/plugin mechanism, not mapped by Outfitter yet
|
|
135
|
-
|
|
136
|
-
## Support Matrix
|
|
137
|
-
|
|
138
|
-
| Controllable Element | Pi | Claude |
|
|
139
|
-
| --------------------------- | --------- | --------- |
|
|
140
|
-
| Agent Config Directory | Supported | Supported |
|
|
141
|
-
| Session Directory | Supported | Supported |
|
|
142
|
-
| Extensions | Supported | Supported |
|
|
143
|
-
| Skills | Supported | Supported |
|
|
144
|
-
| Prompt Templates | Supported | Supported |
|
|
145
|
-
| System Prompt | Supported | Supported |
|
|
146
|
-
| Appended System Prompt | Supported | Supported |
|
|
147
|
-
| Model Selection | Supported | Supported |
|
|
148
|
-
| Credentials and Environment | Supported | Supported |
|
|
149
|
-
| Tool Availability | Roadmap | Roadmap |
|
|
150
|
-
| Context Files | Roadmap | Roadmap |
|
|
151
|
-
| Theme / UI Presentation | Roadmap | Roadmap |
|
|
152
|
-
| Project Override Policy | Roadmap | Roadmap |
|
|
153
|
-
| Working Directory | Roadmap | Roadmap |
|
|
154
|
-
| Pass-through Arguments | Supported | Supported |
|
|
155
|
-
| Bootstrap Hook | Supported | Roadmap |
|
|
156
|
-
|
|
157
|
-
## Day-One Interpretation
|
|
158
|
-
|
|
159
|
-
For v1, a Outfitter profile may describe all defined terms generically.
|
|
160
|
-
The Pi adapter is the first implementation, and pi remains the default adapter.
|
|
161
|
-
Adapter-specific overrides live under `controls.pi` and `controls.claude`; unsupported controls warn at runtime, and `--strict` makes those warnings fatal.
|
|
162
|
-
For Claude Code, `skills/` and `commands/` are supported as native configuration directories inside the profiled `CLAUDE_CONFIG_DIR`; the generic `controls.skills` and `controls.prompt_template` selectors remain unmapped and warn if requested.
|
package/doc/file_structure.md
DELETED
|
@@ -1,141 +0,0 @@
|
|
|
1
|
-
# Outfitter File Structure
|
|
2
|
-
|
|
3
|
-
This document records the key repository file and directory structure used by Outfitter.
|
|
4
|
-
See `doc/architecture.md` for runtime file conventions such as `.outfitter` settings folders, profile folders, and generated composite profile directories.
|
|
5
|
-
|
|
6
|
-
## Repository Layout
|
|
7
|
-
|
|
8
|
-
Outfitter is organized around clear TypeScript source boundaries, requirement documents, and scenario-based tests.
|
|
9
|
-
|
|
10
|
-
```text
|
|
11
|
-
. # repository root
|
|
12
|
-
├── .deepreview # root DeepWork review rules for project-wide checks
|
|
13
|
-
├── .dockerignore # container build context exclusions
|
|
14
|
-
├── Dockerfile # local and release Outfitter container image definition
|
|
15
|
-
├── .deepwork/ # DeepWork schemas and generated review instruction scratch files
|
|
16
|
-
│ └── schemas/ # project-specific DeepSchema definitions
|
|
17
|
-
├── .github/ # GitHub automation configuration
|
|
18
|
-
│ └── workflows/ # GitHub Actions workflows and local .deepreview rules
|
|
19
|
-
├── doc/ # architecture, design, and specification docs
|
|
20
|
-
│ ├── .deepreview # documentation-specific DeepWork review rules
|
|
21
|
-
│ ├── architecture.md # architectural rationale and runtime file conventions
|
|
22
|
-
│ ├── controllable-elements.md # controllable element terminology and support matrix
|
|
23
|
-
│ ├── file_structure.md # repository file structure overview
|
|
24
|
-
│ ├── integration_test_system.md # fixture-backed integration test design
|
|
25
|
-
│ ├── state_writeback_strategy.md # composite profile state persistence and writeback design
|
|
26
|
-
│ └── specs/ # detailed supporting specs
|
|
27
|
-
├── doc_site/ # Nextra/Next.js documentation website
|
|
28
|
-
│ ├── app/ # App Router pages, layout, and site styles
|
|
29
|
-
│ ├── eslint.config.js # documentation site ESLint configuration
|
|
30
|
-
│ ├── mdx-components.tsx # Nextra MDX component bridge
|
|
31
|
-
│ ├── next.config.mjs # Next.js configuration wrapped by Nextra
|
|
32
|
-
│ ├── package.json # documentation site package scripts and dependencies
|
|
33
|
-
│ └── tsconfig.json # documentation site TypeScript configuration
|
|
34
|
-
├── requirements/ # formal OUTFITTER requirement documents
|
|
35
|
-
│ ├── OFTR-001-project-foundation.md
|
|
36
|
-
│ └── ...
|
|
37
|
-
├── .prettierignore # Prettier ignore rules
|
|
38
|
-
├── .prettierrc.json # Prettier formatting configuration
|
|
39
|
-
├── .snapperrc.toml # Snapper Markdown formatting configuration
|
|
40
|
-
├── CONTRIBUTING.md # local install and contributor workflow guide
|
|
41
|
-
├── bin/ # local executable development helpers
|
|
42
|
-
│ ├── dev-container-setup # clean container helper for setup smoke tests
|
|
43
|
-
│ ├── dev-setup-source # local build helper for real setup-source targets
|
|
44
|
-
│ └── dev-tmp-home # isolated temporary HOME launch helper
|
|
45
|
-
├── src/ # production TypeScript source
|
|
46
|
-
│ ├── cli.ts # executable CLI entry point
|
|
47
|
-
│ ├── cli/ # CLI parser construction and command registration
|
|
48
|
-
│ │ ├── OutfitterCli.ts
|
|
49
|
-
│ │ └── commands/ # command objects for non-trivial CLI behavior
|
|
50
|
-
│ │ ├── CommandObject.ts
|
|
51
|
-
│ │ ├── FirstRunWelcomeProfile.ts
|
|
52
|
-
│ │ ├── PiLoginLaunch.ts
|
|
53
|
-
│ │ ├── RunCommand.ts
|
|
54
|
-
│ │ ├── SetupCommand.ts
|
|
55
|
-
│ │ ├── SyncCommand.ts
|
|
56
|
-
│ │ ├── WelcomeCommand.ts
|
|
57
|
-
│ │ └── profile/ # profile command namespace and subcommands
|
|
58
|
-
│ │ ├── Command.ts
|
|
59
|
-
│ │ ├── CreateCommand.ts
|
|
60
|
-
│ │ ├── ListCommand.ts
|
|
61
|
-
│ │ └── Shared.ts
|
|
62
|
-
│ ├── settings/ # settings loading and merging
|
|
63
|
-
│ │ ├── Settings.ts
|
|
64
|
-
│ │ ├── SettingsLoader.ts
|
|
65
|
-
│ │ └── SettingsMerger.ts
|
|
66
|
-
│ ├── profiles/ # profile loading, validation, resolution, and merging
|
|
67
|
-
│ │ ├── Profile.ts
|
|
68
|
-
│ │ ├── ProfileCache.ts
|
|
69
|
-
│ │ ├── ProfileLoader.ts
|
|
70
|
-
│ │ ├── ProfileMerger.ts
|
|
71
|
-
│ │ └── ProfileSource.ts
|
|
72
|
-
│ ├── merge/ # reusable deterministic value and array merge policy helpers
|
|
73
|
-
│ │ ├── ArrayMergePolicy.ts
|
|
74
|
-
│ │ └── SettingsValueMerger.ts
|
|
75
|
-
│ ├── compositeProfile/ # generated runtime composite profile assembly and watching
|
|
76
|
-
│ │ ├── CompositeProfile.ts
|
|
77
|
-
│ │ ├── CompositeProfileAssembler.ts
|
|
78
|
-
│ │ ├── CompositeProfileFile.ts
|
|
79
|
-
│ │ ├── CompositeProfileTemplate.ts
|
|
80
|
-
│ │ ├── CompositeProfileWatcher.ts
|
|
81
|
-
│ │ └── StatePersistence.ts
|
|
82
|
-
│ ├── agents/ # agent adapter boundary and CLI-specific adapters
|
|
83
|
-
│ │ ├── AdapterProfileControls.ts
|
|
84
|
-
│ │ ├── AdapterStatePaths.ts
|
|
85
|
-
│ │ ├── AgentAdapter.ts
|
|
86
|
-
│ │ ├── AgentRegistry.ts
|
|
87
|
-
│ │ ├── LaunchResources.ts
|
|
88
|
-
│ │ ├── ResourceIdentity.ts
|
|
89
|
-
│ │ ├── pi/ # pi-specific adapter implementation
|
|
90
|
-
│ │ │ ├── PiAdapter.ts
|
|
91
|
-
│ │ │ ├── PiMcpConfig.ts
|
|
92
|
-
│ │ │ ├── PiSettingsMergePolicy.ts
|
|
93
|
-
│ │ │ └── PiCompositeProfileWriter.ts
|
|
94
|
-
│ │ └── claude/ # Claude Code-specific adapter implementation
|
|
95
|
-
│ │ ├── ClaudeAdapter.ts
|
|
96
|
-
│ │ └── ClaudeCompositeProfileWriter.ts
|
|
97
|
-
│ ├── schemas/ # JSON Schema artifacts for persisted formats
|
|
98
|
-
│ │ ├── settings.schema.json
|
|
99
|
-
│ │ ├── profile.schema.json
|
|
100
|
-
│ │ ├── profile-source.schema.json
|
|
101
|
-
│ │ └── SchemaDocument.ts
|
|
102
|
-
│ └── validation/ # shared validation helpers
|
|
103
|
-
│ ├── SchemaValidator.ts
|
|
104
|
-
│ └── YamlDocument.ts
|
|
105
|
-
├── scripts/ # local development and formatting helper scripts
|
|
106
|
-
│ ├── .deepreview # script-specific DeepWork review rules
|
|
107
|
-
│ └── run-snapper.mjs # pinned Snapper binary downloader/runner
|
|
108
|
-
├── skills/ # Pi package skills published with Outfitter
|
|
109
|
-
│ └── outfitter/ # default /outfitter setup guidance skill
|
|
110
|
-
│ └── SKILL.md
|
|
111
|
-
├── tests/ # automated tests
|
|
112
|
-
│ ├── fixtures/ # reusable test fixtures
|
|
113
|
-
│ │ ├── integration/ # fixture-backed integration scenarios, catalog, and local .deepreview
|
|
114
|
-
│ │ └── scenarios/ # compact profile-resolution scenarios and expected outputs
|
|
115
|
-
│ ├── integration/ # fixture-backed integration tests and harness helpers
|
|
116
|
-
│ ├── setup.ts # Vitest global setup for quiet test-output guards
|
|
117
|
-
│ ├── test-console.ts # shared console-output guard helpers for tests
|
|
118
|
-
│ └── unit/ # unit tests grouped by functionality under test, including welcome and first-run tests
|
|
119
|
-
├── package-lock.json # locked npm dependency graph
|
|
120
|
-
└── package.json # npm package metadata and scripts
|
|
121
|
-
```
|
|
122
|
-
|
|
123
|
-
The exact layout may evolve, but these boundaries should stay recognizable.
|
|
124
|
-
|
|
125
|
-
## Test Fixtures
|
|
126
|
-
|
|
127
|
-
Integration fixtures should live under `tests/fixtures/integration/` with full `home/`, `project/`, and optional `expected/` trees.
|
|
128
|
-
Fixture-backed integration tests and shared harness helpers should live under `tests/integration/`.
|
|
129
|
-
|
|
130
|
-
Scenario fixtures should live under `tests/fixtures/scenarios/`, for example:
|
|
131
|
-
|
|
132
|
-
```text
|
|
133
|
-
tests/fixtures/scenarios/
|
|
134
|
-
profile-cycle/
|
|
135
|
-
profile-inheritance-chain/
|
|
136
|
-
profile-missing-inheritance/
|
|
137
|
-
profile-multiple-inheritance/
|
|
138
|
-
profile-precedence/
|
|
139
|
-
```
|
|
140
|
-
|
|
141
|
-
Each scenario should include realistic `.outfitter` folders and expected resolution output.
|
|
@@ -1,214 +0,0 @@
|
|
|
1
|
-
# Integration Test System
|
|
2
|
-
|
|
3
|
-
## Purpose
|
|
4
|
-
|
|
5
|
-
Outfitter uses fixture-backed integration tests to exercise real settings/profile directory trees rather than constructing every input inside individual tests.
|
|
6
|
-
This is especially important for composite profile generation and state persistence because the effective runtime composite profile can be composed from multiple settings files, multiple profile sources, inherited profiles, adapter defaults, and CLI-specific profile state files.
|
|
7
|
-
|
|
8
|
-
The core risk is that a generated composite profile can look correct in isolated unit tests while write-back/state-persistence behavior remains ambiguous or unsafe when the composite profile came from four or more durable sources.
|
|
9
|
-
Integration fixtures make those source relationships visible and testable.
|
|
10
|
-
|
|
11
|
-
## Goals
|
|
12
|
-
|
|
13
|
-
- Store realistic, pre-written Outfitter projects as fixture directories.
|
|
14
|
-
- Copy each fixture into a temporary directory before the test mutates it.
|
|
15
|
-
- Traverse fixtures through the same public loading, resolution, composite profile assembly, and run/write detection paths used by commands.
|
|
16
|
-
- Assert the resulting composite profile shape, symlinks, generated files, argv/env launch plan, warnings, and durable write results.
|
|
17
|
-
- Make source ownership explicit enough that tests prove Outfitter does not perform unsupported generic write-back into composed settings/profile inputs.
|
|
18
|
-
- Keep fixtures reusable across tests and documented in the integration fixture catalog.
|
|
19
|
-
|
|
20
|
-
## Non-goals
|
|
21
|
-
|
|
22
|
-
- Integration tests do not replace focused unit tests for schema validation, merge algorithms, adapter helpers, or path-safety checks.
|
|
23
|
-
- Outfitter does not implement generic structured merge-back from generated composite profile files into settings or profiles.
|
|
24
|
-
- Integration tests do not require real pi or Claude Code binaries.
|
|
25
|
-
Tests inject fake launchers that read/write the composite profile.
|
|
26
|
-
- Integration tests do not depend on the developer machine's real home directory, native CLI config, or network state.
|
|
27
|
-
|
|
28
|
-
## Repository layout
|
|
29
|
-
|
|
30
|
-
```text
|
|
31
|
-
tests/
|
|
32
|
-
integration/
|
|
33
|
-
composite profile-generation.test.ts
|
|
34
|
-
fixtureHarness.ts
|
|
35
|
-
fixtures/
|
|
36
|
-
integration/
|
|
37
|
-
README.md
|
|
38
|
-
trivial_repo_only_profile/
|
|
39
|
-
README.md
|
|
40
|
-
home/
|
|
41
|
-
.outfitter/settings.yml
|
|
42
|
-
.outfitter/profiles/default/profile.yml
|
|
43
|
-
project/
|
|
44
|
-
.outfitter/settings.yml
|
|
45
|
-
.outfitter/profiles/repo-review/profile.yml
|
|
46
|
-
expected/
|
|
47
|
-
pi/
|
|
48
|
-
composite profile-summary.json
|
|
49
|
-
warnings.json
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
The existing `tests/fixtures/scenarios/` directory contains small profile-resolution fixtures used by current unit tests.
|
|
53
|
-
The integration framework does not replace or move those fixtures.
|
|
54
|
-
End-to-end fixtures live in `tests/fixtures/integration/` because they model full home/project/cache/native trees and expected composite profile effects.
|
|
55
|
-
When an existing scenario is useful for an integration test, copy or expand it into a new integration fixture instead of changing the existing unit-test fixture in place.
|
|
56
|
-
|
|
57
|
-
Additional fixture-set PRs target this framework branch and add more directories under `tests/fixtures/integration/`.
|
|
58
|
-
|
|
59
|
-
## Fixture directory contract
|
|
60
|
-
|
|
61
|
-
Each integration fixture is a complete synthetic filesystem tree.
|
|
62
|
-
A fixture uses these top-level entries:
|
|
63
|
-
|
|
64
|
-
| Path | Purpose |
|
|
65
|
-
| ----------- | ------------------------------------------------------------------------------------------------------------ |
|
|
66
|
-
| `README.md` | Human explanation of the scenario and the behavior it protects. |
|
|
67
|
-
| `home/` | Synthetic user home directory passed to command execution. |
|
|
68
|
-
| `project/` | Synthetic project directory passed to command execution. |
|
|
69
|
-
| `expected/` | Expected composite profile summaries, symlink targets, warnings, launch args/env, and durable file contents. |
|
|
70
|
-
|
|
71
|
-
A fixture may also include these top-level entries:
|
|
72
|
-
|
|
73
|
-
| Path | Purpose |
|
|
74
|
-
| --------- | ----------------------------------------------------------------------------------------------- |
|
|
75
|
-
| `native/` | Explicit native CLI state tree for tests that map adapter fallbacks away from `home/`. |
|
|
76
|
-
| `cache/` | Pre-seeded Outfitter cache, remote-profile cache, or adapter cache/tooling state when required. |
|
|
77
|
-
|
|
78
|
-
Settings and profiles inside `home/` and `project/` use normal Outfitter paths such as `.outfitter/settings.yml`, `.outfitter/local/settings.yml`, and `.outfitter/profiles/<id>/profile.yml`.
|
|
79
|
-
CLI-specific state lives under profile folders, for example `cli_specific/pi/settings.json` or `cli_specific/claude/settings.json`.
|
|
80
|
-
Fixture names describe the user/project scenario rather than the adapter; adapter-specific expected output is nested under `expected/pi/`, `expected/claude/`, and similar directories.
|
|
81
|
-
|
|
82
|
-
## Harness responsibilities
|
|
83
|
-
|
|
84
|
-
`tests/integration/fixtureHarness.ts` exports these helpers:
|
|
85
|
-
|
|
86
|
-
- `copyFixtureToTemp(name)` copies `tests/fixtures/integration/<name>` into `mkdtemp` and returns an `IntegrationFixture` with `root`, `home`, `project`, `cache`, and `expected` paths.
|
|
87
|
-
- `runFixture(fixture, options)` executes `executeRunCommand` with the copied home/project and the provided fake launcher.
|
|
88
|
-
- `summarizePiComposite profile(fixture, composite profileRoot)` returns stable pi-specific facts about generated profile content and selected state symlinks.
|
|
89
|
-
- `readExpectedJson(fixture, relativePath)` loads expected fixture output from the copied `expected/` tree.
|
|
90
|
-
- `readFixtureText(fixture, relativePath)` reads a text file from the copied fixture root.
|
|
91
|
-
- `cleanupIntegrationFixtures()` removes copied fixtures after each test.
|
|
92
|
-
|
|
93
|
-
The harness normalizes absolute paths in expected output using tokens such as `<fixture>`, `<home>`, `<project>`, `<cache>`, and `<composite profile>`.
|
|
94
|
-
This keeps expected files readable and independent of temporary directory names.
|
|
95
|
-
|
|
96
|
-
## Where mutations and assertions live
|
|
97
|
-
|
|
98
|
-
The framework uses a split model:
|
|
99
|
-
|
|
100
|
-
- **Fixture files encode inputs and expected stable outputs.
|
|
101
|
-
** The fixture directory contains settings, profiles, CLI-specific state files, and optional `expected/*.json` snapshots such as expected symlink targets, warnings, or final durable file contents.
|
|
102
|
-
- **Test code encodes behavior.
|
|
103
|
-
** The Vitest test case chooses which fixture to run, defines the fake launcher's mutation script, and performs assertions against the copied fixture and any expected files.
|
|
104
|
-
|
|
105
|
-
This keeps fixtures readable as normal Outfitter directory trees while keeping active behavior in TypeScript where it can use filesystem APIs, helper functions, and precise assertions.
|
|
106
|
-
Do not hide executable test behavior in ad hoc YAML unless a future mutation-script format is deliberately added.
|
|
107
|
-
|
|
108
|
-
For example:
|
|
109
|
-
|
|
110
|
-
```ts
|
|
111
|
-
it('does not copy generated composed settings back to source layers', async () => {
|
|
112
|
-
const fixture = copyFixtureToTemp('heavily_overridden_engineering');
|
|
113
|
-
|
|
114
|
-
const result = await runFixture(fixture, {
|
|
115
|
-
launcher(plan) {
|
|
116
|
-
const composite profileRoot = composite profileRootFromLaunchPlan(plan);
|
|
117
|
-
writeFileSync(join(composite profileRoot, 'outfitter', 'profile.json'), '{"mutated":true}\n');
|
|
118
|
-
writeFileSync(join(composite profileRoot, 'unexpected.txt'), 'unknown write\n');
|
|
119
|
-
return Promise.resolve(0);
|
|
120
|
-
},
|
|
121
|
-
});
|
|
122
|
-
|
|
123
|
-
expect(result.warnings).toEqual(readExpectedJson(fixture, 'warnings.json'));
|
|
124
|
-
expect(readFileSync(join(fixture.project, '.outfitter/settings.yml'), 'utf8')).toBe(
|
|
125
|
-
readExpectedText(fixture, 'source-project-settings-after.yml'),
|
|
126
|
-
);
|
|
127
|
-
});
|
|
128
|
-
```
|
|
129
|
-
|
|
130
|
-
A fixture can include optional expectation files like:
|
|
131
|
-
|
|
132
|
-
```text
|
|
133
|
-
expected/
|
|
134
|
-
composite profile-summary.json
|
|
135
|
-
warnings.json
|
|
136
|
-
durable-files-after.json
|
|
137
|
-
source-project-settings-after.yml
|
|
138
|
-
```
|
|
139
|
-
|
|
140
|
-
The test decides how much to snapshot.
|
|
141
|
-
Use structured expected files for broad composite profile summaries and explicit inline assertions for the key write-back invariant the test protects.
|
|
142
|
-
|
|
143
|
-
## Test flow
|
|
144
|
-
|
|
145
|
-
A typical integration test:
|
|
146
|
-
|
|
147
|
-
1. Copies a named fixture to a temporary directory.
|
|
148
|
-
2. Runs Outfitter command code with the copied `homeDirectory` and `projectDirectory`.
|
|
149
|
-
3. Uses a fake launcher defined in the Vitest test to inspect the composite profile while it exists.
|
|
150
|
-
4. Mutates declared or undeclared composite profile paths from that fake launcher when the scenario requires it.
|
|
151
|
-
5. Lets normal post-run state detection classify the mutations.
|
|
152
|
-
6. Asserts warnings/errors and durable source files after the command completes, using fixture `expected/` files where snapshots improve readability.
|
|
153
|
-
|
|
154
|
-
Example fake-launcher responsibilities:
|
|
155
|
-
|
|
156
|
-
```text
|
|
157
|
-
- Read the adapter config root from launch plan env, such as `PI_CODING_AGENT_DIR` or `CLAUDE_CONFIG_DIR`.
|
|
158
|
-
- Assert generated composite profile files exist.
|
|
159
|
-
- Assert declared persistent paths are symlinks to the expected profile/native/cache sources.
|
|
160
|
-
- Write to declared state paths and unknown files according to the scenario.
|
|
161
|
-
- Return exit code 0 unless the scenario is testing child failure handling.
|
|
162
|
-
```
|
|
163
|
-
|
|
164
|
-
## Composite profile assertions
|
|
165
|
-
|
|
166
|
-
Integration tests assert stable behavior, not incidental implementation details.
|
|
167
|
-
Useful composite profile assertions include:
|
|
168
|
-
|
|
169
|
-
- selected adapter and profile id;
|
|
170
|
-
- resolved profile stack order;
|
|
171
|
-
- generated Outfitter metadata files;
|
|
172
|
-
- generated adapter-specific files such as profile/settings payloads;
|
|
173
|
-
- launch argv and environment;
|
|
174
|
-
- symlink versus temporary materialization for each declared state path;
|
|
175
|
-
- symlink target precedence: project-local profile, project profile, user profile, cache, then native fallback as applicable;
|
|
176
|
-
- non-persistent baseline paths and detected writes;
|
|
177
|
-
- warnings becoming fatal under `--strict`.
|
|
178
|
-
|
|
179
|
-
## Write-back/state-persistence focus
|
|
180
|
-
|
|
181
|
-
The integration suite encodes the product rule from `doc/state_writeback_strategy.md`: Outfitter does not do generic post-run copy-back or structured merge-back.
|
|
182
|
-
Durable writes happen only through declared state paths that have a persistent strategy, normally by symlink.
|
|
183
|
-
|
|
184
|
-
Important cases:
|
|
185
|
-
|
|
186
|
-
- A generated composite profile file composed from several settings/profile layers is mutated in the composite profile.
|
|
187
|
-
Current behavior is explicit: the mutation is not generically copied back to any source layer unless that path is an adapter-declared symlink.
|
|
188
|
-
- A state file supplied by a high-precedence profile is symlinked and receives writes directly.
|
|
189
|
-
- A declared state path configured as `warn` or `error` is not persisted.
|
|
190
|
-
- Unknown files written into the composite profile are classified by the adapter's `unknown` strategy and never silently persisted.
|
|
191
|
-
- Cache-backed adapter paths, such as Pi `utilities/` and `bin/`, persist to the configured cache rather than to profile directories.
|
|
192
|
-
|
|
193
|
-
## Fixture authoring rules
|
|
194
|
-
|
|
195
|
-
- Prefer realistic fixtures with one clear user/project story.
|
|
196
|
-
- Name fixtures after that story, such as `trivial_repo_only_profile` or `heavily_overridden_engineering`, rather than after an adapter.
|
|
197
|
-
- Include enough settings/profile layers to demonstrate precedence when the scenario is about merging.
|
|
198
|
-
- Use obvious values such as `REMOTE_ONLY`, `USER_ONLY`, `REPO_ONLY`, `LOCAL_ONLY`, and `SHARED` so failed assertions identify the wrong layer immediately.
|
|
199
|
-
- Keep expected output as JSON when possible so tests can diff structured facts.
|
|
200
|
-
- Avoid timestamps, random IDs, host-specific paths, and real credentials.
|
|
201
|
-
- Include a fixture-root `README.md` for every fixture set.
|
|
202
|
-
|
|
203
|
-
## Extension path
|
|
204
|
-
|
|
205
|
-
The framework currently includes `trivial_repo_only_profile` as the first implemented fixture.
|
|
206
|
-
Additional fixture-set PRs add the remaining cataloged scenarios under `tests/fixtures/integration/` and extend `tests/integration/composite profile-generation.test.ts` or add focused integration test files when needed.
|
|
207
|
-
|
|
208
|
-
When adding or changing a fixture:
|
|
209
|
-
|
|
210
|
-
1. Add or update the fixture root `README.md` in the same change.
|
|
211
|
-
2. Add static fixture files under `home/`, `project/`, optional `cache/` or `native/`, and optional `expected/`.
|
|
212
|
-
3. Add a Vitest integration test that copies the fixture, runs through command code, and asserts the composite profile/write-back behavior.
|
|
213
|
-
4. Update `tests/fixtures/integration/INTEGRATION_TEST_FIXTURES.md` when the fixture's scenario, status, or purpose changes.
|
|
214
|
-
5. Run `npm run check-ci` before opening or updating the PR.
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
## Validating Requirements with Tests, DeepSchemas, and Review Rules
|
|
2
|
-
|
|
3
|
-
Formal requirements use RFC 2119 keywords such as MUST, SHOULD, and MAY.
|
|
4
|
-
Each requirement needs an appropriate validation mechanism.
|
|
5
|
-
|
|
6
|
-
### Use automated TypeScript tests for deterministic requirements
|
|
7
|
-
|
|
8
|
-
Use tests when a requirement can be checked by exact values, paths, return values, emitted CLI arguments, or structured data.
|
|
9
|
-
|
|
10
|
-
Examples:
|
|
11
|
-
|
|
12
|
-
- `PI_CODING_AGENT_DIR` MUST be set to the selected profile directory → assert the generated launch environment contains that exact value.
|
|
13
|
-
- A profile name MUST be rejected when it contains whitespace → assert validation returns an error.
|
|
14
|
-
- The wrapper MUST pass `--extension` for configured bootstrap extensions → assert generated argv contains the expected flag and path.
|
|
15
|
-
|
|
16
|
-
### Use DeepSchemas for file-level contracts
|
|
17
|
-
|
|
18
|
-
Use DeepSchemas when a file must satisfy structural or semantic constraints.
|
|
19
|
-
|
|
20
|
-
- Named DeepSchemas are useful for classes of files, such as all requirement specs.
|
|
21
|
-
- Anonymous DeepSchemas are useful when a rule governs one specific file.
|
|
22
|
-
- Put exact structural checks in JSON Schema when the target file is structured data.
|
|
23
|
-
- Put semantic RFC 2119 requirements in the DeepSchema `requirements` section when judgment is required.
|
|
24
|
-
|
|
25
|
-
### Use `.deepreview` rules for broad judgment-based policies
|
|
26
|
-
|
|
27
|
-
Use DeepReview rules when the reviewer must compare changed files, requirements, tests, documentation, or conventions across multiple files.
|
|
28
|
-
|
|
29
|
-
Examples:
|
|
30
|
-
|
|
31
|
-
- Requirement files MUST follow the project requirement format.
|
|
32
|
-
- Tests that claim requirement coverage MUST use durable traceability comments.
|
|
33
|
-
- Documentation MUST stay consistent with TypeScript source behavior.
|
|
34
|
-
|
|
35
|
-
### Anti-patterns
|
|
36
|
-
|
|
37
|
-
Do not use fragile keyword tests for judgment requirements.
|
|
38
|
-
A test such as `expect(text).toContain("safe")` does not prove that a prompt or policy meaningfully enforces safety.
|
|
39
|
-
|
|
40
|
-
Do not spend reviewer judgment on facts that TypeScript tests or JSON Schema can verify exactly.
|
|
41
|
-
|
|
42
|
-
### Test traceability comment format
|
|
43
|
-
|
|
44
|
-
Tests that validate a formal requirement should use a durable comment immediately before the relevant `it(...)`, `test(...)`, or `describe(...)` block:
|
|
45
|
-
|
|
46
|
-
```ts
|
|
47
|
-
// THIS TEST VALIDATES A HARD REQUIREMENT (OFTR-008.3).
|
|
48
|
-
// YOU MUST NOT MODIFY THIS TEST UNLESS THE REQUIREMENT CHANGES.
|
|
49
|
-
it('rejects stale requirement traceability comments', () => {
|
|
50
|
-
// ...
|
|
51
|
-
});
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
Comments should explain durable policy intent.
|
|
55
|
-
They should not reference source line numbers, pull request numbers, or one-time migration context.
|