@howlil/ez-agents 3.4.2 → 3.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +77 -2
- package/agents/ez-observer-agent.md +260 -0
- package/agents/ez-release-agent.md +333 -0
- package/agents/ez-requirements-agent.md +377 -0
- package/agents/ez-scrum-master-agent.md +242 -0
- package/agents/ez-tech-lead-agent.md +267 -0
- package/bin/install.js +3221 -3272
- package/commands/ez/arch-review.md +102 -0
- package/commands/ez/execute-phase.md +11 -0
- package/commands/ez/export-session.md +79 -0
- package/commands/ez/gather-requirements.md +117 -0
- package/commands/ez/git-workflow.md +72 -0
- package/commands/ez/hotfix.md +120 -0
- package/commands/ez/import-session.md +82 -0
- package/commands/ez/list-sessions.md +96 -0
- package/commands/ez/package-manager.md +316 -0
- package/commands/ez/plan-phase.md +9 -1
- package/commands/ez/preflight.md +79 -0
- package/commands/ez/progress.md +13 -1
- package/commands/ez/release.md +153 -0
- package/commands/ez/resume.md +107 -0
- package/commands/ez/standup.md +85 -0
- package/ez-agents/bin/ez-tools.cjs +1095 -716
- package/ez-agents/bin/lib/bdd-validator.cjs +622 -0
- package/ez-agents/bin/lib/content-scanner.cjs +238 -0
- package/ez-agents/bin/lib/context-cache.cjs +154 -0
- package/ez-agents/bin/lib/context-errors.cjs +71 -0
- package/ez-agents/bin/lib/context-manager.cjs +220 -0
- package/ez-agents/bin/lib/discussion-synthesizer.cjs +458 -0
- package/ez-agents/bin/lib/file-access.cjs +207 -0
- package/ez-agents/bin/lib/git-errors.cjs +83 -0
- package/ez-agents/bin/lib/git-utils.cjs +321 -203
- package/ez-agents/bin/lib/git-workflow-engine.cjs +1157 -0
- package/ez-agents/bin/lib/index.cjs +46 -2
- package/ez-agents/bin/lib/lockfile-validator.cjs +227 -0
- package/ez-agents/bin/lib/logger.cjs +124 -154
- package/ez-agents/bin/lib/memory-compression.cjs +256 -0
- package/ez-agents/bin/lib/metrics-tracker.cjs +406 -0
- package/ez-agents/bin/lib/package-manager-detector.cjs +203 -0
- package/ez-agents/bin/lib/package-manager-executor.cjs +385 -0
- package/ez-agents/bin/lib/package-manager-service.cjs +216 -0
- package/ez-agents/bin/lib/release-validator.cjs +614 -0
- package/ez-agents/bin/lib/safe-exec.cjs +128 -214
- package/ez-agents/bin/lib/session-chain.cjs +304 -0
- package/ez-agents/bin/lib/session-errors.cjs +81 -0
- package/ez-agents/bin/lib/session-export.cjs +251 -0
- package/ez-agents/bin/lib/session-import.cjs +262 -0
- package/ez-agents/bin/lib/session-manager.cjs +280 -0
- package/ez-agents/bin/lib/tier-manager.cjs +428 -0
- package/ez-agents/bin/lib/url-fetch.cjs +170 -0
- package/ez-agents/references/metrics-schema.md +118 -0
- package/ez-agents/references/planning-config.md +140 -0
- package/ez-agents/references/tier-strategy.md +103 -0
- package/ez-agents/templates/bdd-feature.md +173 -0
- package/ez-agents/templates/discussion.md +68 -0
- package/ez-agents/templates/incident-runbook.md +205 -0
- package/ez-agents/templates/release-checklist.md +133 -0
- package/ez-agents/templates/rollback-plan.md +201 -0
- package/ez-agents/workflows/arch-review.md +54 -0
- package/ez-agents/workflows/autonomous.md +844 -743
- package/ez-agents/workflows/execute-phase.md +45 -0
- package/ez-agents/workflows/export-session.md +255 -0
- package/ez-agents/workflows/gather-requirements.md +206 -0
- package/ez-agents/workflows/help.md +92 -0
- package/ez-agents/workflows/hotfix.md +291 -0
- package/ez-agents/workflows/import-session.md +303 -0
- package/ez-agents/workflows/new-milestone.md +713 -384
- package/ez-agents/workflows/new-project.md +1107 -1113
- package/ez-agents/workflows/plan-phase.md +22 -0
- package/ez-agents/workflows/progress.md +15 -25
- package/ez-agents/workflows/release.md +253 -0
- package/ez-agents/workflows/resume-session.md +215 -0
- package/ez-agents/workflows/standup.md +64 -0
- package/package.json +9 -2
|
@@ -1,716 +1,1095 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* EZ Tools — CLI utility for EZ Agents workflow operations
|
|
5
|
-
*
|
|
6
|
-
* Replaces repetitive inline bash patterns across ~50 EZ Agents command/workflow/agent files.
|
|
7
|
-
* Centralizes: config parsing, model resolution, phase lookup, git commits, summary verification.
|
|
8
|
-
*
|
|
9
|
-
* Usage: node ez-tools.cjs <command> [args] [--raw]
|
|
10
|
-
*
|
|
11
|
-
* Atomic Commands:
|
|
12
|
-
* state load Load project config + state
|
|
13
|
-
* state json Output STATE.md frontmatter as JSON
|
|
14
|
-
* state update <field> <value> Update a STATE.md field
|
|
15
|
-
* state get [section] Get STATE.md content or section
|
|
16
|
-
* state patch --field val ... Batch update STATE.md fields
|
|
17
|
-
* resolve-model <agent-type> Get model for agent based on profile
|
|
18
|
-
* find-phase <phase> Find phase directory by number
|
|
19
|
-
* commit <message> [--files f1 f2] Commit planning docs
|
|
20
|
-
* verify-summary <path> Verify a SUMMARY.md file
|
|
21
|
-
* generate-slug <text> Convert text to URL-safe slug
|
|
22
|
-
* current-timestamp [format] Get timestamp (full|date|filename)
|
|
23
|
-
* list-todos [area] Count and enumerate pending todos
|
|
24
|
-
* verify-path-exists <path> Check file/directory existence
|
|
25
|
-
* config-ensure-section Initialize .planning/config.json
|
|
26
|
-
* history-digest Aggregate all SUMMARY.md data
|
|
27
|
-
* summary-extract <path> [--fields] Extract structured data from SUMMARY.md
|
|
28
|
-
* state-snapshot Structured parse of STATE.md
|
|
29
|
-
* phase-plan-index <phase> Index plans with waves and status
|
|
30
|
-
* websearch <query> Search web via Brave API (if configured)
|
|
31
|
-
* [--limit N] [--freshness day|week|month]
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
*
|
|
61
|
-
*
|
|
62
|
-
*
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
*
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
-
*
|
|
72
|
-
*
|
|
73
|
-
*
|
|
74
|
-
* --
|
|
75
|
-
*
|
|
76
|
-
*
|
|
77
|
-
* frontmatter
|
|
78
|
-
*
|
|
79
|
-
*
|
|
80
|
-
*
|
|
81
|
-
*
|
|
82
|
-
*
|
|
83
|
-
*
|
|
84
|
-
*
|
|
85
|
-
*
|
|
86
|
-
* verify
|
|
87
|
-
*
|
|
88
|
-
*
|
|
89
|
-
*
|
|
90
|
-
*
|
|
91
|
-
*
|
|
92
|
-
*
|
|
93
|
-
*
|
|
94
|
-
*
|
|
95
|
-
*
|
|
96
|
-
*
|
|
97
|
-
*
|
|
98
|
-
*
|
|
99
|
-
*
|
|
100
|
-
*
|
|
101
|
-
* --
|
|
102
|
-
*
|
|
103
|
-
*
|
|
104
|
-
* state
|
|
105
|
-
*
|
|
106
|
-
*
|
|
107
|
-
*
|
|
108
|
-
*
|
|
109
|
-
* state
|
|
110
|
-
*
|
|
111
|
-
* --
|
|
112
|
-
*
|
|
113
|
-
*
|
|
114
|
-
*
|
|
115
|
-
*
|
|
116
|
-
*
|
|
117
|
-
*
|
|
118
|
-
*
|
|
119
|
-
*
|
|
120
|
-
* init
|
|
121
|
-
* init
|
|
122
|
-
* init
|
|
123
|
-
* init
|
|
124
|
-
* init
|
|
125
|
-
* init
|
|
126
|
-
* init
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
const
|
|
135
|
-
const
|
|
136
|
-
const
|
|
137
|
-
const
|
|
138
|
-
const
|
|
139
|
-
const
|
|
140
|
-
const
|
|
141
|
-
const
|
|
142
|
-
const
|
|
143
|
-
const
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
error('
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
state.
|
|
201
|
-
} else if (subcommand === '
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
const
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
const
|
|
219
|
-
const
|
|
220
|
-
const
|
|
221
|
-
const
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
const
|
|
238
|
-
state.
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
case '
|
|
283
|
-
const
|
|
284
|
-
const
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
if (
|
|
290
|
-
console.log(
|
|
291
|
-
} else {
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
const
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
const
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
} else {
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
} else
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
} else if (subcommand === '
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
} else
|
|
459
|
-
|
|
460
|
-
}
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
}
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
}
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
const
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* EZ Tools — CLI utility for EZ Agents workflow operations
|
|
5
|
+
*
|
|
6
|
+
* Replaces repetitive inline bash patterns across ~50 EZ Agents command/workflow/agent files.
|
|
7
|
+
* Centralizes: config parsing, model resolution, phase lookup, git commits, summary verification.
|
|
8
|
+
*
|
|
9
|
+
* Usage: node ez-tools.cjs <command> [args] [--raw]
|
|
10
|
+
*
|
|
11
|
+
* Atomic Commands:
|
|
12
|
+
* state load Load project config + state
|
|
13
|
+
* state json Output STATE.md frontmatter as JSON
|
|
14
|
+
* state update <field> <value> Update a STATE.md field
|
|
15
|
+
* state get [section] Get STATE.md content or section
|
|
16
|
+
* state patch --field val ... Batch update STATE.md fields
|
|
17
|
+
* resolve-model <agent-type> Get model for agent based on profile
|
|
18
|
+
* find-phase <phase> Find phase directory by number
|
|
19
|
+
* commit <message> [--files f1 f2] Commit planning docs
|
|
20
|
+
* verify-summary <path> Verify a SUMMARY.md file
|
|
21
|
+
* generate-slug <text> Convert text to URL-safe slug
|
|
22
|
+
* current-timestamp [format] Get timestamp (full|date|filename)
|
|
23
|
+
* list-todos [area] Count and enumerate pending todos
|
|
24
|
+
* verify-path-exists <path> Check file/directory existence
|
|
25
|
+
* config-ensure-section Initialize .planning/config.json
|
|
26
|
+
* history-digest Aggregate all SUMMARY.md data
|
|
27
|
+
* summary-extract <path> [--fields] Extract structured data from SUMMARY.md
|
|
28
|
+
* state-snapshot Structured parse of STATE.md
|
|
29
|
+
* phase-plan-index <phase> Index plans with waves and status
|
|
30
|
+
* websearch <query> Search web via Brave API (if configured)
|
|
31
|
+
* [--limit N] [--freshness day|week|month]
|
|
32
|
+
*
|
|
33
|
+
* Context Access Commands:
|
|
34
|
+
* context read <pattern> Read local files using glob patterns
|
|
35
|
+
* context fetch <url> Fetch content from URL (HTTPS only, requires confirmation)
|
|
36
|
+
* context request Interactive context gathering mode
|
|
37
|
+
*
|
|
38
|
+
* Phase Operations:
|
|
39
|
+
* phase next-decimal <phase> Calculate next decimal phase number
|
|
40
|
+
* phase add <description> Append new phase to roadmap + create dir
|
|
41
|
+
* phase insert <after> <description> Insert decimal phase after existing
|
|
42
|
+
* phase remove <phase> [--force] Remove phase, renumber all subsequent
|
|
43
|
+
* phase complete <phase> Mark phase done, update state + roadmap
|
|
44
|
+
*
|
|
45
|
+
* Roadmap Operations:
|
|
46
|
+
* roadmap get-phase <phase> Extract phase section from ROADMAP.md
|
|
47
|
+
* roadmap analyze Full roadmap parse with disk status
|
|
48
|
+
* roadmap update-plan-progress <N> Update progress table row from disk (PLAN vs SUMMARY counts)
|
|
49
|
+
*
|
|
50
|
+
* Requirements Operations:
|
|
51
|
+
* requirements mark-complete <ids> Mark requirement IDs as complete in REQUIREMENTS.md
|
|
52
|
+
* Accepts: REQ-01,REQ-02 or REQ-01 REQ-02 or [REQ-01, REQ-02]
|
|
53
|
+
*
|
|
54
|
+
* Milestone Operations:
|
|
55
|
+
* milestone complete <version> Archive milestone, create MILESTONES.md
|
|
56
|
+
* [--name <name>]
|
|
57
|
+
* [--archive-phases] Move phase dirs to milestones/vX.Y-phases/
|
|
58
|
+
*
|
|
59
|
+
* Validation:
|
|
60
|
+
* validate consistency Check phase numbering, disk/roadmap sync
|
|
61
|
+
* validate health [--repair] Check .planning/ integrity, optionally repair
|
|
62
|
+
*
|
|
63
|
+
* Progress:
|
|
64
|
+
* progress [json|table|bar] Render progress in various formats
|
|
65
|
+
*
|
|
66
|
+
* Todos:
|
|
67
|
+
* todo complete <filename> Move todo from pending to completed
|
|
68
|
+
*
|
|
69
|
+
* Scaffolding:
|
|
70
|
+
* scaffold context --phase <N> Create CONTEXT.md template
|
|
71
|
+
* scaffold uat --phase <N> Create UAT.md template
|
|
72
|
+
* scaffold verification --phase <N> Create VERIFICATION.md template
|
|
73
|
+
* scaffold phase-dir --phase <N> Create phase directory
|
|
74
|
+
* --name <name>
|
|
75
|
+
*
|
|
76
|
+
* Frontmatter CRUD:
|
|
77
|
+
* frontmatter get <file> [--field k] Extract frontmatter as JSON
|
|
78
|
+
* frontmatter set <file> --field k Update single frontmatter field
|
|
79
|
+
* --value jsonVal
|
|
80
|
+
* frontmatter merge <file> Merge JSON into frontmatter
|
|
81
|
+
* --data '{json}'
|
|
82
|
+
* frontmatter validate <file> Validate required fields
|
|
83
|
+
* --schema plan|summary|verification
|
|
84
|
+
*
|
|
85
|
+
* Verification Suite:
|
|
86
|
+
* verify plan-structure <file> Check PLAN.md structure + tasks
|
|
87
|
+
* verify phase-completeness <phase> Check all plans have summaries
|
|
88
|
+
* verify references <file> Check @-refs + paths resolve
|
|
89
|
+
* verify commits <h1> [h2] ... Batch verify commit hashes
|
|
90
|
+
* verify artifacts <plan-file> Check must_haves.artifacts
|
|
91
|
+
* verify key-links <plan-file> Check must_haves.key_links
|
|
92
|
+
*
|
|
93
|
+
* Template Fill:
|
|
94
|
+
* template fill summary --phase N Create pre-filled SUMMARY.md
|
|
95
|
+
* [--plan M] [--name "..."]
|
|
96
|
+
* [--fields '{json}']
|
|
97
|
+
* template fill plan --phase N Create pre-filled PLAN.md
|
|
98
|
+
* [--plan M] [--type execute|tdd]
|
|
99
|
+
* [--wave N] [--fields '{json}']
|
|
100
|
+
* template fill verification Create pre-filled VERIFICATION.md
|
|
101
|
+
* --phase N [--fields '{json}']
|
|
102
|
+
*
|
|
103
|
+
* State Progression:
|
|
104
|
+
* state advance-plan Increment plan counter
|
|
105
|
+
* state record-metric --phase N Record execution metrics
|
|
106
|
+
* --plan M --duration Xmin
|
|
107
|
+
* [--tasks N] [--files N]
|
|
108
|
+
* state update-progress Recalculate progress bar
|
|
109
|
+
* state add-decision --summary "..." Add decision to STATE.md
|
|
110
|
+
* [--phase N] [--rationale "..."]
|
|
111
|
+
* [--summary-file path] [--rationale-file path]
|
|
112
|
+
* state add-blocker --text "..." Add blocker
|
|
113
|
+
* [--text-file path]
|
|
114
|
+
* state resolve-blocker --text "..." Remove blocker
|
|
115
|
+
* state record-session Update session continuity
|
|
116
|
+
* --stopped-at "..."
|
|
117
|
+
* [--resume-file path]
|
|
118
|
+
*
|
|
119
|
+
* Compound Commands (workflow-specific initialization):
|
|
120
|
+
* init execute-phase <phase> All context for execute-phase workflow
|
|
121
|
+
* init plan-phase <phase> All context for plan-phase workflow
|
|
122
|
+
* init new-project All context for new-project workflow
|
|
123
|
+
* init new-milestone All context for new-milestone workflow
|
|
124
|
+
* init quick <description> All context for quick workflow
|
|
125
|
+
* init resume All context for resume-project workflow
|
|
126
|
+
* init verify-work <phase> All context for verify-work workflow
|
|
127
|
+
* init phase-op <phase> Generic phase operation context
|
|
128
|
+
* init todos [area] All context for todo workflows
|
|
129
|
+
* init milestone-op All context for milestone operations
|
|
130
|
+
* init map-codebase All context for map-codebase workflow
|
|
131
|
+
* init progress All context for progress workflow
|
|
132
|
+
*/
|
|
133
|
+
|
|
134
|
+
const fs = require('fs');
|
|
135
|
+
const path = require('path');
|
|
136
|
+
const { error } = require('./lib/core.cjs');
|
|
137
|
+
const state = require('./lib/state.cjs');
|
|
138
|
+
const phase = require('./lib/phase.cjs');
|
|
139
|
+
const roadmap = require('./lib/roadmap.cjs');
|
|
140
|
+
const verify = require('./lib/verify.cjs');
|
|
141
|
+
const config = require('./lib/config.cjs');
|
|
142
|
+
const template = require('./lib/template.cjs');
|
|
143
|
+
const milestone = require('./lib/milestone.cjs');
|
|
144
|
+
const commands = require('./lib/commands.cjs');
|
|
145
|
+
const init = require('./lib/init.cjs');
|
|
146
|
+
const frontmatter = require('./lib/frontmatter.cjs');
|
|
147
|
+
const HealthCheck = require('./lib/health-check.cjs');
|
|
148
|
+
const auth = require('./lib/auth.cjs');
|
|
149
|
+
const FileAccessService = require('./lib/file-access.cjs');
|
|
150
|
+
const URLFetchService = require('./lib/url-fetch.cjs');
|
|
151
|
+
const ContextManager = require('./lib/context-manager.cjs');
|
|
152
|
+
const PackageManagerService = require('./lib/package-manager-service.cjs');
|
|
153
|
+
|
|
154
|
+
// Session management modules
|
|
155
|
+
const SessionManager = require('./lib/session-manager.cjs');
|
|
156
|
+
const SessionExport = require('./lib/session-export.cjs');
|
|
157
|
+
const SessionImport = require('./lib/session-import.cjs');
|
|
158
|
+
const SessionChain = require('./lib/session-chain.cjs');
|
|
159
|
+
const MemoryCompression = require('./lib/memory-compression.cjs');
|
|
160
|
+
|
|
161
|
+
// ─── CLI Router ───────────────────────────────────────────────────────────────
|
|
162
|
+
|
|
163
|
+
async function main() {
|
|
164
|
+
const args = process.argv.slice(2);
|
|
165
|
+
|
|
166
|
+
// Optional cwd override for sandboxed subagents running outside project root.
|
|
167
|
+
let cwd = process.cwd();
|
|
168
|
+
const cwdEqArg = args.find(arg => arg.startsWith('--cwd='));
|
|
169
|
+
const cwdIdx = args.indexOf('--cwd');
|
|
170
|
+
if (cwdEqArg) {
|
|
171
|
+
const value = cwdEqArg.slice('--cwd='.length).trim();
|
|
172
|
+
if (!value) error('Missing value for --cwd');
|
|
173
|
+
args.splice(args.indexOf(cwdEqArg), 1);
|
|
174
|
+
cwd = path.resolve(value);
|
|
175
|
+
} else if (cwdIdx !== -1) {
|
|
176
|
+
const value = args[cwdIdx + 1];
|
|
177
|
+
if (!value || value.startsWith('--')) error('Missing value for --cwd');
|
|
178
|
+
args.splice(cwdIdx, 2);
|
|
179
|
+
cwd = path.resolve(value);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
if (!fs.existsSync(cwd) || !fs.statSync(cwd).isDirectory()) {
|
|
183
|
+
error(`Invalid --cwd: ${cwd}`);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
const rawIndex = args.indexOf('--raw');
|
|
187
|
+
const raw = rawIndex !== -1;
|
|
188
|
+
if (rawIndex !== -1) args.splice(rawIndex, 1);
|
|
189
|
+
|
|
190
|
+
const command = args[0];
|
|
191
|
+
|
|
192
|
+
if (!command) {
|
|
193
|
+
error('Usage: ez-tools <command> [args] [--raw] [--cwd <path>]\nCommands: state, resolve-model, find-phase, commit, verify-summary, verify, frontmatter, template, generate-slug, current-timestamp, list-todos, verify-path-exists, config-ensure-section, init, health, session, resume, export-session, import-session, chain, context');
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
switch (command) {
|
|
197
|
+
case 'state': {
|
|
198
|
+
const subcommand = args[1];
|
|
199
|
+
if (subcommand === 'json') {
|
|
200
|
+
state.cmdStateJson(cwd, raw);
|
|
201
|
+
} else if (subcommand === 'update') {
|
|
202
|
+
state.cmdStateUpdate(cwd, args[2], args[3]);
|
|
203
|
+
} else if (subcommand === 'get') {
|
|
204
|
+
state.cmdStateGet(cwd, args[2], raw);
|
|
205
|
+
} else if (subcommand === 'patch') {
|
|
206
|
+
const patches = {};
|
|
207
|
+
for (let i = 2; i < args.length; i += 2) {
|
|
208
|
+
const key = args[i].replace(/^--/, '');
|
|
209
|
+
const value = args[i + 1];
|
|
210
|
+
if (key && value !== undefined) {
|
|
211
|
+
patches[key] = value;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
state.cmdStatePatch(cwd, patches, raw);
|
|
215
|
+
} else if (subcommand === 'advance-plan') {
|
|
216
|
+
state.cmdStateAdvancePlan(cwd, raw);
|
|
217
|
+
} else if (subcommand === 'record-metric') {
|
|
218
|
+
const phaseIdx = args.indexOf('--phase');
|
|
219
|
+
const planIdx = args.indexOf('--plan');
|
|
220
|
+
const durationIdx = args.indexOf('--duration');
|
|
221
|
+
const tasksIdx = args.indexOf('--tasks');
|
|
222
|
+
const filesIdx = args.indexOf('--files');
|
|
223
|
+
state.cmdStateRecordMetric(cwd, {
|
|
224
|
+
phase: phaseIdx !== -1 ? args[phaseIdx + 1] : null,
|
|
225
|
+
plan: planIdx !== -1 ? args[planIdx + 1] : null,
|
|
226
|
+
duration: durationIdx !== -1 ? args[durationIdx + 1] : null,
|
|
227
|
+
tasks: tasksIdx !== -1 ? args[tasksIdx + 1] : null,
|
|
228
|
+
files: filesIdx !== -1 ? args[filesIdx + 1] : null,
|
|
229
|
+
}, raw);
|
|
230
|
+
} else if (subcommand === 'update-progress') {
|
|
231
|
+
state.cmdStateUpdateProgress(cwd, raw);
|
|
232
|
+
} else if (subcommand === 'add-decision') {
|
|
233
|
+
const phaseIdx = args.indexOf('--phase');
|
|
234
|
+
const summaryIdx = args.indexOf('--summary');
|
|
235
|
+
const summaryFileIdx = args.indexOf('--summary-file');
|
|
236
|
+
const rationaleIdx = args.indexOf('--rationale');
|
|
237
|
+
const rationaleFileIdx = args.indexOf('--rationale-file');
|
|
238
|
+
state.cmdStateAddDecision(cwd, {
|
|
239
|
+
phase: phaseIdx !== -1 ? args[phaseIdx + 1] : null,
|
|
240
|
+
summary: summaryIdx !== -1 ? args[summaryIdx + 1] : null,
|
|
241
|
+
summary_file: summaryFileIdx !== -1 ? args[summaryFileIdx + 1] : null,
|
|
242
|
+
rationale: rationaleIdx !== -1 ? args[rationaleIdx + 1] : '',
|
|
243
|
+
rationale_file: rationaleFileIdx !== -1 ? args[rationaleFileIdx + 1] : null,
|
|
244
|
+
}, raw);
|
|
245
|
+
} else if (subcommand === 'add-blocker') {
|
|
246
|
+
const textIdx = args.indexOf('--text');
|
|
247
|
+
const textFileIdx = args.indexOf('--text-file');
|
|
248
|
+
state.cmdStateAddBlocker(cwd, {
|
|
249
|
+
text: textIdx !== -1 ? args[textIdx + 1] : null,
|
|
250
|
+
text_file: textFileIdx !== -1 ? args[textFileIdx + 1] : null,
|
|
251
|
+
}, raw);
|
|
252
|
+
} else if (subcommand === 'resolve-blocker') {
|
|
253
|
+
const textIdx = args.indexOf('--text');
|
|
254
|
+
state.cmdStateResolveBlocker(cwd, textIdx !== -1 ? args[textIdx + 1] : null, raw);
|
|
255
|
+
} else if (subcommand === 'record-session') {
|
|
256
|
+
const stoppedIdx = args.indexOf('--stopped-at');
|
|
257
|
+
const resumeIdx = args.indexOf('--resume-file');
|
|
258
|
+
state.cmdStateRecordSession(cwd, {
|
|
259
|
+
stopped_at: stoppedIdx !== -1 ? args[stoppedIdx + 1] : null,
|
|
260
|
+
resume_file: resumeIdx !== -1 ? args[resumeIdx + 1] : 'None',
|
|
261
|
+
}, raw);
|
|
262
|
+
} else {
|
|
263
|
+
state.cmdStateLoad(cwd, raw);
|
|
264
|
+
}
|
|
265
|
+
break;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
case 'health': {
|
|
269
|
+
const health = new HealthCheck();
|
|
270
|
+
const result = health.runAll();
|
|
271
|
+
console.log(JSON.stringify(result, null, 2));
|
|
272
|
+
break;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
case 'auth': {
|
|
276
|
+
const subcommand = args[1];
|
|
277
|
+
if (!subcommand) {
|
|
278
|
+
error('Usage: ez-tools auth <save|list|delete|test> [provider] [secret]\nSubcommands: save, list, delete, test');
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
switch (subcommand) {
|
|
282
|
+
case 'save': {
|
|
283
|
+
const provider = args[2];
|
|
284
|
+
const secret = args[3];
|
|
285
|
+
if (!provider || !secret) {
|
|
286
|
+
error('Usage: ez-tools auth save <provider> <secret>');
|
|
287
|
+
}
|
|
288
|
+
const success = await auth.saveCredential(provider, secret);
|
|
289
|
+
if (success) {
|
|
290
|
+
console.log(`✓ Credential saved for ${provider}`);
|
|
291
|
+
} else {
|
|
292
|
+
console.error('Failed to save credential');
|
|
293
|
+
process.exit(1);
|
|
294
|
+
}
|
|
295
|
+
break;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
case 'list': {
|
|
299
|
+
const providers = await auth.listProviders();
|
|
300
|
+
const usingKeychain = auth.isKeychainAvailable();
|
|
301
|
+
|
|
302
|
+
console.log('');
|
|
303
|
+
console.log('Provider Storage');
|
|
304
|
+
console.log('─────────────────────────');
|
|
305
|
+
if (providers.length === 0) {
|
|
306
|
+
console.log('No credentials stored');
|
|
307
|
+
} else {
|
|
308
|
+
for (const p of providers) {
|
|
309
|
+
const storage = usingKeychain ? 'Keychain ✓' : 'File (fallback)';
|
|
310
|
+
console.log(`${p.padEnd(14)} ${storage}`);
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
if (!usingKeychain) {
|
|
314
|
+
console.log('');
|
|
315
|
+
console.log('⚠ Using file storage — consider installing keytar for better security');
|
|
316
|
+
}
|
|
317
|
+
break;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
case 'delete': {
|
|
321
|
+
const provider = args[2];
|
|
322
|
+
const force = args.includes('--force');
|
|
323
|
+
if (!provider) {
|
|
324
|
+
error('Usage: ez-tools auth delete <provider> [--force]');
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
if (!force) {
|
|
328
|
+
const readline = require('readline');
|
|
329
|
+
const rl = readline.createInterface({
|
|
330
|
+
input: process.stdin,
|
|
331
|
+
output: process.stdout
|
|
332
|
+
});
|
|
333
|
+
|
|
334
|
+
const answer = await new Promise(resolve => {
|
|
335
|
+
rl.question(`Delete credential for ${provider}? [y/N] `, resolve);
|
|
336
|
+
rl.close();
|
|
337
|
+
});
|
|
338
|
+
|
|
339
|
+
if (answer.toLowerCase() !== 'y') {
|
|
340
|
+
console.log('Delete cancelled');
|
|
341
|
+
break;
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
const success = await auth.deleteCredential(provider);
|
|
346
|
+
if (success) {
|
|
347
|
+
console.log(`✓ Credential deleted for ${provider}`);
|
|
348
|
+
} else {
|
|
349
|
+
console.error(`No credential found for ${provider}`);
|
|
350
|
+
process.exit(1);
|
|
351
|
+
}
|
|
352
|
+
break;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
case 'test': {
|
|
356
|
+
const usingKeychain = auth.isKeychainAvailable();
|
|
357
|
+
const providers = await auth.listProviders();
|
|
358
|
+
|
|
359
|
+
console.log('');
|
|
360
|
+
console.log('Credential System Test');
|
|
361
|
+
console.log('══════════════════════');
|
|
362
|
+
console.log(`Keychain (keytar): ${usingKeychain ? 'Available ✓' : 'Unavailable'}`);
|
|
363
|
+
console.log(`Storage mode: ${usingKeychain ? 'System keychain' : 'Fallback file'}`);
|
|
364
|
+
console.log('');
|
|
365
|
+
console.log(`Stored providers: ${providers.length}`);
|
|
366
|
+
if (providers.length > 0) {
|
|
367
|
+
console.log(` ${providers.join(', ')}`);
|
|
368
|
+
}
|
|
369
|
+
if (!usingKeychain) {
|
|
370
|
+
console.log('');
|
|
371
|
+
console.log('Tip: Install keytar for better security:');
|
|
372
|
+
console.log(' npm install keytar');
|
|
373
|
+
}
|
|
374
|
+
break;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
default: {
|
|
378
|
+
error('Unknown auth subcommand: ' + subcommand + '\nValid: save, list, delete, test');
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
break;
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
case 'resolve-model': {
|
|
385
|
+
commands.cmdResolveModel(cwd, args[1], raw);
|
|
386
|
+
break;
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
case 'find-phase': {
|
|
390
|
+
phase.cmdFindPhase(cwd, args[1], raw);
|
|
391
|
+
break;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
case 'commit': {
|
|
395
|
+
const amend = args.includes('--amend');
|
|
396
|
+
const filesIndex = args.indexOf('--files');
|
|
397
|
+
// Collect all positional args between command name and first flag,
|
|
398
|
+
// then join them — handles both quoted ("multi word msg") and
|
|
399
|
+
// unquoted (multi word msg) invocations from different shells
|
|
400
|
+
const endIndex = filesIndex !== -1 ? filesIndex : args.length;
|
|
401
|
+
const messageArgs = args.slice(1, endIndex).filter(a => !a.startsWith('--'));
|
|
402
|
+
const message = messageArgs.join(' ') || undefined;
|
|
403
|
+
const files = filesIndex !== -1 ? args.slice(filesIndex + 1).filter(a => !a.startsWith('--')) : [];
|
|
404
|
+
commands.cmdCommit(cwd, message, files, raw, amend);
|
|
405
|
+
break;
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
case 'verify-summary': {
|
|
409
|
+
const summaryPath = args[1];
|
|
410
|
+
const countIndex = args.indexOf('--check-count');
|
|
411
|
+
const checkCount = countIndex !== -1 ? parseInt(args[countIndex + 1], 10) : 2;
|
|
412
|
+
verify.cmdVerifySummary(cwd, summaryPath, checkCount, raw);
|
|
413
|
+
break;
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
case 'template': {
|
|
417
|
+
const subcommand = args[1];
|
|
418
|
+
if (subcommand === 'select') {
|
|
419
|
+
template.cmdTemplateSelect(cwd, args[2], raw);
|
|
420
|
+
} else if (subcommand === 'fill') {
|
|
421
|
+
const templateType = args[2];
|
|
422
|
+
const phaseIdx = args.indexOf('--phase');
|
|
423
|
+
const planIdx = args.indexOf('--plan');
|
|
424
|
+
const nameIdx = args.indexOf('--name');
|
|
425
|
+
const typeIdx = args.indexOf('--type');
|
|
426
|
+
const waveIdx = args.indexOf('--wave');
|
|
427
|
+
const fieldsIdx = args.indexOf('--fields');
|
|
428
|
+
template.cmdTemplateFill(cwd, templateType, {
|
|
429
|
+
phase: phaseIdx !== -1 ? args[phaseIdx + 1] : null,
|
|
430
|
+
plan: planIdx !== -1 ? args[planIdx + 1] : null,
|
|
431
|
+
name: nameIdx !== -1 ? args[nameIdx + 1] : null,
|
|
432
|
+
type: typeIdx !== -1 ? args[typeIdx + 1] : 'execute',
|
|
433
|
+
wave: waveIdx !== -1 ? args[waveIdx + 1] : '1',
|
|
434
|
+
fields: fieldsIdx !== -1 ? JSON.parse(args[fieldsIdx + 1]) : {},
|
|
435
|
+
}, raw);
|
|
436
|
+
} else {
|
|
437
|
+
error('Unknown template subcommand. Available: select, fill');
|
|
438
|
+
}
|
|
439
|
+
break;
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
case 'frontmatter': {
|
|
443
|
+
const subcommand = args[1];
|
|
444
|
+
const file = args[2];
|
|
445
|
+
if (subcommand === 'get') {
|
|
446
|
+
const fieldIdx = args.indexOf('--field');
|
|
447
|
+
frontmatter.cmdFrontmatterGet(cwd, file, fieldIdx !== -1 ? args[fieldIdx + 1] : null, raw);
|
|
448
|
+
} else if (subcommand === 'set') {
|
|
449
|
+
const fieldIdx = args.indexOf('--field');
|
|
450
|
+
const valueIdx = args.indexOf('--value');
|
|
451
|
+
frontmatter.cmdFrontmatterSet(cwd, file, fieldIdx !== -1 ? args[fieldIdx + 1] : null, valueIdx !== -1 ? args[valueIdx + 1] : undefined, raw);
|
|
452
|
+
} else if (subcommand === 'merge') {
|
|
453
|
+
const dataIdx = args.indexOf('--data');
|
|
454
|
+
frontmatter.cmdFrontmatterMerge(cwd, file, dataIdx !== -1 ? args[dataIdx + 1] : null, raw);
|
|
455
|
+
} else if (subcommand === 'validate') {
|
|
456
|
+
const schemaIdx = args.indexOf('--schema');
|
|
457
|
+
frontmatter.cmdFrontmatterValidate(cwd, file, schemaIdx !== -1 ? args[schemaIdx + 1] : null, raw);
|
|
458
|
+
} else {
|
|
459
|
+
error('Unknown frontmatter subcommand. Available: get, set, merge, validate');
|
|
460
|
+
}
|
|
461
|
+
break;
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
case 'verify': {
|
|
465
|
+
const subcommand = args[1];
|
|
466
|
+
if (subcommand === 'plan-structure') {
|
|
467
|
+
verify.cmdVerifyPlanStructure(cwd, args[2], raw);
|
|
468
|
+
} else if (subcommand === 'phase-completeness') {
|
|
469
|
+
verify.cmdVerifyPhaseCompleteness(cwd, args[2], raw);
|
|
470
|
+
} else if (subcommand === 'references') {
|
|
471
|
+
verify.cmdVerifyReferences(cwd, args[2], raw);
|
|
472
|
+
} else if (subcommand === 'commits') {
|
|
473
|
+
verify.cmdVerifyCommits(cwd, args.slice(2), raw);
|
|
474
|
+
} else if (subcommand === 'artifacts') {
|
|
475
|
+
verify.cmdVerifyArtifacts(cwd, args[2], raw);
|
|
476
|
+
} else if (subcommand === 'key-links') {
|
|
477
|
+
verify.cmdVerifyKeyLinks(cwd, args[2], raw);
|
|
478
|
+
} else {
|
|
479
|
+
error('Unknown verify subcommand. Available: plan-structure, phase-completeness, references, commits, artifacts, key-links');
|
|
480
|
+
}
|
|
481
|
+
break;
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
case 'generate-slug': {
|
|
485
|
+
commands.cmdGenerateSlug(args[1], raw);
|
|
486
|
+
break;
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
case 'current-timestamp': {
|
|
490
|
+
commands.cmdCurrentTimestamp(args[1] || 'full', raw);
|
|
491
|
+
break;
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
case 'list-todos': {
|
|
495
|
+
commands.cmdListTodos(cwd, args[1], raw);
|
|
496
|
+
break;
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
case 'verify-path-exists': {
|
|
500
|
+
commands.cmdVerifyPathExists(cwd, args[1], raw);
|
|
501
|
+
break;
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
case 'config-ensure-section': {
|
|
505
|
+
config.cmdConfigEnsureSection(cwd, raw);
|
|
506
|
+
break;
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
case 'config-set': {
|
|
510
|
+
config.cmdConfigSet(cwd, args[1], args[2], raw);
|
|
511
|
+
break;
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
case 'config-get': {
|
|
515
|
+
config.cmdConfigGet(cwd, args[1], raw);
|
|
516
|
+
break;
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
case 'history-digest': {
|
|
520
|
+
commands.cmdHistoryDigest(cwd, raw);
|
|
521
|
+
break;
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
case 'phases': {
|
|
525
|
+
const subcommand = args[1];
|
|
526
|
+
if (subcommand === 'list') {
|
|
527
|
+
const typeIndex = args.indexOf('--type');
|
|
528
|
+
const phaseIndex = args.indexOf('--phase');
|
|
529
|
+
const options = {
|
|
530
|
+
type: typeIndex !== -1 ? args[typeIndex + 1] : null,
|
|
531
|
+
phase: phaseIndex !== -1 ? args[phaseIndex + 1] : null,
|
|
532
|
+
includeArchived: args.includes('--include-archived'),
|
|
533
|
+
};
|
|
534
|
+
phase.cmdPhasesList(cwd, options, raw);
|
|
535
|
+
} else {
|
|
536
|
+
error('Unknown phases subcommand. Available: list');
|
|
537
|
+
}
|
|
538
|
+
break;
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
case 'roadmap': {
|
|
542
|
+
const subcommand = args[1];
|
|
543
|
+
if (subcommand === 'get-phase') {
|
|
544
|
+
roadmap.cmdRoadmapGetPhase(cwd, args[2], raw);
|
|
545
|
+
} else if (subcommand === 'analyze') {
|
|
546
|
+
roadmap.cmdRoadmapAnalyze(cwd, raw);
|
|
547
|
+
} else if (subcommand === 'update-plan-progress') {
|
|
548
|
+
roadmap.cmdRoadmapUpdatePlanProgress(cwd, args[2], raw);
|
|
549
|
+
} else {
|
|
550
|
+
error('Unknown roadmap subcommand. Available: get-phase, analyze, update-plan-progress');
|
|
551
|
+
}
|
|
552
|
+
break;
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
case 'requirements': {
|
|
556
|
+
const subcommand = args[1];
|
|
557
|
+
if (subcommand === 'mark-complete') {
|
|
558
|
+
milestone.cmdRequirementsMarkComplete(cwd, args.slice(2), raw);
|
|
559
|
+
} else {
|
|
560
|
+
error('Unknown requirements subcommand. Available: mark-complete');
|
|
561
|
+
}
|
|
562
|
+
break;
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
case 'phase': {
|
|
566
|
+
const subcommand = args[1];
|
|
567
|
+
if (subcommand === 'next-decimal') {
|
|
568
|
+
phase.cmdPhaseNextDecimal(cwd, args[2], raw);
|
|
569
|
+
} else if (subcommand === 'add') {
|
|
570
|
+
phase.cmdPhaseAdd(cwd, args.slice(2).join(' '), raw);
|
|
571
|
+
} else if (subcommand === 'insert') {
|
|
572
|
+
phase.cmdPhaseInsert(cwd, args[2], args.slice(3).join(' '), raw);
|
|
573
|
+
} else if (subcommand === 'remove') {
|
|
574
|
+
const forceFlag = args.includes('--force');
|
|
575
|
+
phase.cmdPhaseRemove(cwd, args[2], { force: forceFlag }, raw);
|
|
576
|
+
} else if (subcommand === 'complete') {
|
|
577
|
+
phase.cmdPhaseComplete(cwd, args[2], raw);
|
|
578
|
+
} else {
|
|
579
|
+
error('Unknown phase subcommand. Available: next-decimal, add, insert, remove, complete');
|
|
580
|
+
}
|
|
581
|
+
break;
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
case 'milestone': {
|
|
585
|
+
const subcommand = args[1];
|
|
586
|
+
if (subcommand === 'complete') {
|
|
587
|
+
const nameIndex = args.indexOf('--name');
|
|
588
|
+
const archivePhases = args.includes('--archive-phases');
|
|
589
|
+
// Collect --name value (everything after --name until next flag or end)
|
|
590
|
+
let milestoneName = null;
|
|
591
|
+
if (nameIndex !== -1) {
|
|
592
|
+
const nameArgs = [];
|
|
593
|
+
for (let i = nameIndex + 1; i < args.length; i++) {
|
|
594
|
+
if (args[i].startsWith('--')) break;
|
|
595
|
+
nameArgs.push(args[i]);
|
|
596
|
+
}
|
|
597
|
+
milestoneName = nameArgs.join(' ') || null;
|
|
598
|
+
}
|
|
599
|
+
milestone.cmdMilestoneComplete(cwd, args[2], { name: milestoneName, archivePhases }, raw);
|
|
600
|
+
} else {
|
|
601
|
+
error('Unknown milestone subcommand. Available: complete');
|
|
602
|
+
}
|
|
603
|
+
break;
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
case 'package-manager': {
|
|
607
|
+
const subcommand = args[1];
|
|
608
|
+
|
|
609
|
+
if (!subcommand) {
|
|
610
|
+
error('Usage: ez-tools package-manager <detect|install|add|remove|info> [options]\nSubcommands: detect, install, add, remove, info');
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
try {
|
|
614
|
+
const service = new PackageManagerService(cwd);
|
|
615
|
+
|
|
616
|
+
switch (subcommand) {
|
|
617
|
+
case 'detect': {
|
|
618
|
+
const detector = new (require('./lib/package-manager-detector.cjs'))(cwd);
|
|
619
|
+
const result = detector.detect();
|
|
620
|
+
if (raw) {
|
|
621
|
+
console.log(`manager=${result.manager} source=${result.source} confidence=${result.confidence}`);
|
|
622
|
+
} else {
|
|
623
|
+
console.log(JSON.stringify(result, null, 2));
|
|
624
|
+
}
|
|
625
|
+
break;
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
case 'install': {
|
|
629
|
+
await service.initialize();
|
|
630
|
+
const frozenLockfile = args.includes('--frozen');
|
|
631
|
+
const production = args.includes('--production');
|
|
632
|
+
const result = await service.install({ frozenLockfile, production });
|
|
633
|
+
if (!raw) {
|
|
634
|
+
console.log(result);
|
|
635
|
+
}
|
|
636
|
+
break;
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
case 'add': {
|
|
640
|
+
await service.initialize();
|
|
641
|
+
const dev = args.includes('--dev') || args.includes('-D');
|
|
642
|
+
// Extract packages (filter out flags)
|
|
643
|
+
const packages = args.slice(2).filter(arg => !arg.startsWith('--'));
|
|
644
|
+
if (packages.length === 0) {
|
|
645
|
+
error('Usage: ez-tools package-manager add <package> [--dev|-D]');
|
|
646
|
+
}
|
|
647
|
+
const result = await service.add(packages, { dev });
|
|
648
|
+
if (!raw) {
|
|
649
|
+
console.log(result);
|
|
650
|
+
}
|
|
651
|
+
break;
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
case 'remove': {
|
|
655
|
+
await service.initialize();
|
|
656
|
+
// Extract packages (filter out flags)
|
|
657
|
+
const packages = args.slice(2).filter(arg => !arg.startsWith('--'));
|
|
658
|
+
if (packages.length === 0) {
|
|
659
|
+
error('Usage: ez-tools package-manager remove <package>');
|
|
660
|
+
}
|
|
661
|
+
const result = await service.remove(packages);
|
|
662
|
+
if (!raw) {
|
|
663
|
+
console.log(result);
|
|
664
|
+
}
|
|
665
|
+
break;
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
case 'info': {
|
|
669
|
+
await service.initialize();
|
|
670
|
+
const result = service.getInfo();
|
|
671
|
+
if (raw) {
|
|
672
|
+
console.log(`manager=${result.manager} source=${result.source} cwd=${result.cwd} lockfile=${result.lockfile}`);
|
|
673
|
+
} else {
|
|
674
|
+
console.log(JSON.stringify(result, null, 2));
|
|
675
|
+
}
|
|
676
|
+
break;
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
default: {
|
|
680
|
+
error('Unknown package-manager subcommand: ' + subcommand + '\nValid: detect, install, add, remove, info');
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
} catch (err) {
|
|
684
|
+
error(err.message);
|
|
685
|
+
}
|
|
686
|
+
break;
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
case 'validate': {
|
|
690
|
+
const subcommand = args[1];
|
|
691
|
+
if (subcommand === 'consistency') {
|
|
692
|
+
verify.cmdValidateConsistency(cwd, raw);
|
|
693
|
+
} else if (subcommand === 'health') {
|
|
694
|
+
const repairFlag = args.includes('--repair');
|
|
695
|
+
verify.cmdValidateHealth(cwd, { repair: repairFlag }, raw);
|
|
696
|
+
} else {
|
|
697
|
+
error('Unknown validate subcommand. Available: consistency, health');
|
|
698
|
+
}
|
|
699
|
+
break;
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
case 'progress': {
|
|
703
|
+
const subcommand = args[1] || 'json';
|
|
704
|
+
commands.cmdProgressRender(cwd, subcommand, raw);
|
|
705
|
+
break;
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
case 'stats': {
|
|
709
|
+
const subcommand = args[1] || 'json';
|
|
710
|
+
commands.cmdStats(cwd, subcommand, raw);
|
|
711
|
+
break;
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
case 'todo': {
|
|
715
|
+
const subcommand = args[1];
|
|
716
|
+
if (subcommand === 'complete') {
|
|
717
|
+
commands.cmdTodoComplete(cwd, args[2], raw);
|
|
718
|
+
} else {
|
|
719
|
+
error('Unknown todo subcommand. Available: complete');
|
|
720
|
+
}
|
|
721
|
+
break;
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
case 'scaffold': {
|
|
725
|
+
const scaffoldType = args[1];
|
|
726
|
+
const phaseIndex = args.indexOf('--phase');
|
|
727
|
+
const nameIndex = args.indexOf('--name');
|
|
728
|
+
const scaffoldOptions = {
|
|
729
|
+
phase: phaseIndex !== -1 ? args[phaseIndex + 1] : null,
|
|
730
|
+
name: nameIndex !== -1 ? args.slice(nameIndex + 1).join(' ') : null,
|
|
731
|
+
};
|
|
732
|
+
commands.cmdScaffold(cwd, scaffoldType, scaffoldOptions, raw);
|
|
733
|
+
break;
|
|
734
|
+
}
|
|
735
|
+
|
|
736
|
+
case 'init': {
|
|
737
|
+
const workflow = args[1];
|
|
738
|
+
switch (workflow) {
|
|
739
|
+
case 'execute-phase':
|
|
740
|
+
init.cmdInitExecutePhase(cwd, args[2], raw);
|
|
741
|
+
break;
|
|
742
|
+
case 'plan-phase':
|
|
743
|
+
init.cmdInitPlanPhase(cwd, args[2], raw);
|
|
744
|
+
break;
|
|
745
|
+
case 'new-project':
|
|
746
|
+
await init.cmdInitNewProject(cwd, raw);
|
|
747
|
+
break;
|
|
748
|
+
case 'new-milestone':
|
|
749
|
+
init.cmdInitNewMilestone(cwd, raw);
|
|
750
|
+
break;
|
|
751
|
+
case 'quick':
|
|
752
|
+
init.cmdInitQuick(cwd, args.slice(2).join(' '), raw);
|
|
753
|
+
break;
|
|
754
|
+
case 'resume':
|
|
755
|
+
init.cmdInitResume(cwd, raw);
|
|
756
|
+
break;
|
|
757
|
+
case 'verify-work':
|
|
758
|
+
init.cmdInitVerifyWork(cwd, args[2], raw);
|
|
759
|
+
break;
|
|
760
|
+
case 'phase-op':
|
|
761
|
+
init.cmdInitPhaseOp(cwd, args[2], raw);
|
|
762
|
+
break;
|
|
763
|
+
case 'todos':
|
|
764
|
+
init.cmdInitTodos(cwd, args[2], raw);
|
|
765
|
+
break;
|
|
766
|
+
case 'milestone-op':
|
|
767
|
+
init.cmdInitMilestoneOp(cwd, raw);
|
|
768
|
+
break;
|
|
769
|
+
case 'map-codebase':
|
|
770
|
+
init.cmdInitMapCodebase(cwd, raw);
|
|
771
|
+
break;
|
|
772
|
+
case 'progress':
|
|
773
|
+
init.cmdInitProgress(cwd, raw);
|
|
774
|
+
break;
|
|
775
|
+
default:
|
|
776
|
+
error(`Unknown init workflow: ${workflow}\nAvailable: execute-phase, plan-phase, new-project, new-milestone, quick, resume, verify-work, phase-op, todos, milestone-op, map-codebase, progress`);
|
|
777
|
+
}
|
|
778
|
+
break;
|
|
779
|
+
}
|
|
780
|
+
|
|
781
|
+
case 'phase-plan-index': {
|
|
782
|
+
phase.cmdPhasePlanIndex(cwd, args[1], raw);
|
|
783
|
+
break;
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
case 'state-snapshot': {
|
|
787
|
+
state.cmdStateSnapshot(cwd, raw);
|
|
788
|
+
break;
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
case 'summary-extract': {
|
|
792
|
+
const summaryPath = args[1];
|
|
793
|
+
const fieldsIndex = args.indexOf('--fields');
|
|
794
|
+
const fields = fieldsIndex !== -1 ? args[fieldsIndex + 1].split(',') : null;
|
|
795
|
+
commands.cmdSummaryExtract(cwd, summaryPath, fields, raw);
|
|
796
|
+
break;
|
|
797
|
+
}
|
|
798
|
+
|
|
799
|
+
case 'websearch': {
|
|
800
|
+
const query = args[1];
|
|
801
|
+
const limitIdx = args.indexOf('--limit');
|
|
802
|
+
const freshnessIdx = args.indexOf('--freshness');
|
|
803
|
+
await commands.cmdWebsearch(query, {
|
|
804
|
+
limit: limitIdx !== -1 ? parseInt(args[limitIdx + 1], 10) : 10,
|
|
805
|
+
freshness: freshnessIdx !== -1 ? args[freshnessIdx + 1] : null,
|
|
806
|
+
}, raw);
|
|
807
|
+
break;
|
|
808
|
+
}
|
|
809
|
+
|
|
810
|
+
case 'context': {
|
|
811
|
+
const subcommand = args[1];
|
|
812
|
+
|
|
813
|
+
if (subcommand === 'read') {
|
|
814
|
+
const patterns = args.slice(2);
|
|
815
|
+
if (patterns.length === 0) {
|
|
816
|
+
console.error('Usage: ez-tools context read <pattern1> [pattern2...]');
|
|
817
|
+
console.error('Example: node ez-tools.cjs context read "README.md" "src/**/*.ts"');
|
|
818
|
+
process.exit(1);
|
|
819
|
+
}
|
|
820
|
+
const fileAccess = new FileAccessService(cwd);
|
|
821
|
+
const results = fileAccess.readFiles(patterns);
|
|
822
|
+
results.forEach(file => {
|
|
823
|
+
console.log(`\n--- ${file.path} ---\n`);
|
|
824
|
+
console.log(file.content);
|
|
825
|
+
});
|
|
826
|
+
break;
|
|
827
|
+
}
|
|
828
|
+
|
|
829
|
+
if (subcommand === 'fetch') {
|
|
830
|
+
const url = args[2];
|
|
831
|
+
if (!url) {
|
|
832
|
+
console.error('Usage: ez-tools context fetch <url>');
|
|
833
|
+
console.error('Example: node ez-tools.cjs context fetch https://example.com/doc.md');
|
|
834
|
+
process.exit(1);
|
|
835
|
+
}
|
|
836
|
+
const urlFetch = new URLFetchService();
|
|
837
|
+
const validated = urlFetch.validateUrl(url);
|
|
838
|
+
if (!validated.valid) {
|
|
839
|
+
console.error(`Invalid URL: ${validated.error}`);
|
|
840
|
+
process.exit(1);
|
|
841
|
+
}
|
|
842
|
+
const confirmed = await URLFetchService.confirmUrlFetch(url);
|
|
843
|
+
if (!confirmed) {
|
|
844
|
+
console.log('Fetch cancelled by user');
|
|
845
|
+
process.exit(0);
|
|
846
|
+
}
|
|
847
|
+
const result = await urlFetch.fetchUrl(url);
|
|
848
|
+
console.log(result.content);
|
|
849
|
+
break;
|
|
850
|
+
}
|
|
851
|
+
|
|
852
|
+
if (subcommand === 'request') {
|
|
853
|
+
const contextManager = new ContextManager(cwd);
|
|
854
|
+
console.log('Context Request Mode');
|
|
855
|
+
console.log('Enter file patterns or URLs (one per line, empty line to finish):\n');
|
|
856
|
+
|
|
857
|
+
const readline = require('readline');
|
|
858
|
+
const rl = readline.createInterface({
|
|
859
|
+
input: process.stdin,
|
|
860
|
+
output: process.stdout
|
|
861
|
+
});
|
|
862
|
+
|
|
863
|
+
const files = [];
|
|
864
|
+
const urls = [];
|
|
865
|
+
|
|
866
|
+
console.log('> ');
|
|
867
|
+
for await (const line of rl) {
|
|
868
|
+
if (!line.trim()) break;
|
|
869
|
+
if (line.startsWith('http')) {
|
|
870
|
+
urls.push(line);
|
|
871
|
+
} else {
|
|
872
|
+
files.push(line);
|
|
873
|
+
}
|
|
874
|
+
console.log('> ');
|
|
875
|
+
}
|
|
876
|
+
|
|
877
|
+
const result = await contextManager.requestContext({ files, urls });
|
|
878
|
+
console.log('\n=== Aggregated Context ===\n');
|
|
879
|
+
console.log(result.context);
|
|
880
|
+
console.log(`\n\nSources: ${result.sources.length}`);
|
|
881
|
+
if (result.errors.length > 0) {
|
|
882
|
+
console.log(`Errors: ${result.errors.length}`);
|
|
883
|
+
result.errors.forEach(e => console.error(` - ${e.source}: ${e.message}`));
|
|
884
|
+
}
|
|
885
|
+
break;
|
|
886
|
+
}
|
|
887
|
+
|
|
888
|
+
if (!subcommand) {
|
|
889
|
+
console.log('Context Access Commands');
|
|
890
|
+
console.log('═══════════════════════');
|
|
891
|
+
console.log('');
|
|
892
|
+
console.log(' context read <pattern> Read local files using glob patterns');
|
|
893
|
+
console.log(' context fetch <url> Fetch content from URL (HTTPS only)');
|
|
894
|
+
console.log(' context request Interactive context gathering mode');
|
|
895
|
+
console.log('');
|
|
896
|
+
console.log('Examples:');
|
|
897
|
+
console.log(' node ez-tools.cjs context read "README.md"');
|
|
898
|
+
console.log(' node ez-tools.cjs context read "src/**/*.ts" "!*.test.ts"');
|
|
899
|
+
console.log(' node ez-tools.cjs context fetch https://example.com/spec.md');
|
|
900
|
+
console.log(' node ez-tools.cjs context request');
|
|
901
|
+
break;
|
|
902
|
+
}
|
|
903
|
+
|
|
904
|
+
error(`Unknown context subcommand: ${subcommand}\nAvailable: read, fetch, request`);
|
|
905
|
+
}
|
|
906
|
+
|
|
907
|
+
// ─── Session Management Commands ─────────────────────────────────────────
|
|
908
|
+
|
|
909
|
+
case 'session': {
|
|
910
|
+
const subcommand = args[1];
|
|
911
|
+
const sessionMgr = new SessionManager();
|
|
912
|
+
|
|
913
|
+
switch (subcommand) {
|
|
914
|
+
case 'list': {
|
|
915
|
+
const sessions = sessionMgr.listSessions();
|
|
916
|
+
const limitIdx = args.indexOf('--limit');
|
|
917
|
+
const limit = limitIdx !== -1 ? parseInt(args[limitIdx + 1]) : 20;
|
|
918
|
+
output({ sessions: sessions.slice(0, limit) });
|
|
919
|
+
break;
|
|
920
|
+
}
|
|
921
|
+
|
|
922
|
+
case 'get': {
|
|
923
|
+
const sessionId = args[2];
|
|
924
|
+
if (!sessionId) {
|
|
925
|
+
error('Usage: ez-tools session get <session_id>');
|
|
926
|
+
}
|
|
927
|
+
const session = sessionMgr.loadSession(sessionId);
|
|
928
|
+
if (!session) {
|
|
929
|
+
error(`Session not found: ${sessionId}`);
|
|
930
|
+
}
|
|
931
|
+
output(session);
|
|
932
|
+
break;
|
|
933
|
+
}
|
|
934
|
+
|
|
935
|
+
case 'create': {
|
|
936
|
+
const modelIdx = args.indexOf('--model');
|
|
937
|
+
const phaseIdx = args.indexOf('--phase');
|
|
938
|
+
const planIdx = args.indexOf('--plan');
|
|
939
|
+
const newSessionId = sessionMgr.createSession({
|
|
940
|
+
model: modelIdx !== -1 ? args[modelIdx + 1] : undefined,
|
|
941
|
+
phase: phaseIdx !== -1 ? parseInt(args[phaseIdx + 1]) : undefined,
|
|
942
|
+
plan: planIdx !== -1 ? parseInt(args[planIdx + 1]) : undefined
|
|
943
|
+
});
|
|
944
|
+
output({ session_id: newSessionId });
|
|
945
|
+
break;
|
|
946
|
+
}
|
|
947
|
+
|
|
948
|
+
case 'end': {
|
|
949
|
+
const sessionId = args[2];
|
|
950
|
+
if (!sessionId) {
|
|
951
|
+
error('Usage: ez-tools session end <session_id> [--status status]');
|
|
952
|
+
}
|
|
953
|
+
const statusIdx = args.indexOf('--status');
|
|
954
|
+
const status = statusIdx !== -1 ? args[statusIdx + 1] : 'completed';
|
|
955
|
+
const success = sessionMgr.endSession(sessionId, { status });
|
|
956
|
+
if (!success) {
|
|
957
|
+
error(`Failed to end session: ${sessionId}`);
|
|
958
|
+
}
|
|
959
|
+
output({ ended: sessionId });
|
|
960
|
+
break;
|
|
961
|
+
}
|
|
962
|
+
|
|
963
|
+
case 'compress': {
|
|
964
|
+
const sessionId = args[2];
|
|
965
|
+
const thresholdIdx = args.indexOf('--threshold');
|
|
966
|
+
const threshold = thresholdIdx !== -1 ? parseInt(args[thresholdIdx + 1]) : 50;
|
|
967
|
+
|
|
968
|
+
if (!sessionId) {
|
|
969
|
+
error('Usage: ez-tools session compress <session_id> [--threshold N]');
|
|
970
|
+
}
|
|
971
|
+
|
|
972
|
+
const compressor = new MemoryCompression(sessionMgr);
|
|
973
|
+
const result = compressor.compress(sessionId, { threshold });
|
|
974
|
+
output(result);
|
|
975
|
+
break;
|
|
976
|
+
}
|
|
977
|
+
|
|
978
|
+
default:
|
|
979
|
+
error('Usage: ez-tools session <list|get|create|end|compress> [args]');
|
|
980
|
+
}
|
|
981
|
+
break;
|
|
982
|
+
}
|
|
983
|
+
|
|
984
|
+
case 'resume': {
|
|
985
|
+
const sessionId = args[1];
|
|
986
|
+
const sessionMgr = new SessionManager();
|
|
987
|
+
|
|
988
|
+
const session = sessionId
|
|
989
|
+
? sessionMgr.loadSession(sessionId)
|
|
990
|
+
: sessionMgr.getLastSession();
|
|
991
|
+
|
|
992
|
+
if (!session) {
|
|
993
|
+
error('No session found to resume');
|
|
994
|
+
}
|
|
995
|
+
|
|
996
|
+
// Output session summary for display
|
|
997
|
+
output({
|
|
998
|
+
session_id: session.metadata.session_id,
|
|
999
|
+
model: session.metadata.model,
|
|
1000
|
+
phase: session.metadata.phase,
|
|
1001
|
+
plan: session.metadata.plan,
|
|
1002
|
+
last_action: session.state.last_action,
|
|
1003
|
+
next_action: session.state.next_recommended_action,
|
|
1004
|
+
incomplete_tasks: session.state.incomplete_tasks
|
|
1005
|
+
});
|
|
1006
|
+
break;
|
|
1007
|
+
}
|
|
1008
|
+
|
|
1009
|
+
case 'export-session': {
|
|
1010
|
+
const sessionId = args[1] || 'last';
|
|
1011
|
+
const formatIdx = args.indexOf('--format');
|
|
1012
|
+
const outputIdx = args.indexOf('--output');
|
|
1013
|
+
|
|
1014
|
+
const format = formatIdx !== -1 ? args[formatIdx + 1] : 'markdown';
|
|
1015
|
+
const outputPath = outputIdx !== -1 ? args[outputIdx + 1] : null;
|
|
1016
|
+
|
|
1017
|
+
const sessionMgr = new SessionManager();
|
|
1018
|
+
const exporter = new SessionExport(sessionMgr);
|
|
1019
|
+
|
|
1020
|
+
const actualSessionId = sessionId === 'last'
|
|
1021
|
+
? sessionMgr.getLastSession()?.metadata?.session_id
|
|
1022
|
+
: sessionId;
|
|
1023
|
+
|
|
1024
|
+
if (!actualSessionId) {
|
|
1025
|
+
error('No sessions found');
|
|
1026
|
+
}
|
|
1027
|
+
|
|
1028
|
+
try {
|
|
1029
|
+
const result = exporter.exportToFile(actualSessionId, format, outputPath);
|
|
1030
|
+
output(result);
|
|
1031
|
+
} catch (err) {
|
|
1032
|
+
error(`Export failed: ${err.message}`);
|
|
1033
|
+
}
|
|
1034
|
+
break;
|
|
1035
|
+
}
|
|
1036
|
+
|
|
1037
|
+
case 'import-session': {
|
|
1038
|
+
const filePath = args[1];
|
|
1039
|
+
const sourceModelIdx = args.indexOf('--source-model');
|
|
1040
|
+
const sourceModel = sourceModelIdx !== -1 ? args[sourceModelIdx + 1] : null;
|
|
1041
|
+
|
|
1042
|
+
if (!filePath) {
|
|
1043
|
+
error('Usage: ez-tools import-session <file.json> [--source-model <model>]');
|
|
1044
|
+
}
|
|
1045
|
+
|
|
1046
|
+
const sessionMgr = new SessionManager();
|
|
1047
|
+
const importer = new SessionImport(sessionMgr);
|
|
1048
|
+
|
|
1049
|
+
try {
|
|
1050
|
+
const result = importer.import(filePath, { sourceModel });
|
|
1051
|
+
output(result);
|
|
1052
|
+
} catch (err) {
|
|
1053
|
+
error(`Import failed: ${err.message}`);
|
|
1054
|
+
}
|
|
1055
|
+
break;
|
|
1056
|
+
}
|
|
1057
|
+
|
|
1058
|
+
case 'chain': {
|
|
1059
|
+
const sessionId = args[1];
|
|
1060
|
+
const direction = args[2];
|
|
1061
|
+
|
|
1062
|
+
if (!sessionId) {
|
|
1063
|
+
error('Usage: ez-tools chain <session_id> [previous|next|visualize|repair]');
|
|
1064
|
+
}
|
|
1065
|
+
|
|
1066
|
+
const sessionMgr = new SessionManager();
|
|
1067
|
+
const chain = new SessionChain(sessionMgr);
|
|
1068
|
+
|
|
1069
|
+
if (direction === 'previous' || direction === 'next') {
|
|
1070
|
+
const result = chain.navigate(sessionId, direction);
|
|
1071
|
+
if (!result) {
|
|
1072
|
+
output({ navigation: null, message: `No session ${direction} of ${sessionId}` });
|
|
1073
|
+
} else {
|
|
1074
|
+
output(result);
|
|
1075
|
+
}
|
|
1076
|
+
} else if (direction === 'visualize' || !direction) {
|
|
1077
|
+
const viz = chain.getChainVisualization(sessionId);
|
|
1078
|
+
output({ visualization: viz });
|
|
1079
|
+
} else if (direction === 'repair') {
|
|
1080
|
+
const result = chain.repairChain(sessionId);
|
|
1081
|
+
output(result);
|
|
1082
|
+
} else {
|
|
1083
|
+
error('Usage: ez-tools chain <session_id> [previous|next|visualize|repair]');
|
|
1084
|
+
}
|
|
1085
|
+
break;
|
|
1086
|
+
}
|
|
1087
|
+
|
|
1088
|
+
// ─── Default/Error Case ──────────────────────────────────────────────────
|
|
1089
|
+
|
|
1090
|
+
default:
|
|
1091
|
+
error(`Unknown command: ${command}`);
|
|
1092
|
+
}
|
|
1093
|
+
}
|
|
1094
|
+
|
|
1095
|
+
main();
|