feat(cli): add handoff create/read/list commands
This commit is contained in:
parent
c4fbbbd865
commit
0cc88603e1
69
src/cli/commands/handoff.ts
Normal file
69
src/cli/commands/handoff.ts
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
import { input, select } from '@inquirer/prompts';
|
||||||
|
import { join } from 'path';
|
||||||
|
import { getEntityDir } from '../../core/paths.js';
|
||||||
|
import { getNextId } from '../../core/counter.js';
|
||||||
|
import { readEntity, writeEntity, listEntities } from '../../core/files.js';
|
||||||
|
import { HandoffSchema, type Handoff } from '../../core/schema.js';
|
||||||
|
import { Index } from '../../core/index.js';
|
||||||
|
|
||||||
|
const roles = ['architect', 'implementer', 'reviewer', 'tester'];
|
||||||
|
|
||||||
|
export async function handoffCreate(cwd: string, options: Partial<Handoff> = {}): Promise<void> {
|
||||||
|
const fromRole = options.fromRole ?? await select({ message: 'From role:', choices: roles.map((r) => ({ name: r, value: r })) });
|
||||||
|
const toRole = options.toRole ?? await select({ message: 'To role:', choices: roles.map((r) => ({ name: r, value: r })) });
|
||||||
|
const taskId = options.taskId ?? await input({ message: 'Related task id (optional):' });
|
||||||
|
const summary = options.summary ?? await input({ message: 'Summary:' });
|
||||||
|
const context = options.context ?? await input({ message: 'Context:' });
|
||||||
|
|
||||||
|
const now = new Date().toISOString();
|
||||||
|
const handoff: Handoff = HandoffSchema.parse({
|
||||||
|
id: getNextId(cwd, 'handoff'),
|
||||||
|
fromRole,
|
||||||
|
toRole,
|
||||||
|
taskId: taskId || undefined,
|
||||||
|
summary,
|
||||||
|
context,
|
||||||
|
createdAt: now,
|
||||||
|
});
|
||||||
|
|
||||||
|
const filePath = join(getEntityDir(cwd, 'handoffs'), `${handoff.id}.md`);
|
||||||
|
writeEntity(filePath, handoff, `# ${handoff.summary}\n\n${handoff.context}`);
|
||||||
|
|
||||||
|
const index = new Index(cwd);
|
||||||
|
index.upsert({
|
||||||
|
id: handoff.id,
|
||||||
|
type: 'handoff',
|
||||||
|
title: handoff.summary,
|
||||||
|
content: handoff.context,
|
||||||
|
filePath,
|
||||||
|
createdAt: handoff.createdAt,
|
||||||
|
updatedAt: handoff.createdAt,
|
||||||
|
});
|
||||||
|
index.close();
|
||||||
|
|
||||||
|
console.log(`Handoff created: ${handoff.id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function handoffRead(cwd: string, id: string): void {
|
||||||
|
const filePath = join(getEntityDir(cwd, 'handoffs'), `${id}.md`);
|
||||||
|
const { frontmatter, body } = readEntity(filePath);
|
||||||
|
console.log(`# ${frontmatter.summary}`);
|
||||||
|
console.log(`From: ${frontmatter.fromRole} → ${frontmatter.toRole}`);
|
||||||
|
if (frontmatter.taskId) console.log(`Task: ${frontmatter.taskId}`);
|
||||||
|
console.log('\n' + body);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function handoffList(cwd: string): void {
|
||||||
|
const index = new Index(cwd);
|
||||||
|
const handoffs = index.list('handoff');
|
||||||
|
index.close();
|
||||||
|
|
||||||
|
if (handoffs.length === 0) {
|
||||||
|
console.log('No handoffs found.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const h of handoffs) {
|
||||||
|
console.log(`${h.id}: ${h.title}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user