edsger 0.54.1 → 0.55.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/dist/commands/issue-analysis/index.d.ts +5 -0
- package/dist/commands/issue-analysis/index.js +9 -0
- package/dist/commands/technical-design/index.d.ts +5 -0
- package/dist/commands/technical-design/index.js +9 -0
- package/dist/commands/test-cases-analysis/index.d.ts +5 -0
- package/dist/commands/test-cases-analysis/index.js +9 -0
- package/dist/commands/user-stories-analysis/index.d.ts +5 -0
- package/dist/commands/user-stories-analysis/index.js +9 -0
- package/dist/index.js +79 -1
- package/dist/utils/issue-phase-cli.d.ts +26 -0
- package/dist/utils/issue-phase-cli.js +44 -0
- package/package.json +1 -1
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { analyseIssue } from '../../phases/issue-analysis/index.js';
|
|
2
|
+
import { runIssuePhaseCli } from '../../utils/issue-phase-cli.js';
|
|
3
|
+
export const runIssueAnalysisCommand = (options) => runIssuePhaseCli({
|
|
4
|
+
command: 'issue-analysis',
|
|
5
|
+
description: 'Issue analysis',
|
|
6
|
+
issueId: options.issueId,
|
|
7
|
+
verbose: options.verbose,
|
|
8
|
+
execute: analyseIssue,
|
|
9
|
+
});
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { generateTechnicalDesign } from '../../phases/technical-design/index.js';
|
|
2
|
+
import { runIssuePhaseCli } from '../../utils/issue-phase-cli.js';
|
|
3
|
+
export const runTechnicalDesignCommand = (options) => runIssuePhaseCli({
|
|
4
|
+
command: 'technical-design',
|
|
5
|
+
description: 'Technical design',
|
|
6
|
+
issueId: options.issueId,
|
|
7
|
+
verbose: options.verbose,
|
|
8
|
+
execute: generateTechnicalDesign,
|
|
9
|
+
});
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { analyseTestCases } from '../../phases/test-cases-analysis/index.js';
|
|
2
|
+
import { runIssuePhaseCli } from '../../utils/issue-phase-cli.js';
|
|
3
|
+
export const runTestCasesAnalysisCommand = (options) => runIssuePhaseCli({
|
|
4
|
+
command: 'test-cases-analysis',
|
|
5
|
+
description: 'Test-cases analysis',
|
|
6
|
+
issueId: options.issueId,
|
|
7
|
+
verbose: options.verbose,
|
|
8
|
+
execute: analyseTestCases,
|
|
9
|
+
});
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { analyseUserStories } from '../../phases/user-stories-analysis/index.js';
|
|
2
|
+
import { runIssuePhaseCli } from '../../utils/issue-phase-cli.js';
|
|
3
|
+
export const runUserStoriesAnalysisCommand = (options) => runIssuePhaseCli({
|
|
4
|
+
command: 'user-stories-analysis',
|
|
5
|
+
description: 'User-stories analysis',
|
|
6
|
+
issueId: options.issueId,
|
|
7
|
+
verbose: options.verbose,
|
|
8
|
+
execute: analyseUserStories,
|
|
9
|
+
});
|
package/dist/index.js
CHANGED
|
@@ -21,6 +21,7 @@ import { parseCategoriesOption, runFindSmells, } from './commands/find-smells/in
|
|
|
21
21
|
import { runGrowthAnalysis } from './commands/growth-analysis/index.js';
|
|
22
22
|
import { runInit } from './commands/init/index.js';
|
|
23
23
|
import { runIntelligence } from './commands/intelligence/index.js';
|
|
24
|
+
import { runIssueAnalysisCommand } from './commands/issue-analysis/index.js';
|
|
24
25
|
import { runPRResolve } from './commands/pr-resolve/index.js';
|
|
25
26
|
import { runPRReview } from './commands/pr-review/index.js';
|
|
26
27
|
import { runRefactor } from './commands/refactor/refactor.js';
|
|
@@ -30,6 +31,9 @@ import { runSmokeTestCommand } from './commands/smoke-test/index.js';
|
|
|
30
31
|
import { runSyncGithubIssues } from './commands/sync-github-issues/index.js';
|
|
31
32
|
import { runSyncSentryIssues } from './commands/sync-sentry-issues/index.js';
|
|
32
33
|
import { runTaskWorker } from './commands/task-worker/index.js';
|
|
34
|
+
import { runTechnicalDesignCommand } from './commands/technical-design/index.js';
|
|
35
|
+
import { runTestCasesAnalysisCommand } from './commands/test-cases-analysis/index.js';
|
|
36
|
+
import { runUserStoriesAnalysisCommand } from './commands/user-stories-analysis/index.js';
|
|
33
37
|
import { runWorkflow } from './commands/workflow/index.js';
|
|
34
38
|
import { DEFAULT_MAX_FILES as FIND_ARCHITECTURE_DEFAULT_MAX_FILES } from './phases/find-architecture/index.js';
|
|
35
39
|
import { DEFAULT_MAX_FILES as FIND_SMELLS_DEFAULT_MAX_FILES } from './phases/find-smells/index.js';
|
|
@@ -335,6 +339,70 @@ program
|
|
|
335
339
|
}
|
|
336
340
|
});
|
|
337
341
|
// ============================================================
|
|
342
|
+
// Subcommand: edsger issue-analysis <issueId>
|
|
343
|
+
// ============================================================
|
|
344
|
+
program
|
|
345
|
+
.command('issue-analysis <issueId>')
|
|
346
|
+
.description('Generate or refine the execution plan for an issue (issue_analysis phase, with verification loop)')
|
|
347
|
+
.option('-v, --verbose', 'Verbose output')
|
|
348
|
+
.action(async (issueId, opts) => {
|
|
349
|
+
try {
|
|
350
|
+
await runIssueAnalysisCommand({ issueId, verbose: opts.verbose });
|
|
351
|
+
}
|
|
352
|
+
catch (error) {
|
|
353
|
+
logError(error instanceof Error ? error.message : String(error));
|
|
354
|
+
process.exit(1);
|
|
355
|
+
}
|
|
356
|
+
});
|
|
357
|
+
// ============================================================
|
|
358
|
+
// Subcommand: edsger user-stories-analysis <issueId>
|
|
359
|
+
// ============================================================
|
|
360
|
+
program
|
|
361
|
+
.command('user-stories-analysis <issueId>')
|
|
362
|
+
.description('Generate or refine user stories for an issue (user_stories_analysis phase, with verification loop)')
|
|
363
|
+
.option('-v, --verbose', 'Verbose output')
|
|
364
|
+
.action(async (issueId, opts) => {
|
|
365
|
+
try {
|
|
366
|
+
await runUserStoriesAnalysisCommand({ issueId, verbose: opts.verbose });
|
|
367
|
+
}
|
|
368
|
+
catch (error) {
|
|
369
|
+
logError(error instanceof Error ? error.message : String(error));
|
|
370
|
+
process.exit(1);
|
|
371
|
+
}
|
|
372
|
+
});
|
|
373
|
+
// ============================================================
|
|
374
|
+
// Subcommand: edsger test-cases-analysis <issueId>
|
|
375
|
+
// ============================================================
|
|
376
|
+
program
|
|
377
|
+
.command('test-cases-analysis <issueId>')
|
|
378
|
+
.description('Generate or refine test cases for an issue (test_cases_analysis phase, with verification loop)')
|
|
379
|
+
.option('-v, --verbose', 'Verbose output')
|
|
380
|
+
.action(async (issueId, opts) => {
|
|
381
|
+
try {
|
|
382
|
+
await runTestCasesAnalysisCommand({ issueId, verbose: opts.verbose });
|
|
383
|
+
}
|
|
384
|
+
catch (error) {
|
|
385
|
+
logError(error instanceof Error ? error.message : String(error));
|
|
386
|
+
process.exit(1);
|
|
387
|
+
}
|
|
388
|
+
});
|
|
389
|
+
// ============================================================
|
|
390
|
+
// Subcommand: edsger technical-design <issueId>
|
|
391
|
+
// ============================================================
|
|
392
|
+
program
|
|
393
|
+
.command('technical-design <issueId>')
|
|
394
|
+
.description('Generate or refine the technical design for an issue (technical_design phase, with verification loop)')
|
|
395
|
+
.option('-v, --verbose', 'Verbose output')
|
|
396
|
+
.action(async (issueId, opts) => {
|
|
397
|
+
try {
|
|
398
|
+
await runTechnicalDesignCommand({ issueId, verbose: opts.verbose });
|
|
399
|
+
}
|
|
400
|
+
catch (error) {
|
|
401
|
+
logError(error instanceof Error ? error.message : String(error));
|
|
402
|
+
process.exit(1);
|
|
403
|
+
}
|
|
404
|
+
});
|
|
405
|
+
// ============================================================
|
|
338
406
|
// Subcommand: edsger smoke-test <releaseId>
|
|
339
407
|
// ============================================================
|
|
340
408
|
program
|
|
@@ -569,7 +637,17 @@ program
|
|
|
569
637
|
.option('--concurrency <number>', 'Max concurrent issues to process (default: 3)', parseInt)
|
|
570
638
|
.option('-c, --config <path>', 'Path to config file')
|
|
571
639
|
.option('-v, --verbose', 'Verbose output');
|
|
572
|
-
program.action(async (options) => {
|
|
640
|
+
program.action(async (options, command) => {
|
|
641
|
+
// Commander silently falls through to this default action when the user
|
|
642
|
+
// passes a subcommand name that isn't registered (e.g. an old binary that
|
|
643
|
+
// doesn't yet know about `sync-sentry-issues`). That makes version-skew
|
|
644
|
+
// bugs look like the agent inexplicably running with the wrong intent.
|
|
645
|
+
// Treat any leftover positional arg as an unknown command and abort.
|
|
646
|
+
if (command.args.length > 0) {
|
|
647
|
+
logError(`Unknown command: ${command.args[0]}`);
|
|
648
|
+
logError(`Run 'edsger --help' to see available commands.`);
|
|
649
|
+
process.exit(1);
|
|
650
|
+
}
|
|
573
651
|
try {
|
|
574
652
|
await runEdsger(options);
|
|
575
653
|
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { type EdsgerConfig } from '../types/index.js';
|
|
2
|
+
/** Result shape shared by all four issue-scoped phase functions.
|
|
3
|
+
* `pending` means the phase had no work to do (e.g. nothing to regenerate);
|
|
4
|
+
* it's not a failure. */
|
|
5
|
+
interface IssuePhaseResult {
|
|
6
|
+
status: 'success' | 'error' | 'pending';
|
|
7
|
+
summary: string;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Run a single-issue phase from the CLI: validate config, register a session,
|
|
11
|
+
* invoke the phase function, log the result, and set the process exit code on
|
|
12
|
+
* failure. Used by `issue-analysis`, `user-stories-analysis`,
|
|
13
|
+
* `test-cases-analysis`, and `technical-design` — all of which share the
|
|
14
|
+
* same `(options, config) => Result` shape and need the same wrapper.
|
|
15
|
+
*/
|
|
16
|
+
export declare const runIssuePhaseCli: <TResult extends IssuePhaseResult>(args: {
|
|
17
|
+
command: string;
|
|
18
|
+
description: string;
|
|
19
|
+
issueId: string;
|
|
20
|
+
verbose?: boolean;
|
|
21
|
+
execute: (options: {
|
|
22
|
+
issueId: string;
|
|
23
|
+
verbose?: boolean;
|
|
24
|
+
}, config: EdsgerConfig) => Promise<TResult>;
|
|
25
|
+
}) => Promise<void>;
|
|
26
|
+
export {};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { deregisterSession, registerSession, } from '../system/session-manager.js';
|
|
2
|
+
import { logError, logInfo } from './logger.js';
|
|
3
|
+
import { validateConfiguration } from './validation.js';
|
|
4
|
+
/**
|
|
5
|
+
* Run a single-issue phase from the CLI: validate config, register a session,
|
|
6
|
+
* invoke the phase function, log the result, and set the process exit code on
|
|
7
|
+
* failure. Used by `issue-analysis`, `user-stories-analysis`,
|
|
8
|
+
* `test-cases-analysis`, and `technical-design` — all of which share the
|
|
9
|
+
* same `(options, config) => Result` shape and need the same wrapper.
|
|
10
|
+
*/
|
|
11
|
+
export const runIssuePhaseCli = async (args) => {
|
|
12
|
+
const { command, description, issueId, verbose, execute } = args;
|
|
13
|
+
if (!issueId) {
|
|
14
|
+
throw new Error(`Issue ID is required for ${command}`);
|
|
15
|
+
}
|
|
16
|
+
const config = validateConfiguration({ verbose });
|
|
17
|
+
// registerSession must run inside the try so a partial failure still
|
|
18
|
+
// triggers deregisterSession in the finally — otherwise the server-side
|
|
19
|
+
// session row is leaked.
|
|
20
|
+
let registered = false;
|
|
21
|
+
try {
|
|
22
|
+
await registerSession({ command });
|
|
23
|
+
registered = true;
|
|
24
|
+
logInfo(`Starting ${description} for issue: ${issueId}`);
|
|
25
|
+
const result = await execute({ issueId, verbose }, config);
|
|
26
|
+
if (result.status === 'error') {
|
|
27
|
+
logError(`${description} failed: ${result.summary}`);
|
|
28
|
+
process.exitCode = 1;
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
// success or pending — both are non-failure outcomes
|
|
32
|
+
logInfo(result.summary);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
catch (error) {
|
|
36
|
+
logError(`${description} failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
37
|
+
process.exitCode = 1;
|
|
38
|
+
}
|
|
39
|
+
finally {
|
|
40
|
+
if (registered) {
|
|
41
|
+
await deregisterSession();
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
};
|