openspec-mcp 0.1.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.
Files changed (75) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +205 -0
  3. package/README.zh.md +205 -0
  4. package/dist/api/routes/approvals.d.ts +7 -0
  5. package/dist/api/routes/approvals.d.ts.map +1 -0
  6. package/dist/api/routes/approvals.js +99 -0
  7. package/dist/api/routes/approvals.js.map +1 -0
  8. package/dist/api/routes/changes.d.ts +7 -0
  9. package/dist/api/routes/changes.d.ts.map +1 -0
  10. package/dist/api/routes/changes.js +55 -0
  11. package/dist/api/routes/changes.js.map +1 -0
  12. package/dist/api/routes/specs.d.ts +7 -0
  13. package/dist/api/routes/specs.d.ts.map +1 -0
  14. package/dist/api/routes/specs.js +34 -0
  15. package/dist/api/routes/specs.js.map +1 -0
  16. package/dist/api/routes/tasks.d.ts +7 -0
  17. package/dist/api/routes/tasks.d.ts.map +1 -0
  18. package/dist/api/routes/tasks.js +61 -0
  19. package/dist/api/routes/tasks.js.map +1 -0
  20. package/dist/api/server.d.ts +23 -0
  21. package/dist/api/server.d.ts.map +1 -0
  22. package/dist/api/server.js +142 -0
  23. package/dist/api/server.js.map +1 -0
  24. package/dist/core/approval-manager.d.ts +69 -0
  25. package/dist/core/approval-manager.d.ts.map +1 -0
  26. package/dist/core/approval-manager.js +268 -0
  27. package/dist/core/approval-manager.js.map +1 -0
  28. package/dist/core/file-watcher.d.ts +38 -0
  29. package/dist/core/file-watcher.d.ts.map +1 -0
  30. package/dist/core/file-watcher.js +128 -0
  31. package/dist/core/file-watcher.js.map +1 -0
  32. package/dist/core/openspec-cli.d.ts +94 -0
  33. package/dist/core/openspec-cli.d.ts.map +1 -0
  34. package/dist/core/openspec-cli.js +436 -0
  35. package/dist/core/openspec-cli.js.map +1 -0
  36. package/dist/core/task-parser.d.ts +48 -0
  37. package/dist/core/task-parser.d.ts.map +1 -0
  38. package/dist/core/task-parser.js +172 -0
  39. package/dist/core/task-parser.js.map +1 -0
  40. package/dist/index.d.ts +9 -0
  41. package/dist/index.d.ts.map +1 -0
  42. package/dist/index.js +95 -0
  43. package/dist/index.js.map +1 -0
  44. package/dist/server/tools/approval.d.ts +8 -0
  45. package/dist/server/tools/approval.d.ts.map +1 -0
  46. package/dist/server/tools/approval.js +197 -0
  47. package/dist/server/tools/approval.js.map +1 -0
  48. package/dist/server/tools/archive.d.ts +8 -0
  49. package/dist/server/tools/archive.d.ts.map +1 -0
  50. package/dist/server/tools/archive.js +41 -0
  51. package/dist/server/tools/archive.js.map +1 -0
  52. package/dist/server/tools/guides.d.ts +8 -0
  53. package/dist/server/tools/guides.d.ts.map +1 -0
  54. package/dist/server/tools/guides.js +25 -0
  55. package/dist/server/tools/guides.js.map +1 -0
  56. package/dist/server/tools/management.d.ts +8 -0
  57. package/dist/server/tools/management.d.ts.map +1 -0
  58. package/dist/server/tools/management.js +96 -0
  59. package/dist/server/tools/management.js.map +1 -0
  60. package/dist/server/tools/tasks.d.ts +8 -0
  61. package/dist/server/tools/tasks.d.ts.map +1 -0
  62. package/dist/server/tools/tasks.js +124 -0
  63. package/dist/server/tools/tasks.js.map +1 -0
  64. package/dist/server/tools/validation.d.ts +8 -0
  65. package/dist/server/tools/validation.d.ts.map +1 -0
  66. package/dist/server/tools/validation.js +119 -0
  67. package/dist/server/tools/validation.js.map +1 -0
  68. package/dist/types/openspec.d.ts +141 -0
  69. package/dist/types/openspec.d.ts.map +1 -0
  70. package/dist/types/openspec.js +5 -0
  71. package/dist/types/openspec.js.map +1 -0
  72. package/package.json +58 -0
  73. package/web/dist/assets/index--LppUKpS.js +67 -0
  74. package/web/dist/assets/index-DdJQfs9Z.css +1 -0
  75. package/web/dist/index.html +14 -0
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Tasks REST API 路由
3
+ */
4
+ export function registerTasksRoutes(fastify, ctx) {
5
+ const { cli } = ctx;
6
+ /**
7
+ * GET /api/changes/:id/tasks - 获取变更的任务列表
8
+ */
9
+ fastify.get('/changes/:id/tasks', async (request, reply) => {
10
+ const { id } = request.params;
11
+ const result = await cli.getTasks(id);
12
+ return result;
13
+ });
14
+ /**
15
+ * PATCH /api/changes/:id/tasks/:taskId - 更新任务状态
16
+ */
17
+ fastify.patch('/changes/:id/tasks/:taskId', async (request, reply) => {
18
+ const { id, taskId } = request.params;
19
+ const { status } = request.body;
20
+ if (!status || !['pending', 'in_progress', 'done'].includes(status)) {
21
+ return reply.status(400).send({ error: 'Invalid status' });
22
+ }
23
+ const result = await cli.updateTaskStatus(id, taskId, status);
24
+ if (result.success) {
25
+ // 广播任务更新事件
26
+ ctx.broadcast('task:updated', { changeId: id, taskId, status });
27
+ return { success: true, taskId, status };
28
+ }
29
+ else {
30
+ return reply.status(400).send(result);
31
+ }
32
+ });
33
+ /**
34
+ * GET /api/progress - 获取所有变更的进度汇总
35
+ */
36
+ fastify.get('/progress', async () => {
37
+ const changes = await cli.listChanges();
38
+ const summaries = [];
39
+ for (const change of changes) {
40
+ const { progress } = await cli.getTasks(change.id);
41
+ summaries.push({
42
+ changeId: change.id,
43
+ title: change.title,
44
+ progress,
45
+ });
46
+ }
47
+ // 计算总体进度
48
+ const totalTasks = summaries.reduce((sum, s) => sum + s.progress.total, 0);
49
+ const completedTasks = summaries.reduce((sum, s) => sum + s.progress.completed, 0);
50
+ const overallPercentage = totalTasks > 0 ? Math.round((completedTasks / totalTasks) * 100) : 0;
51
+ return {
52
+ summaries,
53
+ overall: {
54
+ total: totalTasks,
55
+ completed: completedTasks,
56
+ percentage: overallPercentage,
57
+ },
58
+ };
59
+ });
60
+ }
61
+ //# sourceMappingURL=tasks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tasks.js","sourceRoot":"","sources":["../../../src/api/routes/tasks.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Fastify HTTP API Server
3
+ * 提供 REST API 和 WebSocket 实时更新
4
+ */
5
+ import { FastifyInstance } from 'fastify';
6
+ import { OpenSpecCli } from '../core/openspec-cli.js';
7
+ import { ApprovalManager } from '../core/approval-manager.js';
8
+ import { FileWatcher } from '../core/file-watcher.js';
9
+ export interface ApiServerOptions {
10
+ cwd: string;
11
+ port: number;
12
+ }
13
+ export interface ApiContext {
14
+ cli: OpenSpecCli;
15
+ approvalManager: ApprovalManager;
16
+ fileWatcher: FileWatcher;
17
+ broadcast: (event: string, data: any) => void;
18
+ }
19
+ /**
20
+ * 创建并启动 API 服务器
21
+ */
22
+ export declare function startApiServer(options: ApiServerOptions): Promise<FastifyInstance>;
23
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/api/server.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAgB,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAMnD,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAC9D,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAStD,MAAM,WAAW,gBAAgB;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,UAAU;IACzB,GAAG,EAAE,WAAW,CAAC;IACjB,eAAe,EAAE,eAAe,CAAC;IACjC,WAAW,EAAE,WAAW,CAAC;IACzB,SAAS,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,KAAK,IAAI,CAAC;CAC/C;AAED;;GAEG;AACH,wBAAsB,cAAc,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,eAAe,CAAC,CA+IxF"}
@@ -0,0 +1,142 @@
1
+ /**
2
+ * Fastify HTTP API Server
3
+ * 提供 REST API 和 WebSocket 实时更新
4
+ */
5
+ import Fastify from 'fastify';
6
+ import fastifyCors from '@fastify/cors';
7
+ import fastifyWebsocket from '@fastify/websocket';
8
+ import fastifyStatic from '@fastify/static';
9
+ import * as path from 'path';
10
+ import { fileURLToPath } from 'url';
11
+ import { OpenSpecCli } from '../core/openspec-cli.js';
12
+ import { ApprovalManager } from '../core/approval-manager.js';
13
+ import { FileWatcher } from '../core/file-watcher.js';
14
+ import { registerChangesRoutes } from './routes/changes.js';
15
+ import { registerSpecsRoutes } from './routes/specs.js';
16
+ import { registerTasksRoutes } from './routes/tasks.js';
17
+ import { registerApprovalsRoutes } from './routes/approvals.js';
18
+ const __filename = fileURLToPath(import.meta.url);
19
+ const __dirname = path.dirname(__filename);
20
+ /**
21
+ * 创建并启动 API 服务器
22
+ */
23
+ export async function startApiServer(options) {
24
+ const { cwd, port } = options;
25
+ // 创建 Fastify 实例
26
+ const fastify = Fastify({
27
+ logger: true,
28
+ });
29
+ // 注册插件
30
+ await fastify.register(fastifyCors, {
31
+ origin: true,
32
+ });
33
+ await fastify.register(fastifyWebsocket);
34
+ // 静态文件服务(Web Dashboard)
35
+ const webDir = path.join(__dirname, '../../web/dist');
36
+ try {
37
+ await fastify.register(fastifyStatic, {
38
+ root: webDir,
39
+ prefix: '/',
40
+ });
41
+ }
42
+ catch {
43
+ // Web dashboard 可能未构建
44
+ console.log('Web dashboard not found, skipping static files');
45
+ }
46
+ // 创建核心模块
47
+ const cli = new OpenSpecCli({ cwd });
48
+ const approvalManager = new ApprovalManager({ cwd });
49
+ const fileWatcher = new FileWatcher({ cwd });
50
+ // WebSocket 客户端列表
51
+ const wsClients = new Set();
52
+ // 广播函数
53
+ const broadcast = (event, data) => {
54
+ const message = JSON.stringify({ event, data, timestamp: new Date().toISOString() });
55
+ for (const client of wsClients) {
56
+ if (client.readyState === 1) {
57
+ // OPEN
58
+ client.send(message);
59
+ }
60
+ }
61
+ };
62
+ // API 上下文
63
+ const ctx = {
64
+ cli,
65
+ approvalManager,
66
+ fileWatcher,
67
+ broadcast,
68
+ };
69
+ // 注册 WebSocket 路由
70
+ fastify.get('/ws', { websocket: true }, (connection) => {
71
+ const { socket } = connection;
72
+ wsClients.add(socket);
73
+ console.log(`WebSocket client connected. Total: ${wsClients.size}`);
74
+ // 发送欢迎消息
75
+ socket.send(JSON.stringify({
76
+ event: 'connected',
77
+ data: { message: 'Connected to OpenSpec MCP Dashboard' },
78
+ timestamp: new Date().toISOString(),
79
+ }));
80
+ socket.on('message', (message) => {
81
+ try {
82
+ const data = JSON.parse(message.toString());
83
+ console.log('WebSocket message:', data);
84
+ // 处理订阅请求等
85
+ if (data.type === 'subscribe') {
86
+ // TODO: 实现订阅逻辑
87
+ }
88
+ }
89
+ catch (e) {
90
+ console.error('Invalid WebSocket message:', e);
91
+ }
92
+ });
93
+ socket.on('close', () => {
94
+ wsClients.delete(socket);
95
+ console.log(`WebSocket client disconnected. Total: ${wsClients.size}`);
96
+ });
97
+ });
98
+ // 注册 REST 路由
99
+ await fastify.register(async (instance) => {
100
+ registerChangesRoutes(instance, ctx);
101
+ registerSpecsRoutes(instance, ctx);
102
+ registerTasksRoutes(instance, ctx);
103
+ registerApprovalsRoutes(instance, ctx);
104
+ }, { prefix: '/api' });
105
+ // 健康检查
106
+ fastify.get('/health', async () => {
107
+ return { status: 'ok', version: '0.1.0' };
108
+ });
109
+ // SPA fallback - 所有非 API 路由返回 index.html
110
+ fastify.setNotFoundHandler(async (request, reply) => {
111
+ if (!request.url.startsWith('/api/') && !request.url.startsWith('/ws')) {
112
+ return reply.sendFile('index.html');
113
+ }
114
+ return reply.code(404).send({ error: 'Not Found', statusCode: 404 });
115
+ });
116
+ // 启动文件监控
117
+ fileWatcher.on('change', (event, filePath) => {
118
+ broadcast('file:changed', { event, filePath });
119
+ });
120
+ await fileWatcher.start();
121
+ // 启动服务器
122
+ try {
123
+ await fastify.listen({ port, host: '0.0.0.0' });
124
+ console.log(`\n🚀 OpenSpec MCP Dashboard running at http://localhost:${port}`);
125
+ console.log(`📁 Watching: ${cwd}/openspec`);
126
+ }
127
+ catch (err) {
128
+ fastify.log.error(err);
129
+ process.exit(1);
130
+ }
131
+ // 优雅关闭
132
+ const shutdown = async () => {
133
+ console.log('\nShutting down...');
134
+ await fileWatcher.stop();
135
+ await fastify.close();
136
+ process.exit(0);
137
+ };
138
+ process.on('SIGINT', shutdown);
139
+ process.on('SIGTERM', shutdown);
140
+ return fastify;
141
+ }
142
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/api/server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,69 @@
1
+ /**
2
+ * 审批管理器
3
+ * 管理变更提案的审批流程
4
+ */
5
+ import type { ApprovalRecord } from '../types/openspec.js';
6
+ export interface ApprovalManagerOptions {
7
+ cwd?: string;
8
+ }
9
+ export declare class ApprovalManager {
10
+ private cwd;
11
+ constructor(options?: ApprovalManagerOptions);
12
+ /**
13
+ * 获取审批目录路径
14
+ */
15
+ private getApprovalsDir;
16
+ /**
17
+ * 获取审批记录文件路径
18
+ */
19
+ private getApprovalPath;
20
+ /**
21
+ * 确保审批目录存在
22
+ */
23
+ private ensureApprovalsDir;
24
+ /**
25
+ * 获取审批状态
26
+ */
27
+ getApprovalStatus(changeId: string): Promise<ApprovalRecord | null>;
28
+ /**
29
+ * 创建或更新审批记录
30
+ */
31
+ private saveApproval;
32
+ /**
33
+ * 请求审批
34
+ */
35
+ requestApproval(changeId: string, requestedBy: string, reviewers?: string[]): Promise<ApprovalRecord>;
36
+ /**
37
+ * 审批通过
38
+ */
39
+ approve(changeId: string, approver: string, comment?: string): Promise<ApprovalRecord>;
40
+ /**
41
+ * 审批拒绝
42
+ */
43
+ reject(changeId: string, rejector: string, reason: string): Promise<ApprovalRecord>;
44
+ /**
45
+ * 开始实施
46
+ */
47
+ startImplementation(changeId: string, implementer: string): Promise<ApprovalRecord>;
48
+ /**
49
+ * 标记完成
50
+ */
51
+ markCompleted(changeId: string, completedBy: string): Promise<ApprovalRecord>;
52
+ /**
53
+ * 重置为草稿(用于被拒绝后重新提交)
54
+ */
55
+ resetToDraft(changeId: string, resetBy: string): Promise<ApprovalRecord>;
56
+ /**
57
+ * 列出所有审批记录
58
+ */
59
+ listApprovals(): Promise<ApprovalRecord[]>;
60
+ /**
61
+ * 列出待审批的记录
62
+ */
63
+ listPendingApprovals(): Promise<ApprovalRecord[]>;
64
+ /**
65
+ * 删除审批记录
66
+ */
67
+ deleteApproval(changeId: string): Promise<boolean>;
68
+ }
69
+ //# sourceMappingURL=approval-manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"approval-manager.d.ts","sourceRoot":"","sources":["../../src/core/approval-manager.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,KAAK,EAAE,cAAc,EAAkB,MAAM,sBAAsB,CAAC;AAE3E,MAAM,WAAW,sBAAsB;IACrC,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,qBAAa,eAAe;IAC1B,OAAO,CAAC,GAAG,CAAS;gBAER,OAAO,CAAC,EAAE,sBAAsB;IAI5C;;OAEG;IACH,OAAO,CAAC,eAAe;IAIvB;;OAEG;IACH,OAAO,CAAC,eAAe;IAIvB;;OAEG;YACW,kBAAkB;IAShC;;OAEG;IACG,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC;IAWzE;;OAEG;YACW,YAAY;IAM1B;;OAEG;IACG,eAAe,CACnB,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,EACnB,SAAS,CAAC,EAAE,MAAM,EAAE,GACnB,OAAO,CAAC,cAAc,CAAC;IAgC1B;;OAEG;IACG,OAAO,CACX,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,cAAc,CAAC;IAoC1B;;OAEG;IACG,MAAM,CACV,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,cAAc,CAAC;IAoC1B;;OAEG;IACG,mBAAmB,CACvB,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,cAAc,CAAC;IA0B1B;;OAEG;IACG,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IA0BnF;;OAEG;IACG,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAmC9E;;OAEG;IACG,aAAa,IAAI,OAAO,CAAC,cAAc,EAAE,CAAC;IAwBhD;;OAEG;IACG,oBAAoB,IAAI,OAAO,CAAC,cAAc,EAAE,CAAC;IAKvD;;OAEG;IACG,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAUzD"}
@@ -0,0 +1,268 @@
1
+ /**
2
+ * 审批管理器
3
+ * 管理变更提案的审批流程
4
+ */
5
+ import * as fs from 'fs/promises';
6
+ import * as path from 'path';
7
+ export class ApprovalManager {
8
+ cwd;
9
+ constructor(options) {
10
+ this.cwd = options?.cwd || process.cwd();
11
+ }
12
+ /**
13
+ * 获取审批目录路径
14
+ */
15
+ getApprovalsDir() {
16
+ return path.join(this.cwd, 'openspec', 'approvals');
17
+ }
18
+ /**
19
+ * 获取审批记录文件路径
20
+ */
21
+ getApprovalPath(changeId) {
22
+ return path.join(this.getApprovalsDir(), `${changeId}.json`);
23
+ }
24
+ /**
25
+ * 确保审批目录存在
26
+ */
27
+ async ensureApprovalsDir() {
28
+ const dir = this.getApprovalsDir();
29
+ try {
30
+ await fs.access(dir);
31
+ }
32
+ catch {
33
+ await fs.mkdir(dir, { recursive: true });
34
+ }
35
+ }
36
+ /**
37
+ * 获取审批状态
38
+ */
39
+ async getApprovalStatus(changeId) {
40
+ const approvalPath = this.getApprovalPath(changeId);
41
+ try {
42
+ const content = await fs.readFile(approvalPath, 'utf-8');
43
+ return JSON.parse(content);
44
+ }
45
+ catch {
46
+ return null;
47
+ }
48
+ }
49
+ /**
50
+ * 创建或更新审批记录
51
+ */
52
+ async saveApproval(record) {
53
+ await this.ensureApprovalsDir();
54
+ const approvalPath = this.getApprovalPath(record.changeId);
55
+ await fs.writeFile(approvalPath, JSON.stringify(record, null, 2), 'utf-8');
56
+ }
57
+ /**
58
+ * 请求审批
59
+ */
60
+ async requestApproval(changeId, requestedBy, reviewers) {
61
+ const existing = await this.getApprovalStatus(changeId);
62
+ const now = new Date().toISOString();
63
+ const record = existing || {
64
+ changeId,
65
+ status: 'draft',
66
+ approvals: [],
67
+ rejections: [],
68
+ history: [],
69
+ };
70
+ // 更新状态
71
+ record.status = 'pending_approval';
72
+ record.requestedAt = now;
73
+ record.requestedBy = requestedBy;
74
+ if (reviewers) {
75
+ record.reviewers = reviewers;
76
+ }
77
+ // 添加历史记录
78
+ record.history.push({
79
+ action: 'request_approval',
80
+ by: requestedBy,
81
+ at: now,
82
+ details: reviewers ? `Reviewers: ${reviewers.join(', ')}` : undefined,
83
+ });
84
+ await this.saveApproval(record);
85
+ return record;
86
+ }
87
+ /**
88
+ * 审批通过
89
+ */
90
+ async approve(changeId, approver, comment) {
91
+ const record = await this.getApprovalStatus(changeId);
92
+ const now = new Date().toISOString();
93
+ if (!record) {
94
+ throw new Error(`No approval record found for change: ${changeId}`);
95
+ }
96
+ if (record.status !== 'pending_approval') {
97
+ throw new Error(`Cannot approve change in status: ${record.status}. Must be pending_approval.`);
98
+ }
99
+ // 添加审批
100
+ record.approvals.push({
101
+ approver,
102
+ approvedAt: now,
103
+ comment,
104
+ });
105
+ // 更新状态
106
+ record.status = 'approved';
107
+ // 添加历史记录
108
+ record.history.push({
109
+ action: 'approved',
110
+ by: approver,
111
+ at: now,
112
+ details: comment,
113
+ });
114
+ await this.saveApproval(record);
115
+ return record;
116
+ }
117
+ /**
118
+ * 审批拒绝
119
+ */
120
+ async reject(changeId, rejector, reason) {
121
+ const record = await this.getApprovalStatus(changeId);
122
+ const now = new Date().toISOString();
123
+ if (!record) {
124
+ throw new Error(`No approval record found for change: ${changeId}`);
125
+ }
126
+ if (record.status !== 'pending_approval') {
127
+ throw new Error(`Cannot reject change in status: ${record.status}. Must be pending_approval.`);
128
+ }
129
+ // 添加拒绝
130
+ record.rejections.push({
131
+ rejector,
132
+ rejectedAt: now,
133
+ reason,
134
+ });
135
+ // 更新状态
136
+ record.status = 'rejected';
137
+ // 添加历史记录
138
+ record.history.push({
139
+ action: 'rejected',
140
+ by: rejector,
141
+ at: now,
142
+ details: reason,
143
+ });
144
+ await this.saveApproval(record);
145
+ return record;
146
+ }
147
+ /**
148
+ * 开始实施
149
+ */
150
+ async startImplementation(changeId, implementer) {
151
+ const record = await this.getApprovalStatus(changeId);
152
+ const now = new Date().toISOString();
153
+ if (!record) {
154
+ throw new Error(`No approval record found for change: ${changeId}`);
155
+ }
156
+ if (record.status !== 'approved') {
157
+ throw new Error(`Cannot start implementation in status: ${record.status}. Must be approved.`);
158
+ }
159
+ record.status = 'implementing';
160
+ record.history.push({
161
+ action: 'start_implementation',
162
+ by: implementer,
163
+ at: now,
164
+ });
165
+ await this.saveApproval(record);
166
+ return record;
167
+ }
168
+ /**
169
+ * 标记完成
170
+ */
171
+ async markCompleted(changeId, completedBy) {
172
+ const record = await this.getApprovalStatus(changeId);
173
+ const now = new Date().toISOString();
174
+ if (!record) {
175
+ throw new Error(`No approval record found for change: ${changeId}`);
176
+ }
177
+ if (record.status !== 'implementing') {
178
+ throw new Error(`Cannot mark as completed in status: ${record.status}. Must be implementing.`);
179
+ }
180
+ record.status = 'completed';
181
+ record.history.push({
182
+ action: 'completed',
183
+ by: completedBy,
184
+ at: now,
185
+ });
186
+ await this.saveApproval(record);
187
+ return record;
188
+ }
189
+ /**
190
+ * 重置为草稿(用于被拒绝后重新提交)
191
+ */
192
+ async resetToDraft(changeId, resetBy) {
193
+ const record = await this.getApprovalStatus(changeId);
194
+ const now = new Date().toISOString();
195
+ if (!record) {
196
+ // 创建新的草稿记录
197
+ const newRecord = {
198
+ changeId,
199
+ status: 'draft',
200
+ approvals: [],
201
+ rejections: [],
202
+ history: [
203
+ {
204
+ action: 'created',
205
+ by: resetBy,
206
+ at: now,
207
+ },
208
+ ],
209
+ };
210
+ await this.saveApproval(newRecord);
211
+ return newRecord;
212
+ }
213
+ record.status = 'draft';
214
+ record.history.push({
215
+ action: 'reset_to_draft',
216
+ by: resetBy,
217
+ at: now,
218
+ });
219
+ await this.saveApproval(record);
220
+ return record;
221
+ }
222
+ /**
223
+ * 列出所有审批记录
224
+ */
225
+ async listApprovals() {
226
+ const dir = this.getApprovalsDir();
227
+ const records = [];
228
+ try {
229
+ const files = await fs.readdir(dir);
230
+ for (const file of files) {
231
+ if (!file.endsWith('.json'))
232
+ continue;
233
+ try {
234
+ const content = await fs.readFile(path.join(dir, file), 'utf-8');
235
+ records.push(JSON.parse(content));
236
+ }
237
+ catch {
238
+ // 跳过无效文件
239
+ }
240
+ }
241
+ }
242
+ catch {
243
+ // 目录不存在
244
+ }
245
+ return records;
246
+ }
247
+ /**
248
+ * 列出待审批的记录
249
+ */
250
+ async listPendingApprovals() {
251
+ const all = await this.listApprovals();
252
+ return all.filter((r) => r.status === 'pending_approval');
253
+ }
254
+ /**
255
+ * 删除审批记录
256
+ */
257
+ async deleteApproval(changeId) {
258
+ const approvalPath = this.getApprovalPath(changeId);
259
+ try {
260
+ await fs.unlink(approvalPath);
261
+ return true;
262
+ }
263
+ catch {
264
+ return false;
265
+ }
266
+ }
267
+ }
268
+ //# sourceMappingURL=approval-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"approval-manager.js","sourceRoot":"","sources":["../../src/core/approval-manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * 文件监控器
3
+ * 使用 Chokidar 监控 openspec 目录变化
4
+ */
5
+ import { EventEmitter } from 'events';
6
+ export interface FileWatcherOptions {
7
+ cwd: string;
8
+ }
9
+ export declare class FileWatcher extends EventEmitter {
10
+ private cwd;
11
+ private watcher;
12
+ constructor(options: FileWatcherOptions);
13
+ /**
14
+ * 获取监控目录路径
15
+ */
16
+ private getWatchPath;
17
+ /**
18
+ * 启动监控
19
+ */
20
+ start(): Promise<void>;
21
+ /**
22
+ * 处理文件变化
23
+ */
24
+ private handleChange;
25
+ /**
26
+ * 获取文件类型
27
+ */
28
+ private getFileType;
29
+ /**
30
+ * 停止监控
31
+ */
32
+ stop(): Promise<void>;
33
+ /**
34
+ * 是否正在监控
35
+ */
36
+ isWatching(): boolean;
37
+ }
38
+ //# sourceMappingURL=file-watcher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-watcher.d.ts","sourceRoot":"","sources":["../../src/core/file-watcher.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAEtC,MAAM,WAAW,kBAAkB;IACjC,GAAG,EAAE,MAAM,CAAC;CACb;AAED,qBAAa,WAAY,SAAQ,YAAY;IAC3C,OAAO,CAAC,GAAG,CAAS;IACpB,OAAO,CAAC,OAAO,CAA0B;gBAE7B,OAAO,EAAE,kBAAkB;IAKvC;;OAEG;IACH,OAAO,CAAC,YAAY;IAIpB;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAuC5B;;OAEG;IACH,OAAO,CAAC,YAAY;IAqBpB;;OAEG;IACH,OAAO,CAAC,WAAW;IA0BnB;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAQ3B;;OAEG;IACH,UAAU,IAAI,OAAO;CAGtB"}