@ai-outfitter/outfitter 0.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 (156) hide show
  1. package/LICENSE.md +58 -0
  2. package/README.md +256 -0
  3. package/dist/agents/AdapterProfileControls.d.ts +20 -0
  4. package/dist/agents/AdapterProfileControls.js +63 -0
  5. package/dist/agents/AdapterProfileControls.js.map +1 -0
  6. package/dist/agents/AdapterStatePaths.d.ts +12 -0
  7. package/dist/agents/AdapterStatePaths.js +44 -0
  8. package/dist/agents/AdapterStatePaths.js.map +1 -0
  9. package/dist/agents/AgentAdapter.d.ts +32 -0
  10. package/dist/agents/AgentAdapter.js +2 -0
  11. package/dist/agents/AgentAdapter.js.map +1 -0
  12. package/dist/agents/AgentRegistry.d.ts +6 -0
  13. package/dist/agents/AgentRegistry.js +17 -0
  14. package/dist/agents/AgentRegistry.js.map +1 -0
  15. package/dist/agents/LaunchResources.d.ts +13 -0
  16. package/dist/agents/LaunchResources.js +35 -0
  17. package/dist/agents/LaunchResources.js.map +1 -0
  18. package/dist/agents/ResourceIdentity.d.ts +2 -0
  19. package/dist/agents/ResourceIdentity.js +51 -0
  20. package/dist/agents/ResourceIdentity.js.map +1 -0
  21. package/dist/agents/claude/ClaudeAdapter.d.ts +2 -0
  22. package/dist/agents/claude/ClaudeAdapter.js +117 -0
  23. package/dist/agents/claude/ClaudeAdapter.js.map +1 -0
  24. package/dist/agents/claude/ClaudeCompositeProfileWriter.d.ts +5 -0
  25. package/dist/agents/claude/ClaudeCompositeProfileWriter.js +7 -0
  26. package/dist/agents/claude/ClaudeCompositeProfileWriter.js.map +1 -0
  27. package/dist/agents/pi/PiAdapter.d.ts +2 -0
  28. package/dist/agents/pi/PiAdapter.js +229 -0
  29. package/dist/agents/pi/PiAdapter.js.map +1 -0
  30. package/dist/agents/pi/PiCompositeProfileWriter.d.ts +5 -0
  31. package/dist/agents/pi/PiCompositeProfileWriter.js +7 -0
  32. package/dist/agents/pi/PiCompositeProfileWriter.js.map +1 -0
  33. package/dist/agents/pi/PiMcpConfig.d.ts +2 -0
  34. package/dist/agents/pi/PiMcpConfig.js +114 -0
  35. package/dist/agents/pi/PiMcpConfig.js.map +1 -0
  36. package/dist/agents/pi/PiSettingsMergePolicy.d.ts +17 -0
  37. package/dist/agents/pi/PiSettingsMergePolicy.js +59 -0
  38. package/dist/agents/pi/PiSettingsMergePolicy.js.map +1 -0
  39. package/dist/cli/OutfitterCli.d.ts +4 -0
  40. package/dist/cli/OutfitterCli.js +32 -0
  41. package/dist/cli/OutfitterCli.js.map +1 -0
  42. package/dist/cli/commands/CommandObject.d.ts +11 -0
  43. package/dist/cli/commands/CommandObject.js +5 -0
  44. package/dist/cli/commands/CommandObject.js.map +1 -0
  45. package/dist/cli/commands/FirstRunWelcomeProfile.d.ts +11 -0
  46. package/dist/cli/commands/FirstRunWelcomeProfile.js +107 -0
  47. package/dist/cli/commands/FirstRunWelcomeProfile.js.map +1 -0
  48. package/dist/cli/commands/PiLoginLaunch.d.ts +10 -0
  49. package/dist/cli/commands/PiLoginLaunch.js +76 -0
  50. package/dist/cli/commands/PiLoginLaunch.js.map +1 -0
  51. package/dist/cli/commands/RunCommand.d.ts +30 -0
  52. package/dist/cli/commands/RunCommand.js +299 -0
  53. package/dist/cli/commands/RunCommand.js.map +1 -0
  54. package/dist/cli/commands/SetupCommand.d.ts +34 -0
  55. package/dist/cli/commands/SetupCommand.js +379 -0
  56. package/dist/cli/commands/SetupCommand.js.map +1 -0
  57. package/dist/cli/commands/SyncCommand.d.ts +28 -0
  58. package/dist/cli/commands/SyncCommand.js +178 -0
  59. package/dist/cli/commands/SyncCommand.js.map +1 -0
  60. package/dist/cli/commands/WelcomeCommand.d.ts +54 -0
  61. package/dist/cli/commands/WelcomeCommand.js +214 -0
  62. package/dist/cli/commands/WelcomeCommand.js.map +1 -0
  63. package/dist/cli/commands/profile/Command.d.ts +6 -0
  64. package/dist/cli/commands/profile/Command.js +21 -0
  65. package/dist/cli/commands/profile/Command.js.map +1 -0
  66. package/dist/cli/commands/profile/CreateCommand.d.ts +19 -0
  67. package/dist/cli/commands/profile/CreateCommand.js +115 -0
  68. package/dist/cli/commands/profile/CreateCommand.js.map +1 -0
  69. package/dist/cli/commands/profile/ListCommand.d.ts +17 -0
  70. package/dist/cli/commands/profile/ListCommand.js +85 -0
  71. package/dist/cli/commands/profile/ListCommand.js.map +1 -0
  72. package/dist/cli/commands/profile/Shared.d.ts +9 -0
  73. package/dist/cli/commands/profile/Shared.js +10 -0
  74. package/dist/cli/commands/profile/Shared.js.map +1 -0
  75. package/dist/cli.d.ts +3 -0
  76. package/dist/cli.js +22 -0
  77. package/dist/cli.js.map +1 -0
  78. package/dist/compositeProfile/CompositeProfile.d.ts +8 -0
  79. package/dist/compositeProfile/CompositeProfile.js +6 -0
  80. package/dist/compositeProfile/CompositeProfile.js.map +1 -0
  81. package/dist/compositeProfile/CompositeProfileAssembler.d.ts +12 -0
  82. package/dist/compositeProfile/CompositeProfileAssembler.js +32 -0
  83. package/dist/compositeProfile/CompositeProfileAssembler.js.map +1 -0
  84. package/dist/compositeProfile/CompositeProfileFile.d.ts +16 -0
  85. package/dist/compositeProfile/CompositeProfileFile.js +16 -0
  86. package/dist/compositeProfile/CompositeProfileFile.js.map +1 -0
  87. package/dist/compositeProfile/CompositeProfileTemplate.d.ts +15 -0
  88. package/dist/compositeProfile/CompositeProfileTemplate.js +65 -0
  89. package/dist/compositeProfile/CompositeProfileTemplate.js.map +1 -0
  90. package/dist/compositeProfile/CompositeProfileWatcher.d.ts +18 -0
  91. package/dist/compositeProfile/CompositeProfileWatcher.js +46 -0
  92. package/dist/compositeProfile/CompositeProfileWatcher.js.map +1 -0
  93. package/dist/compositeProfile/StatePersistence.d.ts +24 -0
  94. package/dist/compositeProfile/StatePersistence.js +224 -0
  95. package/dist/compositeProfile/StatePersistence.js.map +1 -0
  96. package/dist/merge/ArrayMergePolicy.d.ts +8 -0
  97. package/dist/merge/ArrayMergePolicy.js +45 -0
  98. package/dist/merge/ArrayMergePolicy.js.map +1 -0
  99. package/dist/merge/SettingsValueMerger.d.ts +11 -0
  100. package/dist/merge/SettingsValueMerger.js +34 -0
  101. package/dist/merge/SettingsValueMerger.js.map +1 -0
  102. package/dist/profiles/Profile.d.ts +32 -0
  103. package/dist/profiles/Profile.js +7 -0
  104. package/dist/profiles/Profile.js.map +1 -0
  105. package/dist/profiles/ProfileCache.d.ts +8 -0
  106. package/dist/profiles/ProfileCache.js +36 -0
  107. package/dist/profiles/ProfileCache.js.map +1 -0
  108. package/dist/profiles/ProfileLoader.d.ts +24 -0
  109. package/dist/profiles/ProfileLoader.js +169 -0
  110. package/dist/profiles/ProfileLoader.js.map +1 -0
  111. package/dist/profiles/ProfileMerger.d.ts +20 -0
  112. package/dist/profiles/ProfileMerger.js +97 -0
  113. package/dist/profiles/ProfileMerger.js.map +1 -0
  114. package/dist/profiles/ProfileSource.d.ts +35 -0
  115. package/dist/profiles/ProfileSource.js +13 -0
  116. package/dist/profiles/ProfileSource.js.map +1 -0
  117. package/dist/schemas/profile-source.schema.json +29 -0
  118. package/dist/schemas/profile.schema.json +115 -0
  119. package/dist/schemas/settings.schema.json +37 -0
  120. package/dist/settings/Settings.d.ts +17 -0
  121. package/dist/settings/Settings.js +5 -0
  122. package/dist/settings/Settings.js.map +1 -0
  123. package/dist/settings/SettingsLoader.d.ts +33 -0
  124. package/dist/settings/SettingsLoader.js +129 -0
  125. package/dist/settings/SettingsLoader.js.map +1 -0
  126. package/dist/settings/SettingsMerger.d.ts +2 -0
  127. package/dist/settings/SettingsMerger.js +31 -0
  128. package/dist/settings/SettingsMerger.js.map +1 -0
  129. package/dist/validation/SchemaValidator.d.ts +11 -0
  130. package/dist/validation/SchemaValidator.js +36 -0
  131. package/dist/validation/SchemaValidator.js.map +1 -0
  132. package/dist/validation/YamlDocument.d.ts +13 -0
  133. package/dist/validation/YamlDocument.js +11 -0
  134. package/dist/validation/YamlDocument.js.map +1 -0
  135. package/doc/.deepreview +30 -0
  136. package/doc/architecture.md +834 -0
  137. package/doc/controllable-elements.md +162 -0
  138. package/doc/file_structure.md +133 -0
  139. package/doc/integration_test_system.md +214 -0
  140. package/doc/specs/validating_requirements_with_rules.md +55 -0
  141. package/doc/state_writeback_strategy.md +334 -0
  142. package/package.json +73 -0
  143. package/requirements/OFTR-001-project-foundation.md +53 -0
  144. package/requirements/OFTR-002-settings.md +65 -0
  145. package/requirements/OFTR-003-profiles.md +51 -0
  146. package/requirements/OFTR-004-sync-and-setup.md +57 -0
  147. package/requirements/OFTR-005-run-and-composite-profile.md +60 -0
  148. package/requirements/OFTR-006-agent-adapters.md +64 -0
  149. package/requirements/OFTR-007-controllable-elements.md +32 -0
  150. package/requirements/OFTR-008-requirements-governance.md +42 -0
  151. package/requirements/OFTR-009-release-publishing.md +25 -0
  152. package/requirements/OFTR-010-onboarding-welcome.md +38 -0
  153. package/src/schemas/SchemaDocument.ts +20 -0
  154. package/src/schemas/profile-source.schema.json +29 -0
  155. package/src/schemas/profile.schema.json +115 -0
  156. package/src/schemas/settings.schema.json +37 -0
@@ -0,0 +1,54 @@
1
+ import type { CommandObject } from './CommandObject.js';
2
+ export type WelcomeDefaultProfileRoleId = 'engineer' | 'data_analyst';
3
+ export type WelcomeLoadoutItemKind = 'extension' | 'package';
4
+ export interface WelcomeCommandInput {
5
+ readonly homeDirectory: string;
6
+ readonly projectDirectory: string;
7
+ }
8
+ export interface WelcomeRoleChoice {
9
+ readonly id: WelcomeDefaultProfileRoleId;
10
+ readonly label: string;
11
+ }
12
+ export interface WelcomeLoadoutItem {
13
+ readonly id: string;
14
+ readonly label: string;
15
+ readonly kind: WelcomeLoadoutItemKind;
16
+ readonly source: string;
17
+ }
18
+ export interface WelcomeLoadout {
19
+ readonly id: string;
20
+ readonly label: string;
21
+ readonly items: readonly WelcomeLoadoutItem[];
22
+ }
23
+ export interface WelcomeLoadoutSelection {
24
+ readonly id: string;
25
+ readonly label: string;
26
+ readonly selectedItems: readonly WelcomeLoadoutItem[];
27
+ }
28
+ export interface WelcomePlan {
29
+ readonly answerQuestions: boolean;
30
+ readonly selectedRoleId?: string;
31
+ readonly loadoutItemIds?: readonly string[];
32
+ }
33
+ export interface WelcomeCommandResult {
34
+ readonly answered: boolean;
35
+ readonly selectedRole?: WelcomeRoleChoice;
36
+ readonly selectedLoadout?: WelcomeLoadoutSelection;
37
+ readonly warnings: readonly string[];
38
+ readonly messages: readonly string[];
39
+ }
40
+ export interface WelcomeCommandDependencies {
41
+ readonly homeDirectory?: string;
42
+ readonly projectDirectory?: string;
43
+ readonly input?: {
44
+ readonly isTTY?: boolean;
45
+ } & NodeJS.ReadableStream;
46
+ readonly output?: {
47
+ readonly isTTY?: boolean;
48
+ } & NodeJS.WritableStream;
49
+ readonly interactive?: boolean;
50
+ readonly writeLine?: (message: string) => void;
51
+ readonly selectWelcomePlan?: (input: WelcomeCommandInput) => Promise<WelcomePlan>;
52
+ }
53
+ export declare const executeWelcomeCommand: (input: WelcomeCommandInput, dependencies?: WelcomeCommandDependencies) => Promise<WelcomeCommandResult>;
54
+ export declare const createWelcomeCommand: (dependencies?: WelcomeCommandDependencies) => CommandObject;
@@ -0,0 +1,214 @@
1
+ // Provides the command object for first-run Outfitter welcome onboarding.
2
+ import { createInterface } from 'node:readline/promises';
3
+ import { homedir } from 'node:os';
4
+ const welcomeIntroLines = [
5
+ String.raw ` _ _ ____ _`,
6
+ String.raw ` / \ _ __ _ __ | | ___ | _ \(_)`,
7
+ String.raw ` / _ \ | '_ \| '_ \| |/ _ \ | |_) | |`,
8
+ String.raw ` / ___ \| |_) | |_) | | __/ | __/| |`,
9
+ String.raw `/_/ \_\ .__/| .__/|_|\___| |_| |_|`,
10
+ String.raw ` |_| |_|`,
11
+ '',
12
+ 'Welcome to Outfitter.',
13
+ 'Pi is a heavily customizable coding harness. The next few questions will configure Outfitter to best suit your workflow.',
14
+ ];
15
+ const defaultProfileRoleChoices = [
16
+ { id: 'engineer', label: 'Engineer' },
17
+ { id: 'data_analyst', label: 'Data Analyst' },
18
+ ];
19
+ const fallbackRoleId = 'engineer';
20
+ const recommendedPiLoadout = {
21
+ id: 'recommended-pi',
22
+ label: 'Recommended Pi productivity loadout',
23
+ items: [
24
+ {
25
+ id: 'ulta-tasklist',
26
+ label: 'Ulta Tasklist',
27
+ kind: 'extension',
28
+ source: 'git:github.com/ai-outfitter/ulta-tasklist',
29
+ },
30
+ {
31
+ id: 'deepwork',
32
+ label: 'DeepWork',
33
+ kind: 'extension',
34
+ source: 'git:github.com/ai-outfitter/deepwork',
35
+ },
36
+ {
37
+ id: 'pi-subagents',
38
+ label: 'Pi Subagents',
39
+ kind: 'package',
40
+ source: 'npm:pi-subagents',
41
+ },
42
+ {
43
+ id: 'pi-mcp-adapter',
44
+ label: 'Pi MCP Adapter',
45
+ kind: 'package',
46
+ source: 'npm:pi-mcp-adapter',
47
+ },
48
+ ],
49
+ };
50
+ export const executeWelcomeCommand = async (input, dependencies = {}) => {
51
+ requireInteractiveTerminalIfNeeded(dependencies);
52
+ const plan = await selectWelcomePlan(input, dependencies);
53
+ if (!plan.answerQuestions) {
54
+ return {
55
+ answered: false,
56
+ warnings: [],
57
+ messages: ['Skipped Outfitter welcome questions. Run `outfitter welcome` any time to revisit them.'],
58
+ };
59
+ }
60
+ const roleResolution = resolveSelectedRole(plan.selectedRoleId);
61
+ const loadoutResolution = resolveSelectedLoadout(plan.loadoutItemIds);
62
+ const warnings = [...roleResolution.warnings, ...loadoutResolution.warnings];
63
+ return {
64
+ answered: true,
65
+ selectedRole: roleResolution.role,
66
+ selectedLoadout: loadoutResolution.loadout,
67
+ warnings,
68
+ messages: buildWelcomeMessages(roleResolution.role, loadoutResolution.loadout, warnings),
69
+ };
70
+ };
71
+ export const createWelcomeCommand = (dependencies = {}) => {
72
+ const command = {
73
+ name: 'welcome',
74
+ description: 'Run Outfitter welcome onboarding prompts.',
75
+ register(program) {
76
+ program
77
+ .command(command.name)
78
+ .description(command.description)
79
+ .action(async () => {
80
+ const result = await executeWelcomeCommand({
81
+ /* v8 ignore next -- default process home is exercised by the direct CLI entrypoint, not unit tests. */
82
+ homeDirectory: dependencies.homeDirectory ?? homedir(),
83
+ /* v8 ignore next -- default process cwd is exercised by the direct CLI entrypoint, not unit tests. */
84
+ projectDirectory: dependencies.projectDirectory ?? process.cwd(),
85
+ }, { ...dependencies, interactive: true });
86
+ for (const message of result.messages) {
87
+ /* v8 ignore next -- console fallback is direct CLI behavior; tests inject a writer. */
88
+ (dependencies.writeLine ?? console.log)(message);
89
+ }
90
+ });
91
+ },
92
+ };
93
+ return command;
94
+ };
95
+ const selectWelcomePlan = async (input, dependencies) => {
96
+ if (dependencies.selectWelcomePlan !== undefined) {
97
+ return dependencies.selectWelcomePlan(input);
98
+ }
99
+ return promptForWelcomePlan(dependencies);
100
+ };
101
+ const promptForWelcomePlan = async (dependencies) => {
102
+ /* v8 ignore next -- default process streams are direct terminal behavior; tests inject streams. */
103
+ const output = dependencies.output ?? process.stdout;
104
+ /* v8 ignore next -- default process streams are direct terminal behavior; tests inject streams. */
105
+ const readline = createInterface({ input: dependencies.input ?? process.stdin, output });
106
+ try {
107
+ output.write(`\n${welcomeIntroLines.join('\n')}\n`);
108
+ const answerQuestions = await promptForYesNo(readline, 'Choose a role and recommended Pi loadout now? [Y/n]: ', true);
109
+ if (!answerQuestions) {
110
+ return { answerQuestions: false };
111
+ }
112
+ const selectedRoleId = await promptForRole(readline, output);
113
+ const loadoutItemIds = await promptForLoadout(readline, output);
114
+ return { answerQuestions: true, selectedRoleId, loadoutItemIds };
115
+ }
116
+ finally {
117
+ readline.close();
118
+ }
119
+ };
120
+ const promptForYesNo = async (readline, query, defaultValue) => {
121
+ const answer = (await readline.question(query)).trim().toLowerCase();
122
+ if (answer === '') {
123
+ return defaultValue;
124
+ }
125
+ return ['y', 'yes'].includes(answer);
126
+ };
127
+ const promptForRole = async (readline, output) => {
128
+ output.write('\nChoose your initial Outfitter role/profile:\n');
129
+ defaultProfileRoleChoices.forEach((role, index) => output.write(`${index + 1}. ${role.id} - ${role.label}\n`));
130
+ return defaultProfileRoleChoices[await promptForSelectionIndex(readline, 'Role [1]: ', 0)]?.id ?? fallbackRoleId;
131
+ };
132
+ const promptForLoadout = async (readline, output) => {
133
+ output.write(`\n${recommendedPiLoadout.label}:\n`);
134
+ recommendedPiLoadout.items.forEach((item, index) => {
135
+ output.write(`${index + 1}. ${item.label} (${item.kind}) - ${item.source}\n`);
136
+ });
137
+ const mode = (await readline.question('Install recommended loadout? [Y=all/c=choose/n=skip]: ')).trim().toLowerCase();
138
+ if (['n', 'no', 'skip'].includes(mode)) {
139
+ return [];
140
+ }
141
+ if (!['c', 'choose', 'custom', 's', 'select'].includes(mode)) {
142
+ return recommendedPiLoadout.items.map((item) => item.id);
143
+ }
144
+ const answer = (await readline.question('Loadout items [1,2,3,4 or blank for all]: ')).trim();
145
+ if (answer === '') {
146
+ return recommendedPiLoadout.items.map((item) => item.id);
147
+ }
148
+ return answer
149
+ .split(',')
150
+ .map((part) => Number.parseInt(part.trim(), 10) - 1)
151
+ .filter((index) => index >= 0 && index < recommendedPiLoadout.items.length)
152
+ .map((index) => recommendedPiLoadout.items[index].id);
153
+ };
154
+ const promptForSelectionIndex = async (readline, query, defaultIndex) => {
155
+ const answer = (await readline.question(query)).trim();
156
+ if (answer === '') {
157
+ return defaultIndex;
158
+ }
159
+ return Math.max(Number.parseInt(answer, 10) - 1, 0);
160
+ };
161
+ const resolveSelectedRole = (selectedRoleId) => {
162
+ const roleId = selectedRoleId ?? fallbackRoleId;
163
+ const selectedRole = defaultProfileRoleChoices.find((role) => role.id === roleId);
164
+ if (selectedRole !== undefined) {
165
+ return { role: selectedRole, warnings: [] };
166
+ }
167
+ return {
168
+ role: defaultProfileRoleChoices.find((role) => role.id === fallbackRoleId),
169
+ warnings: [`Welcome role '${roleId}' is not available; using fallback role '${fallbackRoleId}'.`],
170
+ };
171
+ };
172
+ const resolveSelectedLoadout = (loadoutItemIds) => {
173
+ const selectedItemIds = loadoutItemIds ?? recommendedPiLoadout.items.map((item) => item.id);
174
+ const availableItems = new Map(recommendedPiLoadout.items.map((item) => [item.id, item]));
175
+ const selectedItems = [];
176
+ const warnings = [];
177
+ for (const itemId of selectedItemIds) {
178
+ const item = availableItems.get(itemId);
179
+ if (item === undefined) {
180
+ warnings.push(`Loadout item '${itemId}' is not available for ${recommendedPiLoadout.id}; skipping it.`);
181
+ continue;
182
+ }
183
+ if (selectedItems.every((selectedItem) => selectedItem.id !== item.id)) {
184
+ selectedItems.push(item);
185
+ }
186
+ }
187
+ return {
188
+ loadout: { id: recommendedPiLoadout.id, label: recommendedPiLoadout.label, selectedItems },
189
+ warnings,
190
+ };
191
+ };
192
+ const buildWelcomeMessages = (selectedRole, selectedLoadout, warnings) => {
193
+ const loadoutMessage = selectedLoadout.selectedItems.length === 0
194
+ ? `Skipped ${selectedLoadout.label}.`
195
+ : `Selected ${selectedLoadout.label}: ${selectedLoadout.selectedItems.map((item) => item.source).join(', ')}.`;
196
+ return [
197
+ `Selected Outfitter role: ${selectedRole.id} (${selectedRole.label}).`,
198
+ loadoutMessage,
199
+ ...warnings.map((warning) => `Warning: ${warning}`),
200
+ ];
201
+ };
202
+ const requireInteractiveTerminalIfNeeded = (dependencies) => {
203
+ if (dependencies.interactive !== true) {
204
+ return;
205
+ }
206
+ /* v8 ignore next -- default process streams are direct terminal behavior; tests inject streams. */
207
+ const inputIsTty = (dependencies.input ?? process.stdin).isTTY === true;
208
+ /* v8 ignore next -- default process streams are direct terminal behavior; tests inject streams. */
209
+ const outputIsTty = (dependencies.output ?? process.stdout).isTTY === true;
210
+ if (!inputIsTty || !outputIsTty) {
211
+ throw new Error('`outfitter welcome` requires an interactive TTY on both stdin and stdout.');
212
+ }
213
+ };
214
+ //# sourceMappingURL=WelcomeCommand.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WelcomeCommand.js","sourceRoot":"","sources":["../../../src/cli/commands/WelcomeCommand.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import type { CommandObject } from '../CommandObject.js';
2
+ import type { ProfileCommandDependencies } from './Shared.js';
3
+ export declare const createProfileCommands: (dependencies?: ProfileCommandDependencies) => CommandObject[];
4
+ export declare const createProfileCommand: () => CommandObject;
5
+ export { executeCreateProfileCommand } from './CreateCommand.js';
6
+ export { executeListProfilesCommand } from './ListCommand.js';
@@ -0,0 +1,21 @@
1
+ import { createProfileCreateCommand } from './CreateCommand.js';
2
+ import { createProfileListCommand } from './ListCommand.js';
3
+ import { getOrCreateProfileCommander, profileCommandDescription, profileCommandName } from './Shared.js';
4
+ export const createProfileCommands = (dependencies = {}) => [
5
+ createProfileCommand(),
6
+ createProfileListCommand(dependencies),
7
+ createProfileCreateCommand(dependencies),
8
+ ];
9
+ export const createProfileCommand = () => {
10
+ const command = {
11
+ name: profileCommandName,
12
+ description: profileCommandDescription,
13
+ register(program) {
14
+ getOrCreateProfileCommander(program);
15
+ },
16
+ };
17
+ return command;
18
+ };
19
+ export { executeCreateProfileCommand } from './CreateCommand.js';
20
+ export { executeListProfilesCommand } from './ListCommand.js';
21
+ //# sourceMappingURL=Command.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Command.js","sourceRoot":"","sources":["../../../../src/cli/commands/profile/Command.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,0BAA0B,EAAE,MAAM,oBAAoB,CAAC;AAChE,OAAO,EAAE,wBAAwB,EAAE,MAAM,kBAAkB,CAAC;AAE5D,OAAO,EAAE,2BAA2B,EAAE,yBAAyB,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAEzG,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,eAA2C,EAAE,EAAmB,EAAE,CAAC;IACvG,oBAAoB,EAAE;IACtB,wBAAwB,CAAC,YAAY,CAAC;IACtC,0BAA0B,CAAC,YAAY,CAAC;CACzC,CAAC;AAEF,MAAM,CAAC,MAAM,oBAAoB,GAAG,GAAkB,EAAE;IACtD,MAAM,OAAO,GAAkB;QAC7B,IAAI,EAAE,kBAAkB;QACxB,WAAW,EAAE,yBAAyB;QACtC,QAAQ,CAAC,OAAgB;YACvB,2BAA2B,CAAC,OAAO,CAAC,CAAC;QACvC,CAAC;KACF,CAAC;IAEF,OAAO,OAAO,CAAC;AACjB,CAAC,CAAC;AAEF,OAAO,EAAE,2BAA2B,EAAE,MAAM,oBAAoB,CAAC;AACjE,OAAO,EAAE,0BAA0B,EAAE,MAAM,kBAAkB,CAAC"}
@@ -0,0 +1,19 @@
1
+ import type { CommandObject } from '../CommandObject.js';
2
+ import type { ProfileCommandDependencies } from './Shared.js';
3
+ export type CreateProfileScope = 'user' | 'project' | 'project-local';
4
+ export interface CreateProfileInput {
5
+ readonly name: string;
6
+ readonly scope?: CreateProfileScope;
7
+ readonly path?: string;
8
+ readonly homeDirectory: string;
9
+ readonly projectDirectory: string;
10
+ }
11
+ export interface CreateProfileResult {
12
+ readonly profileDirectory: string;
13
+ readonly profilePath: string;
14
+ readonly createdDirectories: readonly string[];
15
+ readonly createdProfile: boolean;
16
+ readonly messages: readonly string[];
17
+ }
18
+ export declare const createProfileCreateCommand: (dependencies: ProfileCommandDependencies) => CommandObject;
19
+ export declare const executeCreateProfileCommand: (input: CreateProfileInput) => CreateProfileResult;
@@ -0,0 +1,115 @@
1
+ // Provides the profile create subcommand and profile skeleton creation behavior.
2
+ import { existsSync, mkdirSync, writeFileSync } from 'node:fs';
3
+ import { homedir } from 'node:os';
4
+ import { join } from 'node:path';
5
+ import { Command } from 'commander';
6
+ import { isValidProfileId } from '../../../profiles/ProfileLoader.js';
7
+ import { getOrCreateProfileCommander } from './Shared.js';
8
+ export const createProfileCreateCommand = (dependencies) => {
9
+ const command = {
10
+ name: 'profile create',
11
+ description: 'Create a new Outfitter profile skeleton.',
12
+ register(program) {
13
+ getOrCreateProfileCommander(program).addCommand(createProfileCreateCommander(dependencies));
14
+ },
15
+ };
16
+ return command;
17
+ };
18
+ const createProfileCreateCommander = (dependencies) => new Command('create')
19
+ .description('Create a new Outfitter profile skeleton.')
20
+ .argument('<name>', 'filesystem-safe profile name')
21
+ .option('--scope <scope>', 'destination scope: user, project, or project-local')
22
+ .option('--path <path>', 'destination profile source directory')
23
+ .action((name, options) => {
24
+ const result = executeCreateProfileCommand({
25
+ name,
26
+ scope: readCreateProfileScope(options.scope),
27
+ path: options.path,
28
+ /* v8 ignore next -- default process home is exercised by the direct CLI entrypoint, not unit tests. */
29
+ homeDirectory: dependencies.homeDirectory ?? homedir(),
30
+ /* v8 ignore next -- default process cwd is exercised by the direct CLI entrypoint, not unit tests. */
31
+ projectDirectory: dependencies.projectDirectory ?? process.cwd(),
32
+ });
33
+ emitMessages(result.messages, dependencies.writeLine);
34
+ });
35
+ export const executeCreateProfileCommand = (input) => {
36
+ assertValidCreateProfileInput(input);
37
+ const profileRoot = resolveProfileRoot(input);
38
+ const profileDirectory = join(profileRoot, input.name);
39
+ const profilePath = join(profileDirectory, 'profile.yml');
40
+ const resourceDirectories = [
41
+ 'prompts',
42
+ 'skills',
43
+ 'extensions',
44
+ join('cli_specific', 'pi'),
45
+ join('cli_specific', 'claude'),
46
+ ].map((resourcePath) => join(profileDirectory, resourcePath));
47
+ const createdDirectories = [];
48
+ if (!existsSync(profileDirectory)) {
49
+ mkdirSync(profileDirectory, { recursive: true });
50
+ createdDirectories.push(profileDirectory);
51
+ }
52
+ for (const resourceDirectory of resourceDirectories) {
53
+ if (!existsSync(resourceDirectory)) {
54
+ mkdirSync(resourceDirectory, { recursive: true });
55
+ createdDirectories.push(resourceDirectory);
56
+ }
57
+ }
58
+ const createdProfile = !existsSync(profilePath);
59
+ if (createdProfile) {
60
+ writeFileSync(profilePath, createPlaceholderProfileYaml(input.name));
61
+ }
62
+ return {
63
+ profileDirectory,
64
+ profilePath,
65
+ createdDirectories,
66
+ createdProfile,
67
+ messages: [
68
+ createdProfile
69
+ ? `Created profile '${input.name}' at ${profileDirectory}.`
70
+ : `Profile '${input.name}' already exists at ${profileDirectory}; left profile.yml unchanged.`,
71
+ ],
72
+ };
73
+ };
74
+ const emitMessages = (messages, writeLine) => {
75
+ for (const message of messages) {
76
+ /* v8 ignore next -- console fallback is direct CLI behavior; tests inject a writer. */
77
+ (writeLine ?? console.log)(message);
78
+ }
79
+ };
80
+ const assertValidCreateProfileInput = (input) => {
81
+ if (!isValidProfileId(input.name)) {
82
+ throw new Error(`Profile name '${input.name}' is not a filesystem-safe Outfitter profile id.`);
83
+ }
84
+ if ((input.scope === undefined && input.path === undefined) ||
85
+ (input.scope !== undefined && input.path !== undefined)) {
86
+ throw new Error('Create profile requires exactly one destination: --scope or --path.');
87
+ }
88
+ };
89
+ const resolveProfileRoot = (input) => {
90
+ if (input.path !== undefined) {
91
+ return input.path;
92
+ }
93
+ switch (input.scope) {
94
+ case 'user':
95
+ return join(input.homeDirectory, '.outfitter', 'profiles');
96
+ case 'project':
97
+ return join(input.projectDirectory, '.outfitter', 'profiles');
98
+ case 'project-local':
99
+ return join(input.projectDirectory, '.outfitter', 'local', 'profiles');
100
+ /* v8 ignore next 2 -- assertValidCreateProfileInput rejects missing scopes before this exhaustive guard. */
101
+ default:
102
+ throw new Error('Create profile requires exactly one destination: --scope or --path.');
103
+ }
104
+ };
105
+ const createPlaceholderProfileYaml = (profileId) => `id: ${profileId}\nlabel: ${profileId}\ncontrols: {}\n`;
106
+ const readCreateProfileScope = (scope) => {
107
+ if (scope === undefined) {
108
+ return undefined;
109
+ }
110
+ if (scope === 'user' || scope === 'project' || scope === 'project-local') {
111
+ return scope;
112
+ }
113
+ throw new Error(`Unknown profile scope '${scope}'. Expected user, project, or project-local.`);
114
+ };
115
+ //# sourceMappingURL=CreateCommand.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CreateCommand.js","sourceRoot":"","sources":["../../../../src/cli/commands/profile/CreateCommand.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import type { CommandObject } from '../CommandObject.js';
2
+ import type { ProfileCommandDependencies } from './Shared.js';
3
+ export interface ListedProfile {
4
+ readonly id: string;
5
+ readonly label?: string;
6
+ readonly profilePath: string;
7
+ }
8
+ export interface ListProfilesInput {
9
+ readonly homeDirectory: string;
10
+ readonly projectDirectory: string;
11
+ }
12
+ export interface ListProfilesResult {
13
+ readonly profiles: readonly ListedProfile[];
14
+ readonly messages: readonly string[];
15
+ }
16
+ export declare const createProfileListCommand: (dependencies: ProfileCommandDependencies) => CommandObject;
17
+ export declare const executeListProfilesCommand: (input: ListProfilesInput) => ListProfilesResult;
@@ -0,0 +1,85 @@
1
+ // Provides the profile list subcommand and profile discovery behavior.
2
+ import { homedir } from 'node:os';
3
+ import { Command } from 'commander';
4
+ import { createProfileSourceCachePath, createRemoteRepositoryCachePath, resolveRemoteRepositorySubpath, } from '../../../profiles/ProfileCache.js';
5
+ import { loadLocalProfileSource } from '../../../profiles/ProfileLoader.js';
6
+ import { loadSettingsWithCachedRemoteSettings } from '../../../settings/SettingsLoader.js';
7
+ import { getOrCreateProfileCommander } from './Shared.js';
8
+ export const createProfileListCommand = (dependencies) => {
9
+ const command = {
10
+ name: 'profile list',
11
+ description: 'List available Outfitter profiles.',
12
+ register(program) {
13
+ getOrCreateProfileCommander(program).addCommand(createProfileListCommander(dependencies));
14
+ },
15
+ };
16
+ return command;
17
+ };
18
+ const createProfileListCommander = (dependencies) => new Command('list').description('List available Outfitter profiles.').action(() => {
19
+ const result = executeListProfilesCommand({
20
+ /* v8 ignore next -- default process home is exercised by the direct CLI entrypoint, not unit tests. */
21
+ homeDirectory: dependencies.homeDirectory ?? homedir(),
22
+ /* v8 ignore next -- default process cwd is exercised by the direct CLI entrypoint, not unit tests. */
23
+ projectDirectory: dependencies.projectDirectory ?? process.cwd(),
24
+ });
25
+ emitMessages(result.messages, dependencies.writeLine);
26
+ });
27
+ export const executeListProfilesCommand = (input) => {
28
+ const loadedSettings = loadSettingsWithCachedRemoteSettings(input);
29
+ if (loadedSettings.issues.length > 0) {
30
+ throw new Error(`Cannot list profiles with invalid settings: ${loadedSettings.issues.map(formatSettingsIssue).join('; ')}`);
31
+ }
32
+ const profileLoadResult = loadProfileSources(input.homeDirectory, loadedSettings.settings.profileSources);
33
+ if (profileLoadResult.issues.length > 0) {
34
+ throw new Error(`Cannot list profiles with invalid profiles: ${profileLoadResult.issues.map(formatProfileIssue).join('; ')}`);
35
+ }
36
+ const profiles = listHighestPrecedenceProfiles(profileLoadResult.profiles);
37
+ return {
38
+ profiles,
39
+ messages: profiles.length === 0 ? ['No profiles found.'] : profiles.map((profile) => profile.id),
40
+ };
41
+ };
42
+ const emitMessages = (messages, writeLine) => {
43
+ for (const message of messages) {
44
+ /* v8 ignore next -- console fallback is direct CLI behavior; tests inject a writer. */
45
+ (writeLine ?? console.log)(message);
46
+ }
47
+ };
48
+ const loadProfileSources = (homeDirectory, sources) => {
49
+ const profiles = [];
50
+ const issues = [];
51
+ for (const source of sources) {
52
+ const materializedSource = materializeSource(homeDirectory, source);
53
+ const result = loadLocalProfileSource(materializedSource);
54
+ profiles.push(...result.profiles.map((profile) => ({ ...profile, source })));
55
+ issues.push(...result.issues);
56
+ }
57
+ return { profiles, issues };
58
+ };
59
+ const materializeSource = (homeDirectory, source) => {
60
+ if (source.uri === undefined && source.github === undefined) {
61
+ return source;
62
+ }
63
+ if (source.uri !== undefined && source.ref === undefined && source.path === undefined) {
64
+ return { path: createProfileSourceCachePath(homeDirectory, source.uri), only: source.only, except: source.except };
65
+ }
66
+ return {
67
+ path: resolveRemoteRepositorySubpath(createRemoteRepositoryCachePath(homeDirectory, source), source.path),
68
+ only: source.only,
69
+ except: source.except,
70
+ };
71
+ };
72
+ const listHighestPrecedenceProfiles = (loadedProfiles) => {
73
+ const profilesById = new Map();
74
+ for (const loadedProfile of loadedProfiles) {
75
+ profilesById.set(loadedProfile.profile.id, {
76
+ id: loadedProfile.profile.id,
77
+ label: loadedProfile.profile.label,
78
+ profilePath: loadedProfile.profilePath,
79
+ });
80
+ }
81
+ return [...profilesById.values()].sort((left, right) => left.id.localeCompare(right.id));
82
+ };
83
+ const formatSettingsIssue = (issue) => `${issue.filePath}#${issue.path} ${issue.message}`;
84
+ const formatProfileIssue = (issue) => `${issue.path} ${issue.message}`;
85
+ //# sourceMappingURL=ListCommand.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ListCommand.js","sourceRoot":"","sources":["../../../../src/cli/commands/profile/ListCommand.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import { Command } from 'commander';
2
+ export declare const profileCommandName = "profile";
3
+ export declare const profileCommandDescription = "List and manage Outfitter profiles.";
4
+ export interface ProfileCommandDependencies {
5
+ readonly homeDirectory?: string;
6
+ readonly projectDirectory?: string;
7
+ readonly writeLine?: (message: string) => void;
8
+ }
9
+ export declare const getOrCreateProfileCommander: (program: Command) => Command;
@@ -0,0 +1,10 @@
1
+ export const profileCommandName = 'profile';
2
+ export const profileCommandDescription = 'List and manage Outfitter profiles.';
3
+ export const getOrCreateProfileCommander = (program) => {
4
+ const existingProfileCommand = program.commands.find((command) => command.name() === profileCommandName);
5
+ if (existingProfileCommand !== undefined) {
6
+ return existingProfileCommand;
7
+ }
8
+ return program.command(profileCommandName).description(profileCommandDescription);
9
+ };
10
+ //# sourceMappingURL=Shared.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Shared.js","sourceRoot":"","sources":["../../../../src/cli/commands/profile/Shared.ts"],"names":[],"mappings":"AAGA,MAAM,CAAC,MAAM,kBAAkB,GAAG,SAAS,CAAC;AAC5C,MAAM,CAAC,MAAM,yBAAyB,GAAG,qCAAqC,CAAC;AAQ/E,MAAM,CAAC,MAAM,2BAA2B,GAAG,CAAC,OAAgB,EAAW,EAAE;IACvE,MAAM,sBAAsB,GAAG,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,kBAAkB,CAAC,CAAC;IAEzG,IAAI,sBAAsB,KAAK,SAAS,EAAE,CAAC;QACzC,OAAO,sBAAsB,CAAC;IAChC,CAAC;IAED,OAAO,OAAO,CAAC,OAAO,CAAC,kBAAkB,CAAC,CAAC,WAAW,CAAC,yBAAyB,CAAC,CAAC;AACpF,CAAC,CAAC"}
package/dist/cli.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export declare const createProgram: (commands?: readonly import("./cli/commands/CommandObject.js").CommandObject[]) => import("commander").Command;
3
+ export declare const isDirectCliExecution: (moduleUrl: string, argvPath: string | undefined) => boolean;
package/dist/cli.js ADDED
@@ -0,0 +1,22 @@
1
+ #!/usr/bin/env node
2
+ // Defines the initial Outfitter executable entrypoint.
3
+ import { realpathSync } from 'node:fs';
4
+ import { fileURLToPath } from 'node:url';
5
+ import { createOutfitterProgram } from './cli/OutfitterCli.js';
6
+ export const createProgram = createOutfitterProgram;
7
+ export const isDirectCliExecution = (moduleUrl, argvPath) => {
8
+ if (argvPath === undefined) {
9
+ return false;
10
+ }
11
+ try {
12
+ return realpathSync(fileURLToPath(moduleUrl)) === realpathSync(argvPath);
13
+ }
14
+ catch {
15
+ return false;
16
+ }
17
+ };
18
+ /* v8 ignore next 3 -- direct bin execution is covered by local install smoke tests. */
19
+ if (isDirectCliExecution(import.meta.url, process.argv[1])) {
20
+ await createProgram().parseAsync(process.argv);
21
+ }
22
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA,uDAAuD;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAE/D,MAAM,CAAC,MAAM,aAAa,GAAG,sBAAsB,CAAC;AAEpD,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,SAAiB,EAAE,QAA4B,EAAW,EAAE;IAC/F,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QAC3B,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,CAAC;QACH,OAAO,YAAY,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC,KAAK,YAAY,CAAC,QAAQ,CAAC,CAAC;IAC3E,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC,CAAC;AAEF,uFAAuF;AACvF,IAAI,oBAAoB,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAC3D,MAAM,aAAa,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;AACjD,CAAC"}
@@ -0,0 +1,8 @@
1
+ import type { CompositeProfileStatePath } from './StatePersistence.js';
2
+ import type { CompositeProfileFile } from './CompositeProfileFile.js';
3
+ export interface CompositeProfile {
4
+ readonly rootDirectory: string;
5
+ readonly files: readonly CompositeProfileFile[];
6
+ readonly statePaths: readonly CompositeProfileStatePath[];
7
+ }
8
+ export declare const createCompositeProfile: (rootDirectory: string, files: readonly CompositeProfileFile[], statePaths?: readonly CompositeProfileStatePath[]) => CompositeProfile;