@fractary/faber-cli 1.5.29 → 1.5.31

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.
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Changelog subcommand - Machine-readable changelog management
3
+ *
4
+ * Provides emit, query, aggregate, and read-run operations via ChangelogManager SDK.
5
+ */
6
+ import { Command } from 'commander';
7
+ /**
8
+ * Create the changelog command tree
9
+ */
10
+ export declare function createChangelogCommand(): Command;
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/changelog/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIpC;;GAEG;AACH,wBAAgB,sBAAsB,IAAI,OAAO,CAUhD"}
@@ -0,0 +1,201 @@
1
+ /**
2
+ * Changelog subcommand - Machine-readable changelog management
3
+ *
4
+ * Provides emit, query, aggregate, and read-run operations via ChangelogManager SDK.
5
+ */
6
+ import { Command } from 'commander';
7
+ import chalk from 'chalk';
8
+ import { ChangelogManager } from '@fractary/faber';
9
+ /**
10
+ * Create the changelog command tree
11
+ */
12
+ export function createChangelogCommand() {
13
+ const changelog = new Command('changelog')
14
+ .description('Machine-readable changelog management');
15
+ changelog.addCommand(createChangelogEmitCommand());
16
+ changelog.addCommand(createChangelogQueryCommand());
17
+ changelog.addCommand(createChangelogAggregateCommand());
18
+ changelog.addCommand(createChangelogReadRunCommand());
19
+ return changelog;
20
+ }
21
+ function createChangelogEmitCommand() {
22
+ return new Command('emit')
23
+ .description('Emit a changelog entry for a completed step')
24
+ .requiredOption('--run-id <id>', 'Run identifier')
25
+ .requiredOption('--step-id <id>', 'Step identifier')
26
+ .requiredOption('--step-name <name>', 'Human-readable step name')
27
+ .requiredOption('--phase <phase>', 'FABER phase')
28
+ .requiredOption('--status <status>', 'Step status (success, warning, failure, skipped)')
29
+ .requiredOption('--event-type <type>', 'Semantic event type (e.g., CODE_MERGED)')
30
+ .requiredOption('--workflow-id <id>', 'Workflow identifier')
31
+ .requiredOption('--work-id <id>', 'Work item identifier')
32
+ .option('--target <target>', 'Target branch/environment/resource')
33
+ .option('--environment <env>', 'Target environment (test, prod)')
34
+ .option('--message <msg>', 'Human-readable description')
35
+ .option('--duration-ms <ms>', 'Step duration in milliseconds')
36
+ .option('--metadata <json>', 'Step-specific metadata (JSON string)')
37
+ .option('--custom <json>', 'Project-specific custom data (JSON string)')
38
+ .option('--json', 'Output as JSON')
39
+ .action(async (options) => {
40
+ try {
41
+ const manager = new ChangelogManager();
42
+ const entry = manager.emit({
43
+ run_id: options.runId,
44
+ step_id: options.stepId,
45
+ step_name: options.stepName,
46
+ phase: options.phase,
47
+ status: options.status,
48
+ event_type: options.eventType,
49
+ workflow_id: options.workflowId,
50
+ work_id: options.workId,
51
+ target: options.target,
52
+ environment: options.environment,
53
+ message: options.message,
54
+ duration_ms: options.durationMs ? parseInt(options.durationMs, 10) : undefined,
55
+ metadata: options.metadata ? JSON.parse(options.metadata) : undefined,
56
+ custom: options.custom ? JSON.parse(options.custom) : undefined,
57
+ });
58
+ if (options.json) {
59
+ console.log(JSON.stringify({ status: 'success', data: entry }, null, 2));
60
+ }
61
+ else {
62
+ console.log(chalk.green(`Emitted changelog entry: ${entry.event_type}`));
63
+ console.log(chalk.gray(` Event ID: ${entry.event_id}`));
64
+ console.log(chalk.gray(` Step: ${entry.step_name}`));
65
+ }
66
+ }
67
+ catch (error) {
68
+ handleChangelogError(error, options);
69
+ }
70
+ });
71
+ }
72
+ function createChangelogQueryCommand() {
73
+ return new Command('query')
74
+ .description('Query the project-level changelog')
75
+ .option('--event-type <type>', 'Filter by event type')
76
+ .option('--target <target>', 'Filter by target')
77
+ .option('--phase <phase>', 'Filter by phase')
78
+ .option('--status <status>', 'Filter by status')
79
+ .option('--work-id <id>', 'Filter by work item ID')
80
+ .option('--since <date>', 'Filter entries after this date (ISO 8601)')
81
+ .option('--until <date>', 'Filter entries before this date (ISO 8601)')
82
+ .option('--limit <n>', 'Maximum entries to return')
83
+ .option('--json', 'Output as JSON')
84
+ .action(async (options) => {
85
+ try {
86
+ const manager = new ChangelogManager();
87
+ const result = manager.query({
88
+ event_type: options.eventType,
89
+ target: options.target,
90
+ phase: options.phase,
91
+ status: options.status,
92
+ work_id: options.workId,
93
+ since: options.since,
94
+ until: options.until,
95
+ limit: options.limit ? parseInt(options.limit, 10) : undefined,
96
+ });
97
+ if (options.json) {
98
+ console.log(JSON.stringify({ status: 'success', data: result }, null, 2));
99
+ }
100
+ else {
101
+ if (result.entries.length === 0) {
102
+ console.log(chalk.yellow('No changelog entries found'));
103
+ }
104
+ else {
105
+ console.log(chalk.bold(`Changelog entries (${result.entries.length} of ${result.total}):\n`));
106
+ for (const entry of result.entries) {
107
+ const statusColor = entry.status === 'success' ? chalk.green
108
+ : entry.status === 'failure' ? chalk.red
109
+ : entry.status === 'warning' ? chalk.yellow
110
+ : chalk.gray;
111
+ console.log(`${statusColor(entry.status.padEnd(8))} ${chalk.cyan(entry.event_type.padEnd(22))} ${entry.step_name}`);
112
+ console.log(chalk.gray(` ${entry.timestamp} phase:${entry.phase} work:${entry.work_id}${entry.environment ? ' env:' + entry.environment : ''}`));
113
+ if (entry.message) {
114
+ console.log(chalk.gray(` ${entry.message}`));
115
+ }
116
+ console.log('');
117
+ }
118
+ }
119
+ }
120
+ }
121
+ catch (error) {
122
+ handleChangelogError(error, options);
123
+ }
124
+ });
125
+ }
126
+ function createChangelogAggregateCommand() {
127
+ return new Command('aggregate')
128
+ .description('Aggregate per-run changelog to project-level file')
129
+ .requiredOption('--run-id <id>', 'Run identifier to aggregate')
130
+ .option('--json', 'Output as JSON')
131
+ .action(async (options) => {
132
+ try {
133
+ const manager = new ChangelogManager();
134
+ const result = manager.aggregate(options.runId);
135
+ if (options.json) {
136
+ console.log(JSON.stringify({ status: 'success', data: result }, null, 2));
137
+ }
138
+ else {
139
+ if (result.entries_aggregated === 0) {
140
+ console.log(chalk.yellow('No entries to aggregate'));
141
+ }
142
+ else {
143
+ console.log(chalk.green(`Aggregated ${result.entries_aggregated} changelog entries`));
144
+ }
145
+ }
146
+ }
147
+ catch (error) {
148
+ handleChangelogError(error, options);
149
+ }
150
+ });
151
+ }
152
+ function createChangelogReadRunCommand() {
153
+ return new Command('read-run')
154
+ .description('Read changelog entries for a specific run')
155
+ .requiredOption('--run-id <id>', 'Run identifier')
156
+ .option('--json', 'Output as JSON')
157
+ .action(async (options) => {
158
+ try {
159
+ const manager = new ChangelogManager();
160
+ const entries = manager.readRun(options.runId);
161
+ if (options.json) {
162
+ console.log(JSON.stringify({ status: 'success', data: { entries, total: entries.length } }, null, 2));
163
+ }
164
+ else {
165
+ if (entries.length === 0) {
166
+ console.log(chalk.yellow('No changelog entries for this run'));
167
+ }
168
+ else {
169
+ console.log(chalk.bold(`Run changelog (${entries.length} entries):\n`));
170
+ for (const entry of entries) {
171
+ const statusColor = entry.status === 'success' ? chalk.green
172
+ : entry.status === 'failure' ? chalk.red
173
+ : entry.status === 'warning' ? chalk.yellow
174
+ : chalk.gray;
175
+ console.log(`${statusColor(entry.status.padEnd(8))} ${chalk.cyan(entry.event_type.padEnd(22))} ${entry.step_name}`);
176
+ if (entry.message) {
177
+ console.log(chalk.gray(` ${entry.message}`));
178
+ }
179
+ }
180
+ }
181
+ }
182
+ }
183
+ catch (error) {
184
+ handleChangelogError(error, options);
185
+ }
186
+ });
187
+ }
188
+ // Error handling
189
+ function handleChangelogError(error, options) {
190
+ const message = error instanceof Error ? error.message : String(error);
191
+ if (options.json) {
192
+ console.error(JSON.stringify({
193
+ status: 'error',
194
+ error: { code: 'CHANGELOG_ERROR', message },
195
+ }));
196
+ }
197
+ else {
198
+ console.error(chalk.red('Error:'), message);
199
+ }
200
+ process.exit(1);
201
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/commands/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAsCpC,wBAAgB,mBAAmB,IAAI,OAAO,CA6e7C"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/commands/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAsCpC,wBAAgB,mBAAmB,IAAI,OAAO,CAkf7C"}
@@ -127,6 +127,7 @@ export function createConfigCommand() {
127
127
  .option('--default-workflow <id>', 'Default workflow ID', 'default')
128
128
  .option('--autonomy <level>', 'Autonomy level (dry-run|assisted|guarded|autonomous)', 'guarded')
129
129
  .option('--runs-path <path>', 'Directory for run artifacts', '.fractary/faber/runs')
130
+ .option('--changelog-path <path>', 'Path for project-level changelog file', '.fractary/changelog.ndjson')
130
131
  .option('--force', 'Overwrite existing configuration')
131
132
  .action(async (options) => {
132
133
  try {
@@ -155,6 +156,9 @@ export function createConfigCommand() {
155
156
  runs: {
156
157
  path: options.runsPath,
157
158
  },
159
+ changelog: {
160
+ path: options.changelogPath,
161
+ },
158
162
  };
159
163
  // Load existing config or create empty
160
164
  let config = loadYamlConfig({ warnMissingEnvVars: false }) || { version: '2.0' };
@@ -197,6 +201,7 @@ ${yaml.dump(manifest, { indent: 2, lineWidth: 100 })}`;
197
201
  console.log(` Default workflow: ${options.defaultWorkflow}`);
198
202
  console.log(` Autonomy: ${options.autonomy}`);
199
203
  console.log(` Runs path: ${options.runsPath}`);
204
+ console.log(` Changelog path: ${options.changelogPath}`);
200
205
  }
201
206
  catch (error) {
202
207
  console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA;;;;;GAKG;AAMH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAoBpC;;GAEG;AACH,wBAAgB,cAAc,IAAI,OAAO,CAqDxC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA;;;;;GAKG;AAMH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAqBpC;;GAEG;AACH,wBAAgB,cAAc,IAAI,OAAO,CAsDxC"}
package/dist/index.js CHANGED
@@ -15,6 +15,7 @@ import { createSessionLoadCommand, createSessionSaveCommand } from './commands/s
15
15
  import { createWorkCommand } from './commands/work/index.js';
16
16
  import { createRepoCommand } from './commands/repo/index.js';
17
17
  import { createLogsCommand } from './commands/logs/index.js';
18
+ import { createChangelogCommand } from './commands/changelog/index.js';
18
19
  import { createMigrateCommand } from './commands/migrate.js';
19
20
  import { createPlanCommand } from './commands/plan/index.js';
20
21
  import { createAuthCommand } from './commands/auth/index.js';
@@ -59,6 +60,7 @@ export function createFaberCLI() {
59
60
  program.addCommand(createWorkCommand());
60
61
  program.addCommand(createRepoCommand());
61
62
  program.addCommand(createLogsCommand());
63
+ program.addCommand(createChangelogCommand());
62
64
  // Help command
63
65
  program.addCommand(new Command('help')
64
66
  .description('Show help for all commands')
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fractary/faber-cli",
3
- "version": "1.5.29",
3
+ "version": "1.5.31",
4
4
  "description": "FABER CLI - Command-line interface for FABER development toolkit",
5
5
  "main": "dist/index.js",
6
6
  "bin": {