ai-summon 0.0.1
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/.claude/commands/speckit.analyze.md +184 -0
- package/.claude/commands/speckit.checklist.md +294 -0
- package/.claude/commands/speckit.clarify.md +177 -0
- package/.claude/commands/speckit.constitution.md +78 -0
- package/.claude/commands/speckit.implement.md +121 -0
- package/.claude/commands/speckit.plan.md +81 -0
- package/.claude/commands/speckit.specify.md +204 -0
- package/.claude/commands/speckit.tasks.md +108 -0
- package/.claude/settings.local.json +23 -0
- package/.prettierignore +5 -0
- package/.prettierrc.json +10 -0
- package/.specify/memory/constitution.md +72 -0
- package/.specify/scripts/bash/check-prerequisites.sh +166 -0
- package/.specify/scripts/bash/common.sh +113 -0
- package/.specify/scripts/bash/create-new-feature.sh +97 -0
- package/.specify/scripts/bash/setup-plan.sh +60 -0
- package/.specify/scripts/bash/update-agent-context.sh +738 -0
- package/.specify/templates/agent-file-template.md +28 -0
- package/.specify/templates/checklist-template.md +40 -0
- package/.specify/templates/plan-template.md +111 -0
- package/.specify/templates/spec-template.md +115 -0
- package/.specify/templates/tasks-template.md +250 -0
- package/CLAUDE.md +199 -0
- package/PRD.md +268 -0
- package/README.md +171 -0
- package/dist/ai-summon.d.ts +2 -0
- package/dist/ai-summon.js +73 -0
- package/dist/commands/ide/index.d.ts +3 -0
- package/dist/commands/ide/index.js +253 -0
- package/dist/commands/init.d.ts +4 -0
- package/dist/commands/init.js +55 -0
- package/dist/commands/url.d.ts +4 -0
- package/dist/commands/url.js +223 -0
- package/dist/types/index.d.ts +40 -0
- package/dist/types/index.js +1 -0
- package/dist/util.d.ts +16 -0
- package/dist/util.js +109 -0
- package/eslint.config.js +47 -0
- package/package.json +47 -0
- package/specs/001-cloud-login-feature/contracts/cloud-command.ts +82 -0
- package/specs/001-cloud-login-feature/contracts/config-service.ts +170 -0
- package/specs/001-cloud-login-feature/data-model.md +269 -0
- package/specs/001-cloud-login-feature/plan.md +91 -0
- package/specs/001-cloud-login-feature/quickstart.md +366 -0
- package/specs/001-cloud-login-feature/research.md +290 -0
- package/specs/001-cloud-login-feature/spec.md +195 -0
- package/specs/001-cloud-login-feature/tasks.md +235 -0
- package/specs/001-cloud-scp-command/contracts/cloud-scp-api.ts +402 -0
- package/specs/001-cloud-scp-command/data-model.md +424 -0
- package/specs/001-cloud-scp-command/plan.md +124 -0
- package/specs/001-cloud-scp-command/quickstart.md +536 -0
- package/specs/001-cloud-scp-command/research.md +345 -0
- package/specs/001-cloud-scp-command/spec.md +248 -0
- package/specs/001-cloud-scp-command/tasks.md +434 -0
- package/src/ai-summon.ts +88 -0
- package/src/commands/ide/index.ts +322 -0
- package/src/commands/init.ts +64 -0
- package/src/commands/url.ts +262 -0
- package/src/types/index.ts +49 -0
- package/src/util.ts +146 -0
- package/tsconfig.json +21 -0
|
@@ -0,0 +1,434 @@
|
|
|
1
|
+
# Tasks: Cloud SCP Command
|
|
2
|
+
|
|
3
|
+
**Feature ID**: 001-cloud-scp-command
|
|
4
|
+
**Branch**: `001-cloud-scp-command`
|
|
5
|
+
**Input**: Design documents from `/specs/001-cloud-scp-command/`
|
|
6
|
+
**Prerequisites**: plan.md, spec.md, research.md, data-model.md, contracts/
|
|
7
|
+
|
|
8
|
+
**Tests**: Manual CLI testing (no automated test suite requested in spec)
|
|
9
|
+
|
|
10
|
+
**Organization**: Tasks grouped by user story for independent implementation and testing
|
|
11
|
+
|
|
12
|
+
## Format: `[ID] [P?] [Story] Description`
|
|
13
|
+
|
|
14
|
+
- **[P]**: Can run in parallel (different files, no dependencies)
|
|
15
|
+
- **[Story]**: Which user story this task belongs to (US1, US2, US3)
|
|
16
|
+
- Include exact file paths in descriptions
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Phase 1: Setup (Shared Infrastructure)
|
|
21
|
+
|
|
22
|
+
**Purpose**: Minimal setup - most infrastructure already exists from cloud login feature
|
|
23
|
+
|
|
24
|
+
- [x] T001 Verify TypeScript 5.0+ configuration in tsconfig.json (strict mode enabled)
|
|
25
|
+
- [x] T002 [P] Verify existing dependencies (commander, inquirer, zx, chalk, fs/promises)
|
|
26
|
+
- [x] T003 [P] Review existing cloud.ts helper functions (validatePrivateKey, promptForService, promptForEnvironment, handleSSHError)
|
|
27
|
+
|
|
28
|
+
**Notes**: This is an extension of existing infrastructure. Setup tasks are verification only since the project already exists.
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## Phase 2: Foundational (Blocking Prerequisites)
|
|
33
|
+
|
|
34
|
+
**Purpose**: Core types and infrastructure needed by ALL user stories
|
|
35
|
+
|
|
36
|
+
**⚠️ CRITICAL**: No user story work can begin until this phase is complete
|
|
37
|
+
|
|
38
|
+
- [x] T004 [P] Add ScpOptions interface to src/types/index.ts (env, service, recursive fields)
|
|
39
|
+
- [x] T005 [P] Add PathValidationResult interface to src/types/index.ts (exists, isDirectory, isFile, path fields)
|
|
40
|
+
- [x] T006 [P] Export ScpOptions and PathValidationResult from src/types/index.ts
|
|
41
|
+
|
|
42
|
+
**Checkpoint**: Foundation ready - user story implementation can now begin
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## Phase 3: User Story 1 - Quick File Deploy (Priority: P1) 🎯 MVP
|
|
47
|
+
|
|
48
|
+
**Goal**: Enable developers to quickly copy a single file to a remote server with interactive prompts
|
|
49
|
+
|
|
50
|
+
**Independent Test**:
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
# Create a test file
|
|
54
|
+
echo "test content" > /tmp/test-file.txt
|
|
55
|
+
|
|
56
|
+
# Test command (interactive - will prompt for service/env)
|
|
57
|
+
hsh cloud scp /tmp/test-file.txt /tmp/remote-test.txt
|
|
58
|
+
|
|
59
|
+
# Verify success message appears
|
|
60
|
+
# Expected: ✅ Successfully copied to [service] ([env]): /tmp/remote-test.txt
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### Implementation for User Story 1
|
|
64
|
+
|
|
65
|
+
- [x] T007 [US1] Implement validateLocalPath() function in src/commands/cloud.ts
|
|
66
|
+
- Import { stat } from 'fs/promises'
|
|
67
|
+
- Check if path exists using stat()
|
|
68
|
+
- Return PathValidationResult with exists, isDirectory, isFile, path
|
|
69
|
+
- Handle ENOENT error (file not found) separately from permission errors
|
|
70
|
+
- Throw on permission denied or other fs errors
|
|
71
|
+
|
|
72
|
+
- [x] T008 [US1] Implement cloudScp() main function in src/commands/cloud.ts (depends on T007)
|
|
73
|
+
- Accept localPath, remotePath, options parameters with ScpOptions type
|
|
74
|
+
- Call validateLocalPath() for local path validation
|
|
75
|
+
- Handle case when path doesn't exist: log error and return early
|
|
76
|
+
- Read configuration using existing readConfig() from util.ts
|
|
77
|
+
- Handle case when no services configured: log error and return
|
|
78
|
+
- Use existing promptForService() if options.service not provided
|
|
79
|
+
- Validate service exists in config, log available services if not found
|
|
80
|
+
- Use existing promptForEnvironment() if options.env not provided
|
|
81
|
+
- Validate environment exists for service, log available environments if not found
|
|
82
|
+
- Get cloudConfig from config.yiren[service][env]
|
|
83
|
+
- Call existing validatePrivateKey() with cloudConfig.privateKeyFile
|
|
84
|
+
- Construct SCP command using zx $ template literal
|
|
85
|
+
- Pattern: `scp -i ${privateKeyFile} -o ConnectTimeout=10 -o StrictHostKeyChecking=no scp ${localPath} root@${ip}:${remotePath}`
|
|
86
|
+
- Wrap SCP execution in try-catch, use existing handleSSHError() on failure
|
|
87
|
+
- Log success message with chalk.green on completion
|
|
88
|
+
|
|
89
|
+
- [x] T009 [US1] Export cloudScp function from src/commands/cloud.ts
|
|
90
|
+
- Add cloudScp to existing export list
|
|
91
|
+
|
|
92
|
+
- [x] T010 [US1] Import cloudScp in src/hsh.ts
|
|
93
|
+
- Add cloudScp to import statement from './commands/cloud.js'
|
|
94
|
+
|
|
95
|
+
- [x] T011 [US1] Register cloud scp subcommand in src/hsh.ts (depends on T010)
|
|
96
|
+
- Add after existing cloud login subcommand registration
|
|
97
|
+
- Use cloudCommand.command('scp')
|
|
98
|
+
- Add .description('Copy files to cloud instances')
|
|
99
|
+
- Add .option('--env <environment>', 'Environment: dev, staging, or prod')
|
|
100
|
+
- Add .option('--service <service>', 'Service name')
|
|
101
|
+
- Add .argument('<local-path>', 'Local file or directory path')
|
|
102
|
+
- Add .argument('<remote-path>', 'Remote destination path')
|
|
103
|
+
- Add .action() handler that calls cloudScp(localPath, remotePath, options)
|
|
104
|
+
|
|
105
|
+
- [x] T012 [US1] Build and test file copy functionality
|
|
106
|
+
- Run: yarn build
|
|
107
|
+
- Run: yarn build:install
|
|
108
|
+
- Test with actual file: hsh cloud scp /tmp/test.txt /tmp/remote-test.txt
|
|
109
|
+
- Verify interactive prompts work for service and environment selection
|
|
110
|
+
- Verify file copy succeeds with success message
|
|
111
|
+
|
|
112
|
+
**Checkpoint**: User Story 1 complete - file copying works with interactive prompts
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
## Phase 4: User Story 2 - Directory Upload (Priority: P2)
|
|
117
|
+
|
|
118
|
+
**Goal**: Enable developers to upload entire directories with recursive flag validation
|
|
119
|
+
|
|
120
|
+
**Independent Test**:
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
# Create a test directory with files
|
|
124
|
+
mkdir -p /tmp/test-dir
|
|
125
|
+
echo "file1" > /tmp/test-dir/file1.txt
|
|
126
|
+
echo "file2" > /tmp/test-dir/file2.txt
|
|
127
|
+
|
|
128
|
+
# Test without -r flag (should fail with clear message)
|
|
129
|
+
hsh cloud scp /tmp/test-dir /tmp/remote-dir
|
|
130
|
+
|
|
131
|
+
# Expected: ❌ Cannot copy directory without -r flag
|
|
132
|
+
# Expected: Hint: Use -r flag for recursive directory copy
|
|
133
|
+
|
|
134
|
+
# Test with -r flag (should succeed)
|
|
135
|
+
hsh cloud scp -r /tmp/test-dir /tmp/remote-dir --env dev --service my-service
|
|
136
|
+
|
|
137
|
+
# Verify success message appears
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### Implementation for User Story 2
|
|
141
|
+
|
|
142
|
+
- [ ] T013 [US2] Add -r/--recursive option to cloud scp command in src/hsh.ts
|
|
143
|
+
- Add before .argument() calls
|
|
144
|
+
- Use .option('-r, --recursive', 'Copy directories recursively')
|
|
145
|
+
|
|
146
|
+
- [ ] T014 [US2] Add directory detection logic to cloudScp() in src/commands/cloud.ts
|
|
147
|
+
- After validateLocalPath() call, check if pathInfo.isDirectory is true
|
|
148
|
+
- If isDirectory && !options.recursive, log error and return early
|
|
149
|
+
- Error message: chalk.red('❌ Cannot copy directory without -r flag')
|
|
150
|
+
- Hint message: chalk.yellow('Hint: Use -r flag for recursive directory copy')
|
|
151
|
+
|
|
152
|
+
- [ ] T015 [US2] Update SCP command construction for recursive flag in src/commands/cloud.ts
|
|
153
|
+
- Before SCP execution, check if pathInfo.isDirectory
|
|
154
|
+
- If directory, construct flags variable with '-r', otherwise empty string
|
|
155
|
+
- Update SCP command: `scp -i ${privateKeyFile} -o ConnectTimeout=10 -o StrictHostKeyChecking=no scp ${flags} ${localPath} root@${ip}:${remotePath}`
|
|
156
|
+
- Ensure flags variable is properly spaced or empty
|
|
157
|
+
|
|
158
|
+
- [ ] T016 [US2] Build and test directory copy functionality
|
|
159
|
+
- Run: yarn build
|
|
160
|
+
- Run: yarn build:install
|
|
161
|
+
- Test directory without -r flag: verify error message with hint
|
|
162
|
+
- Test directory with -r flag: verify successful recursive copy
|
|
163
|
+
- Test that file copy still works (regression test for US1)
|
|
164
|
+
|
|
165
|
+
**Checkpoint**: User Stories 1 AND 2 complete - both file and directory copying work
|
|
166
|
+
|
|
167
|
+
---
|
|
168
|
+
|
|
169
|
+
## Phase 5: User Story 3 - Interactive Service Selection (Priority: P3)
|
|
170
|
+
|
|
171
|
+
**Goal**: Polish interactive experience - ensure prompts work consistently with cloud login
|
|
172
|
+
|
|
173
|
+
**Independent Test**:
|
|
174
|
+
|
|
175
|
+
```bash
|
|
176
|
+
# Test interactive service selection (no --service flag)
|
|
177
|
+
hsh cloud scp /tmp/test.txt /tmp/remote.txt
|
|
178
|
+
|
|
179
|
+
# Expected: Prompt "Select service:" with list of available services
|
|
180
|
+
# User selects service from list
|
|
181
|
+
# Expected: Prompt "Select environment:" with list of available environments for that service
|
|
182
|
+
# User selects environment from list
|
|
183
|
+
# Expected: ✅ Successfully copied to [service] ([env]): /tmp/remote.txt
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
### Implementation for User Story 3
|
|
187
|
+
|
|
188
|
+
**Note**: Interactive prompts already implemented in US1 (T008). This phase focuses on production safety.
|
|
189
|
+
|
|
190
|
+
- [x] T017 [US3] Add production confirmation prompt to cloudScp() in src/commands/cloud.ts
|
|
191
|
+
- After getting cloudConfig, before validatePrivateKey()
|
|
192
|
+
- Check if env === 'prod'
|
|
193
|
+
- If production, use inquirer.prompt() with type: 'confirm'
|
|
194
|
+
- Message: chalk.red(`⚠️ You are about to copy files to PRODUCTION (${service}). Continue?`)
|
|
195
|
+
- Default: false
|
|
196
|
+
- If confirmProduction is false, log chalk.yellow('⏸️ Production operation cancelled.') and return
|
|
197
|
+
- If confirmed, continue with execution
|
|
198
|
+
|
|
199
|
+
- [x] T018 [US3] Build and test production confirmation
|
|
200
|
+
- Run: yarn build
|
|
201
|
+
- Run: yarn build:install
|
|
202
|
+
- Test with --env prod: verify production warning appears
|
|
203
|
+
- Test declining production: verify cancellation message
|
|
204
|
+
- Test accepting production: verify copy proceeds
|
|
205
|
+
- Test dev/staging: verify no prompt appears (regression test)
|
|
206
|
+
|
|
207
|
+
**Checkpoint**: All user stories complete - interactive prompts and production safety work
|
|
208
|
+
|
|
209
|
+
---
|
|
210
|
+
|
|
211
|
+
## Phase 6: Polish & Cross-Cutting Concerns
|
|
212
|
+
|
|
213
|
+
**Purpose**: Final improvements and validation
|
|
214
|
+
|
|
215
|
+
- [x] T019 [P] Code review: Verify all types are properly exported from src/types/index.ts
|
|
216
|
+
- [x] T020 [P] Code review: Verify consistent error handling with chalk colors
|
|
217
|
+
- [x] T021 [P] Code review: Verify all async functions use await with proper error handling
|
|
218
|
+
- [x] T022 [P] Verify TypeScript compilation with strict mode: yarn build
|
|
219
|
+
- [x] T023 Test all user stories end-to-end following quickstart.md validation scenarios
|
|
220
|
+
- File copy with explicit --env and --service flags
|
|
221
|
+
- Directory copy with -r flag
|
|
222
|
+
- Interactive service selection (no --service flag)
|
|
223
|
+
- Interactive environment selection (no --env flag)
|
|
224
|
+
- Production confirmation prompt and cancellation
|
|
225
|
+
- Error handling for missing local path
|
|
226
|
+
- Error handling for directory without -r flag
|
|
227
|
+
- Error handling for invalid service
|
|
228
|
+
- Error handling for invalid environment
|
|
229
|
+
|
|
230
|
+
- [x] T024 Final verification: Install globally and test from different directory
|
|
231
|
+
- Run: yarn build:install
|
|
232
|
+
- Navigate to different directory: cd ~/
|
|
233
|
+
- Test command: hsh cloud scp [test scenarios from T023]
|
|
234
|
+
- Verify all functionality works from any directory
|
|
235
|
+
|
|
236
|
+
---
|
|
237
|
+
|
|
238
|
+
## Dependencies & Execution Order
|
|
239
|
+
|
|
240
|
+
### Phase Dependencies
|
|
241
|
+
|
|
242
|
+
- **Setup (Phase 1)**: No dependencies - verification only
|
|
243
|
+
- **Foundational (Phase 2)**: Depends on Setup - adds required types to src/types/index.ts
|
|
244
|
+
- **User Story 1 (Phase 3)**: Depends on Foundational - implements basic file copy with interactive prompts
|
|
245
|
+
- **User Story 2 (Phase 4)**: Depends on US1 complete - adds directory copy functionality
|
|
246
|
+
- **User Story 3 (Phase 5)**: Depends on US1 complete - adds production safety (can run in parallel with US2)
|
|
247
|
+
- **Polish (Phase 6)**: Depends on all user stories complete
|
|
248
|
+
|
|
249
|
+
### User Story Dependencies
|
|
250
|
+
|
|
251
|
+
- **User Story 1 (P1)**: Foundation → Basic file copy → Interactive prompts → SCP execution
|
|
252
|
+
- BLOCKS: US2, US3 (they extend US1 functionality)
|
|
253
|
+
|
|
254
|
+
- **User Story 2 (P2)**: US1 → Directory detection → -r flag validation → Recursive copy
|
|
255
|
+
- Can run in parallel with US3 (different features)
|
|
256
|
+
|
|
257
|
+
- **User Story 3 (P3)**: US1 → Production detection → Confirmation prompt → Safe execution
|
|
258
|
+
- Can run in parallel with US2 (different features)
|
|
259
|
+
|
|
260
|
+
### Within Each User Story
|
|
261
|
+
|
|
262
|
+
**User Story 1** (T007-T012):
|
|
263
|
+
|
|
264
|
+
- T007 (validateLocalPath) must complete first - foundational helper
|
|
265
|
+
- T008 (cloudScp main function) depends on T007
|
|
266
|
+
- T009 (export) depends on T008
|
|
267
|
+
- T010 (import) can run in parallel with T009 [P]
|
|
268
|
+
- T011 (register command) depends on T010
|
|
269
|
+
- T012 (build and test) depends on T011
|
|
270
|
+
|
|
271
|
+
**User Story 2** (T013-T016):
|
|
272
|
+
|
|
273
|
+
- T013 (add -r option) and T014 (directory detection) can run in parallel [P]
|
|
274
|
+
- T015 (update SCP command) depends on T014
|
|
275
|
+
- T016 (build and test) depends on T013, T014, T015
|
|
276
|
+
|
|
277
|
+
**User Story 3** (T017-T018):
|
|
278
|
+
|
|
279
|
+
- T017 (production confirmation) is single task
|
|
280
|
+
- T018 (build and test) depends on T017
|
|
281
|
+
|
|
282
|
+
### Parallel Opportunities
|
|
283
|
+
|
|
284
|
+
**Phase 1 (Setup)**:
|
|
285
|
+
|
|
286
|
+
- T002 and T003 can run in parallel [P]
|
|
287
|
+
|
|
288
|
+
**Phase 2 (Foundational)**:
|
|
289
|
+
|
|
290
|
+
- T004, T005, T006 can all run in parallel [P] - different interfaces in same file
|
|
291
|
+
|
|
292
|
+
**Phase 3 (US1)**:
|
|
293
|
+
|
|
294
|
+
- T009 and T010 can run in parallel [P] - different files
|
|
295
|
+
|
|
296
|
+
**Phase 4 (US2)**:
|
|
297
|
+
|
|
298
|
+
- T013 and T014 can run in parallel [P] - different parts of implementation
|
|
299
|
+
|
|
300
|
+
**Phase 5 (US3)**:
|
|
301
|
+
|
|
302
|
+
- Can run in parallel with Phase 4 (US2) if two developers available
|
|
303
|
+
|
|
304
|
+
**Phase 6 (Polish)**:
|
|
305
|
+
|
|
306
|
+
- T019, T020, T021, T022 can all run in parallel [P] - different review areas
|
|
307
|
+
|
|
308
|
+
---
|
|
309
|
+
|
|
310
|
+
## Parallel Example: User Story 1
|
|
311
|
+
|
|
312
|
+
```bash
|
|
313
|
+
# After Foundational phase completes:
|
|
314
|
+
|
|
315
|
+
# Launch T009 and T010 in parallel (different files):
|
|
316
|
+
Task A: "Export cloudScp function from src/commands/cloud.ts"
|
|
317
|
+
Task B: "Import cloudScp in src/hsh.ts"
|
|
318
|
+
|
|
319
|
+
# After both complete, continue with T011:
|
|
320
|
+
Task: "Register cloud scp subcommand in src/hsh.ts"
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
## Parallel Example: User Story 2 and 3
|
|
324
|
+
|
|
325
|
+
```bash
|
|
326
|
+
# After US1 completes, with 2 developers:
|
|
327
|
+
|
|
328
|
+
# Developer A works on US2:
|
|
329
|
+
Task: "Add -r/--recursive option to cloud scp command"
|
|
330
|
+
Task: "Add directory detection logic to cloudScp()"
|
|
331
|
+
Task: "Update SCP command construction for recursive flag"
|
|
332
|
+
|
|
333
|
+
# Developer B works on US3 (in parallel):
|
|
334
|
+
Task: "Add production confirmation prompt to cloudScp()"
|
|
335
|
+
Task: "Build and test production confirmation"
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
---
|
|
339
|
+
|
|
340
|
+
## Implementation Strategy
|
|
341
|
+
|
|
342
|
+
### MVP First (User Story 1 Only)
|
|
343
|
+
|
|
344
|
+
1. ✅ Complete Phase 1: Setup (verify existing infrastructure)
|
|
345
|
+
2. ✅ Complete Phase 2: Foundational (add SCP-specific types)
|
|
346
|
+
3. ✅ Complete Phase 3: User Story 1 (basic file copy with interactive prompts)
|
|
347
|
+
4. **STOP and VALIDATE**: Test file copying independently
|
|
348
|
+
5. Ready for basic usage!
|
|
349
|
+
|
|
350
|
+
**MVP Deliverable**: Developers can copy single files to cloud instances using interactive service/environment selection
|
|
351
|
+
|
|
352
|
+
### Incremental Delivery
|
|
353
|
+
|
|
354
|
+
1. Foundation → US1 → **MVP Release** (basic file copy)
|
|
355
|
+
2. US1 → US2 → **Enhanced Release** (add directory support)
|
|
356
|
+
3. US2 → US3 → **Production Ready** (add production safety)
|
|
357
|
+
4. US3 → Polish → **Final Release** (complete feature)
|
|
358
|
+
|
|
359
|
+
Each increment adds value without breaking previous functionality.
|
|
360
|
+
|
|
361
|
+
### Parallel Team Strategy
|
|
362
|
+
|
|
363
|
+
With 2 developers:
|
|
364
|
+
|
|
365
|
+
1. **Together**: Complete Setup + Foundational (quick - mostly verification)
|
|
366
|
+
2. **Together**: Complete User Story 1 (foundation for both US2 and US3)
|
|
367
|
+
3. **Split**:
|
|
368
|
+
- Developer A: User Story 2 (directory support)
|
|
369
|
+
- Developer B: User Story 3 (production safety)
|
|
370
|
+
4. **Together**: Polish & validation
|
|
371
|
+
|
|
372
|
+
---
|
|
373
|
+
|
|
374
|
+
## Notes
|
|
375
|
+
|
|
376
|
+
### Task Conventions
|
|
377
|
+
|
|
378
|
+
- [P] tasks = different files, no dependencies - can run in parallel
|
|
379
|
+
- [Story] label maps task to specific user story (US1, US2, US3)
|
|
380
|
+
- Each user story should be independently completable and testable
|
|
381
|
+
- Manual CLI testing approach (no automated test suite)
|
|
382
|
+
|
|
383
|
+
### File Modifications Summary
|
|
384
|
+
|
|
385
|
+
- **src/types/index.ts**: Add ScpOptions, PathValidationResult interfaces
|
|
386
|
+
- **src/commands/cloud.ts**: Add validateLocalPath(), cloudScp() functions
|
|
387
|
+
- **src/hsh.ts**: Add cloud scp subcommand registration
|
|
388
|
+
|
|
389
|
+
### Function Reuse
|
|
390
|
+
|
|
391
|
+
- ✅ validatePrivateKey() - from cloud.ts
|
|
392
|
+
- ✅ promptForService() - from cloud.ts
|
|
393
|
+
- ✅ promptForEnvironment() - from cloud.ts
|
|
394
|
+
- ✅ handleSSHError() - from cloud.ts
|
|
395
|
+
- ✅ readConfig() - from util.ts
|
|
396
|
+
|
|
397
|
+
### Error Handling Layers
|
|
398
|
+
|
|
399
|
+
1. Path validation (validateLocalPath)
|
|
400
|
+
2. Configuration validation (service/environment existence)
|
|
401
|
+
3. Recursive flag validation (directory requires -r)
|
|
402
|
+
4. Production confirmation (explicit user consent)
|
|
403
|
+
5. SSH/SCP execution errors (handleSSHError)
|
|
404
|
+
|
|
405
|
+
### Testing Strategy
|
|
406
|
+
|
|
407
|
+
- Manual CLI testing following quickstart.md scenarios
|
|
408
|
+
- Test each user story independently before moving to next
|
|
409
|
+
- Regression test previous stories when adding new functionality
|
|
410
|
+
- End-to-end testing from different directories after global install
|
|
411
|
+
|
|
412
|
+
---
|
|
413
|
+
|
|
414
|
+
## Total Task Count: 24 tasks
|
|
415
|
+
|
|
416
|
+
**By Phase**:
|
|
417
|
+
|
|
418
|
+
- Phase 1 (Setup): 3 tasks
|
|
419
|
+
- Phase 2 (Foundational): 3 tasks
|
|
420
|
+
- Phase 3 (US1 - MVP): 6 tasks
|
|
421
|
+
- Phase 4 (US2): 4 tasks
|
|
422
|
+
- Phase 5 (US3): 2 tasks
|
|
423
|
+
- Phase 6 (Polish): 6 tasks
|
|
424
|
+
|
|
425
|
+
**By User Story**:
|
|
426
|
+
|
|
427
|
+
- User Story 1 (Quick File Deploy): 6 tasks
|
|
428
|
+
- User Story 2 (Directory Upload): 4 tasks
|
|
429
|
+
- User Story 3 (Interactive Service Selection / Production Safety): 2 tasks
|
|
430
|
+
- Infrastructure & Polish: 12 tasks
|
|
431
|
+
|
|
432
|
+
**Parallel Opportunities**: 11 tasks marked [P] can potentially run in parallel
|
|
433
|
+
|
|
434
|
+
**Suggested MVP Scope**: Phase 1 + Phase 2 + Phase 3 (12 tasks) = Basic file copy functionality
|
package/src/ai-summon.ts
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { Command } from 'commander';
|
|
3
|
+
import { getPackageJson } from './util.js';
|
|
4
|
+
import { openIDE, refreshIdeReposCache } from './commands/ide/index.js';
|
|
5
|
+
import { addUrl, openUrlGroup, removeUrl, searchAndOpenUrl } from './commands/url.js';
|
|
6
|
+
import { initConfig } from './commands/init.js';
|
|
7
|
+
|
|
8
|
+
const packageJson = getPackageJson();
|
|
9
|
+
|
|
10
|
+
const program = new Command();
|
|
11
|
+
|
|
12
|
+
program.usage('<command> [options]');
|
|
13
|
+
program.version(packageJson.version);
|
|
14
|
+
|
|
15
|
+
program
|
|
16
|
+
.command('init')
|
|
17
|
+
.description('initialize ~/.ai/config.json (prompts for workingDirectory)')
|
|
18
|
+
.option('-w, --working-directory <path>', 'set workingDirectory without prompting')
|
|
19
|
+
.option('-f, --force', 'overwrite existing config without confirmation')
|
|
20
|
+
.action(async (options: { workingDirectory?: string; force?: boolean }) => {
|
|
21
|
+
await initConfig({ workingDirectory: options.workingDirectory, force: options.force });
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
const cursor = program.command('cursor').description('open project in Cursor');
|
|
25
|
+
cursor
|
|
26
|
+
.argument('[search]', 'optional search keyword for fuzzy search')
|
|
27
|
+
.action(async (search?: string) => {
|
|
28
|
+
await openIDE('cursor', search);
|
|
29
|
+
});
|
|
30
|
+
cursor
|
|
31
|
+
.command('refresh')
|
|
32
|
+
.description('refresh cached auto-discovered repositories (workingDirectory mode)')
|
|
33
|
+
.action(async () => {
|
|
34
|
+
await refreshIdeReposCache();
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
const claude = program.command('claude').description('open project in Claude');
|
|
38
|
+
claude
|
|
39
|
+
.argument('[search]', 'optional search keyword for fuzzy search')
|
|
40
|
+
.action(async (search?: string) => {
|
|
41
|
+
await openIDE('claude', search);
|
|
42
|
+
});
|
|
43
|
+
claude
|
|
44
|
+
.command('refresh')
|
|
45
|
+
.description('refresh cached auto-discovered repositories (workingDirectory mode)')
|
|
46
|
+
.action(async () => {
|
|
47
|
+
await refreshIdeReposCache();
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
// URL management commands
|
|
51
|
+
const urlCommand = program.command('url').description('URL bookmark management');
|
|
52
|
+
|
|
53
|
+
urlCommand
|
|
54
|
+
.command('add')
|
|
55
|
+
.description('Add a new URL bookmark')
|
|
56
|
+
.argument('<name>', 'Name of the URL bookmark')
|
|
57
|
+
.argument('<url>', 'URL to bookmark')
|
|
58
|
+
.action(async (name: string, url: string) => {
|
|
59
|
+
await addUrl(name, url);
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
urlCommand
|
|
63
|
+
.command('remove')
|
|
64
|
+
.description('Remove a URL bookmark')
|
|
65
|
+
.argument(
|
|
66
|
+
'[name]',
|
|
67
|
+
'Name of the URL bookmark to remove (optional, will enter search mode if not provided)'
|
|
68
|
+
)
|
|
69
|
+
.action(async (name?: string) => {
|
|
70
|
+
await removeUrl(name);
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
urlCommand
|
|
74
|
+
.command('search')
|
|
75
|
+
.description('Search and open a URL bookmark in Chrome')
|
|
76
|
+
.option('--suppress', 'Auto-dismiss popups by simulating Enter key after 1s')
|
|
77
|
+
.action(async (options: { suppress?: boolean }) => {
|
|
78
|
+
await searchAndOpenUrl(options.suppress);
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
urlCommand
|
|
82
|
+
.command('group')
|
|
83
|
+
.description('Select and open a URL group in a new Chrome window')
|
|
84
|
+
.action(async () => {
|
|
85
|
+
await openUrlGroup();
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
program.parse();
|