@bicorne/task-flow 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 (118) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +252 -0
  3. package/SKILL.md +250 -0
  4. package/assets/.harnessrc +10 -0
  5. package/assets/PHASE-task.json.example +50 -0
  6. package/assets/design.md +69 -0
  7. package/assets/hooks.json +15 -0
  8. package/assets/product-requirement.md +82 -0
  9. package/assets/schema.json +127 -0
  10. package/assets/tasks.md +26 -0
  11. package/dist/commands/analyze.d.ts +32 -0
  12. package/dist/commands/analyze.js +338 -0
  13. package/dist/commands/archive.d.ts +11 -0
  14. package/dist/commands/archive.js +53 -0
  15. package/dist/commands/design.d.ts +38 -0
  16. package/dist/commands/design.js +492 -0
  17. package/dist/commands/extract.d.ts +31 -0
  18. package/dist/commands/extract.js +477 -0
  19. package/dist/commands/init.d.ts +24 -0
  20. package/dist/commands/init.js +165 -0
  21. package/dist/commands/merge/index.d.ts +17 -0
  22. package/dist/commands/merge/index.js +322 -0
  23. package/dist/commands/merge/merger.d.ts +18 -0
  24. package/dist/commands/merge/merger.js +151 -0
  25. package/dist/commands/merge/types.d.ts +67 -0
  26. package/dist/commands/merge/types.js +6 -0
  27. package/dist/commands/merge/validators.d.ts +14 -0
  28. package/dist/commands/merge/validators.js +147 -0
  29. package/dist/commands/merge.d.ts +7 -0
  30. package/dist/commands/merge.js +15 -0
  31. package/dist/commands/start.d.ts +32 -0
  32. package/dist/commands/start.js +265 -0
  33. package/dist/commands/status.d.ts +15 -0
  34. package/dist/commands/status.js +143 -0
  35. package/dist/commands/sync.d.ts +11 -0
  36. package/dist/commands/sync.js +58 -0
  37. package/dist/commands/tasks-gen/doc-parser.d.ts +7 -0
  38. package/dist/commands/tasks-gen/doc-parser.js +259 -0
  39. package/dist/commands/tasks-gen/generators.d.ts +33 -0
  40. package/dist/commands/tasks-gen/generators.js +141 -0
  41. package/dist/commands/tasks-gen/index.d.ts +30 -0
  42. package/dist/commands/tasks-gen/index.js +345 -0
  43. package/dist/commands/tasks-gen/parsers.d.ts +29 -0
  44. package/dist/commands/tasks-gen/parsers.js +272 -0
  45. package/dist/commands/tasks-gen/templates.d.ts +8 -0
  46. package/dist/commands/tasks-gen/templates.js +37 -0
  47. package/dist/commands/tasks-gen/types.d.ts +71 -0
  48. package/dist/commands/tasks-gen/types.js +17 -0
  49. package/dist/commands/tasks-gen/validators.d.ts +14 -0
  50. package/dist/commands/tasks-gen/validators.js +54 -0
  51. package/dist/commands/tasks.d.ts +9 -0
  52. package/dist/commands/tasks.js +22 -0
  53. package/dist/commands/worktree.d.ts +28 -0
  54. package/dist/commands/worktree.js +275 -0
  55. package/dist/hooks/check-prd-exists.d.ts +20 -0
  56. package/dist/hooks/check-prd-exists.js +61 -0
  57. package/dist/hooks/check-worktree-conflict.d.ts +34 -0
  58. package/dist/hooks/check-worktree-conflict.js +107 -0
  59. package/dist/hooks/hook-runner/executor.d.ts +18 -0
  60. package/dist/hooks/hook-runner/executor.js +143 -0
  61. package/dist/hooks/hook-runner/index.d.ts +64 -0
  62. package/dist/hooks/hook-runner/index.js +220 -0
  63. package/dist/hooks/hook-runner/loader.d.ts +23 -0
  64. package/dist/hooks/hook-runner/loader.js +126 -0
  65. package/dist/hooks/hook-runner/types.d.ts +59 -0
  66. package/dist/hooks/hook-runner/types.js +6 -0
  67. package/dist/hooks/hook-runner.d.ts +9 -0
  68. package/dist/hooks/hook-runner.js +30 -0
  69. package/dist/hooks/phase-complete-detector.d.ts +35 -0
  70. package/dist/hooks/phase-complete-detector.js +203 -0
  71. package/dist/hooks/phase-gate-validator.d.ts +76 -0
  72. package/dist/hooks/phase-gate-validator.js +407 -0
  73. package/dist/hooks/save-checkpoint.d.ts +43 -0
  74. package/dist/hooks/save-checkpoint.js +144 -0
  75. package/dist/hooks/start-mcp-servers.d.ts +50 -0
  76. package/dist/hooks/start-mcp-servers.js +75 -0
  77. package/dist/hooks/stop-mcp-servers.d.ts +40 -0
  78. package/dist/hooks/stop-mcp-servers.js +58 -0
  79. package/dist/index.d.ts +29 -0
  80. package/dist/index.js +238 -0
  81. package/dist/lib/archive.d.ts +31 -0
  82. package/dist/lib/archive.js +226 -0
  83. package/dist/lib/config.d.ts +93 -0
  84. package/dist/lib/config.js +251 -0
  85. package/dist/lib/constants.d.ts +222 -0
  86. package/dist/lib/constants.js +247 -0
  87. package/dist/lib/interactive.d.ts +31 -0
  88. package/dist/lib/interactive.js +166 -0
  89. package/dist/lib/mcp-client.d.ts +156 -0
  90. package/dist/lib/mcp-client.js +370 -0
  91. package/dist/lib/state.d.ts +119 -0
  92. package/dist/lib/state.js +293 -0
  93. package/dist/slash/executor.d.ts +22 -0
  94. package/dist/slash/executor.js +259 -0
  95. package/dist/slash/index.d.ts +11 -0
  96. package/dist/slash/index.js +45 -0
  97. package/dist/slash/parser.d.ts +24 -0
  98. package/dist/slash/parser.js +101 -0
  99. package/dist/slash/registry.d.ts +22 -0
  100. package/dist/slash/registry.js +155 -0
  101. package/dist/spec/openspec-to-task/builders.d.ts +107 -0
  102. package/dist/spec/openspec-to-task/builders.js +138 -0
  103. package/dist/spec/openspec-to-task/index.d.ts +20 -0
  104. package/dist/spec/openspec-to-task/index.js +182 -0
  105. package/dist/spec/openspec-to-task/parsers.d.ts +65 -0
  106. package/dist/spec/openspec-to-task/parsers.js +232 -0
  107. package/dist/spec/openspec-to-task/types.d.ts +49 -0
  108. package/dist/spec/openspec-to-task/types.js +6 -0
  109. package/dist/spec/sync-openspec-to-task.d.ts +7 -0
  110. package/dist/spec/sync-openspec-to-task.js +21 -0
  111. package/dist/spec/sync-task-to-openspec.d.ts +27 -0
  112. package/dist/spec/sync-task-to-openspec.js +288 -0
  113. package/dist/types/ai-context.d.ts +108 -0
  114. package/dist/types/ai-context.js +9 -0
  115. package/package.json +66 -0
  116. package/references/AI-CONVERSATION-TUTORIAL.md +270 -0
  117. package/references/CLI-TUTORIAL.md +447 -0
  118. package/references/GIT-WORKTREE-SOP.md +109 -0
@@ -0,0 +1,182 @@
1
+ "use strict";
2
+ /**
3
+ * spec/openspec-to-task/index.ts
4
+ * Sync Spec change to harness task definition
5
+ *
6
+ * Usage:
7
+ * node sync-openspec-to-task.js --change <change-name> [options]
8
+ */
9
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ var desc = Object.getOwnPropertyDescriptor(m, k);
12
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
13
+ desc = { enumerable: true, get: function() { return m[k]; } };
14
+ }
15
+ Object.defineProperty(o, k2, desc);
16
+ }) : (function(o, m, k, k2) {
17
+ if (k2 === undefined) k2 = k;
18
+ o[k2] = m[k];
19
+ }));
20
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
21
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
22
+ }) : function(o, v) {
23
+ o["default"] = v;
24
+ });
25
+ var __importStar = (this && this.__importStar) || (function () {
26
+ var ownKeys = function(o) {
27
+ ownKeys = Object.getOwnPropertyNames || function (o) {
28
+ var ar = [];
29
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
30
+ return ar;
31
+ };
32
+ return ownKeys(o);
33
+ };
34
+ return function (mod) {
35
+ if (mod && mod.__esModule) return mod;
36
+ var result = {};
37
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
38
+ __setModuleDefault(result, mod);
39
+ return result;
40
+ };
41
+ })();
42
+ Object.defineProperty(exports, "__esModule", { value: true });
43
+ exports.syncSpecToTask = syncSpecToTask;
44
+ exports.main = main;
45
+ const fs = __importStar(require("fs"));
46
+ const path = __importStar(require("path"));
47
+ const config_1 = require("../../lib/config");
48
+ const parsers_1 = require("./parsers");
49
+ const builders_1 = require("./builders");
50
+ /**
51
+ * Validate config has required properties for sync
52
+ */
53
+ function validateConfigForSync(config) {
54
+ if (!config.projectRoot) {
55
+ return {
56
+ valid: false,
57
+ reason: 'missing-project-root',
58
+ message: 'Config missing projectRoot',
59
+ };
60
+ }
61
+ if (!config.specRootAbs) {
62
+ return {
63
+ valid: false,
64
+ reason: 'missing-spec-root',
65
+ message: 'Config missing specRootAbs',
66
+ };
67
+ }
68
+ if (!config.tasksDirAbs) {
69
+ return {
70
+ valid: false,
71
+ reason: 'missing-tasks-dir',
72
+ message: 'Config missing tasksDirAbs',
73
+ };
74
+ }
75
+ return { valid: true };
76
+ }
77
+ /**
78
+ * Sync Spec to task
79
+ */
80
+ function syncSpecToTask(options = {}) {
81
+ const config = (0, config_1.loadConfig)({ cwd: options.cwd });
82
+ const changeName = String(options.change || '').trim();
83
+ if (!changeName) {
84
+ return {
85
+ success: false,
86
+ reason: 'missing-change',
87
+ message: 'Missing required argument: --change <change-name>',
88
+ };
89
+ }
90
+ // Validate config before use
91
+ const configValidation = validateConfigForSync(config);
92
+ if (!configValidation.valid) {
93
+ return {
94
+ success: false,
95
+ reason: configValidation.reason,
96
+ message: configValidation.message || 'Unknown config validation error',
97
+ };
98
+ }
99
+ const projectRoot = config.projectRoot || process.cwd();
100
+ const specRoot = config.specRootAbs || path.resolve(projectRoot, 'spec');
101
+ const changeDir = path.resolve(specRoot, 'changes', changeName);
102
+ const proposalPath = path.resolve(changeDir, 'product-requirement.md');
103
+ const designPath = path.resolve(changeDir, 'design.md');
104
+ const tasksPath = path.resolve(changeDir, 'tasks.md');
105
+ if (!fs.existsSync(changeDir)) {
106
+ return {
107
+ success: false,
108
+ reason: 'missing-change-dir',
109
+ message: `Spec change not found: ${changeDir}`,
110
+ };
111
+ }
112
+ // Continue with sync only if change directory exists
113
+ const proposalContent = (0, parsers_1.readIfExists)(proposalPath);
114
+ const designContent = (0, parsers_1.readIfExists)(designPath);
115
+ const tasksContent = (0, parsers_1.readIfExists)(tasksPath);
116
+ const { manifestPath, manifest, executionPath } = (0, parsers_1.resolveStructuredConfig)(changeDir, changeName);
117
+ const syncParams = (0, builders_1.buildSyncParams)(options, config, changeName, changeDir, proposalContent, designContent, tasksContent, manifest, manifestPath, executionPath);
118
+ const taskOutputPath = path.resolve(projectRoot, String(options.output || path.relative(projectRoot, path.resolve(config.tasksDirAbs, `${syncParams.taskId}.json`))));
119
+ const taskJson = (0, builders_1.buildTaskJson)({
120
+ ...syncParams,
121
+ changeName,
122
+ manifestPath,
123
+ executionPath,
124
+ config,
125
+ });
126
+ if (options.dryRun) {
127
+ return {
128
+ success: true,
129
+ taskId: syncParams.taskId,
130
+ json: taskJson,
131
+ dryRun: true,
132
+ };
133
+ }
134
+ fs.mkdirSync(path.dirname(taskOutputPath), { recursive: true });
135
+ if (!options.force && fs.existsSync(taskOutputPath)) {
136
+ return {
137
+ success: false,
138
+ reason: 'file-exists',
139
+ message: 'Target task file already exists. Use --force to overwrite.',
140
+ };
141
+ }
142
+ fs.writeFileSync(taskOutputPath, taskJson, 'utf8');
143
+ return {
144
+ success: true,
145
+ taskId: syncParams.taskId,
146
+ taskPath: (0, parsers_1.ensurePosix)(path.relative(config.projectRoot, taskOutputPath)),
147
+ };
148
+ }
149
+ /**
150
+ * Main entry point
151
+ */
152
+ function main() {
153
+ const args = (0, parsers_1.parseArgs)(process.argv);
154
+ const result = syncSpecToTask({
155
+ cwd: args.cwd,
156
+ change: args.change,
157
+ taskId: args['task-id'],
158
+ type: args.type,
159
+ priority: args.priority,
160
+ worktree: args.worktree,
161
+ output: args.output,
162
+ force: args.force === true,
163
+ dryRun: args['dry-run'] === true,
164
+ });
165
+ if (!result.success) {
166
+ console.error(`[SPEC-SYNC] ${result.message}`);
167
+ process.exit(1);
168
+ }
169
+ if (result.dryRun) {
170
+ const jsonOutput = result.json || '';
171
+ process.stdout.write(jsonOutput);
172
+ process.exit(0);
173
+ }
174
+ console.log(`[SPEC-SYNC] Generated task: ${result.taskPath}`);
175
+ process.exit(0);
176
+ }
177
+ if (require.main === module) {
178
+ main();
179
+ }
180
+ exports.default = {
181
+ syncSpecToTask,
182
+ };
@@ -0,0 +1,65 @@
1
+ /**
2
+ * spec/openspec-to-task/parsers.ts
3
+ * Parsing and extraction utilities for Spec to task sync
4
+ */
5
+ import { ManifestJson } from './types';
6
+ /**
7
+ * Parse CLI arguments
8
+ */
9
+ export declare function parseArgs(argv: string[]): Record<string, string | boolean>;
10
+ /**
11
+ * Ensure POSIX path
12
+ */
13
+ export declare function ensurePosix(p: string | undefined): string;
14
+ /**
15
+ * Sanitize task ID
16
+ */
17
+ export declare function toTaskId(input: string | undefined): string;
18
+ /**
19
+ * Generate worktree name
20
+ */
21
+ export declare function toWorktreeName(type: string, taskId: string): string;
22
+ /**
23
+ * Read file if exists
24
+ */
25
+ export declare function readIfExists(filePath: string): string;
26
+ /**
27
+ * Read JSON if exists
28
+ */
29
+ export declare function readJsonIfExists<T>(filePath: string): T | null;
30
+ /**
31
+ * Deduplicate array
32
+ */
33
+ export declare function uniqueArray(items: (string | undefined)[]): string[];
34
+ /**
35
+ * Normalize boolean
36
+ */
37
+ export declare function normalizeBoolean(value: unknown, fallback: boolean): boolean;
38
+ /**
39
+ * Extract title from proposal
40
+ */
41
+ export declare function extractTitle(changeName: string, proposalContent: string): string;
42
+ /**
43
+ * Extract checklist items from tasks.md
44
+ */
45
+ export declare function extractChecklistItems(tasksContent: string): string[];
46
+ /**
47
+ * Extract file candidates from text
48
+ */
49
+ export declare function extractFileCandidates(texts: (string | null)[]): string[];
50
+ /**
51
+ * Infer implementation validations
52
+ */
53
+ export declare function inferImplementationValidations(checklistItems: string[]): string[];
54
+ /**
55
+ * Infer review validations
56
+ */
57
+ export declare function inferReviewValidations(checklistItems: string[]): string[];
58
+ /**
59
+ * Resolve structured config from change directory
60
+ */
61
+ export declare function resolveStructuredConfig(changeDir: string, changeName: string): {
62
+ manifestPath: string;
63
+ manifest: ManifestJson;
64
+ executionPath: string;
65
+ };
@@ -0,0 +1,232 @@
1
+ "use strict";
2
+ /**
3
+ * spec/openspec-to-task/parsers.ts
4
+ * Parsing and extraction utilities for Spec to task sync
5
+ */
6
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
7
+ if (k2 === undefined) k2 = k;
8
+ var desc = Object.getOwnPropertyDescriptor(m, k);
9
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
10
+ desc = { enumerable: true, get: function() { return m[k]; } };
11
+ }
12
+ Object.defineProperty(o, k2, desc);
13
+ }) : (function(o, m, k, k2) {
14
+ if (k2 === undefined) k2 = k;
15
+ o[k2] = m[k];
16
+ }));
17
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
18
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
19
+ }) : function(o, v) {
20
+ o["default"] = v;
21
+ });
22
+ var __importStar = (this && this.__importStar) || (function () {
23
+ var ownKeys = function(o) {
24
+ ownKeys = Object.getOwnPropertyNames || function (o) {
25
+ var ar = [];
26
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
27
+ return ar;
28
+ };
29
+ return ownKeys(o);
30
+ };
31
+ return function (mod) {
32
+ if (mod && mod.__esModule) return mod;
33
+ var result = {};
34
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
35
+ __setModuleDefault(result, mod);
36
+ return result;
37
+ };
38
+ })();
39
+ Object.defineProperty(exports, "__esModule", { value: true });
40
+ exports.parseArgs = parseArgs;
41
+ exports.ensurePosix = ensurePosix;
42
+ exports.toTaskId = toTaskId;
43
+ exports.toWorktreeName = toWorktreeName;
44
+ exports.readIfExists = readIfExists;
45
+ exports.readJsonIfExists = readJsonIfExists;
46
+ exports.uniqueArray = uniqueArray;
47
+ exports.normalizeBoolean = normalizeBoolean;
48
+ exports.extractTitle = extractTitle;
49
+ exports.extractChecklistItems = extractChecklistItems;
50
+ exports.extractFileCandidates = extractFileCandidates;
51
+ exports.inferImplementationValidations = inferImplementationValidations;
52
+ exports.inferReviewValidations = inferReviewValidations;
53
+ exports.resolveStructuredConfig = resolveStructuredConfig;
54
+ const fs = __importStar(require("fs"));
55
+ const path = __importStar(require("path"));
56
+ /**
57
+ * Parse CLI arguments
58
+ */
59
+ function parseArgs(argv) {
60
+ const args = {};
61
+ for (let i = 2; i < argv.length; i += 1) {
62
+ const token = argv[i] || '';
63
+ if (!token.startsWith('--')) {
64
+ continue;
65
+ }
66
+ const key = token.slice(2);
67
+ const next = argv[i + 1] || '';
68
+ if (!next || next.startsWith('--')) {
69
+ args[key] = true;
70
+ continue;
71
+ }
72
+ args[key] = next;
73
+ i += 1;
74
+ }
75
+ return args;
76
+ }
77
+ /**
78
+ * Ensure POSIX path
79
+ */
80
+ function ensurePosix(p) {
81
+ return String(p || '').replace(/\\/g, '/');
82
+ }
83
+ /**
84
+ * Sanitize task ID
85
+ */
86
+ function toTaskId(input) {
87
+ return String(input || '')
88
+ .trim()
89
+ .replace(/[^a-zA-Z0-9-_]/g, '-')
90
+ .replace(/-+/g, '-')
91
+ .replace(/^-|-$/g, '');
92
+ }
93
+ /**
94
+ * Generate worktree name
95
+ */
96
+ function toWorktreeName(type, taskId) {
97
+ return `harness-${type}-${taskId}`;
98
+ }
99
+ /**
100
+ * Read file if exists
101
+ */
102
+ function readIfExists(filePath) {
103
+ if (!fs.existsSync(filePath)) {
104
+ return '';
105
+ }
106
+ return fs.readFileSync(filePath, 'utf8');
107
+ }
108
+ /**
109
+ * Read JSON if exists
110
+ */
111
+ function readJsonIfExists(filePath) {
112
+ if (!fs.existsSync(filePath)) {
113
+ return null;
114
+ }
115
+ try {
116
+ return JSON.parse(fs.readFileSync(filePath, 'utf8'));
117
+ }
118
+ catch (error) {
119
+ throw new Error(`Invalid JSON: ${ensurePosix(filePath)} (${error instanceof Error ? error.message : 'Unknown error'})`, { cause: error });
120
+ }
121
+ }
122
+ /**
123
+ * Deduplicate array
124
+ */
125
+ function uniqueArray(items) {
126
+ return [...new Set((Array.isArray(items) ? items : []).filter(Boolean).map((item) => ensurePosix(String(item).trim())))];
127
+ }
128
+ /**
129
+ * Normalize boolean
130
+ */
131
+ function normalizeBoolean(value, fallback) {
132
+ if (typeof value === 'boolean') {
133
+ return value;
134
+ }
135
+ if (typeof value === 'string') {
136
+ if (value === 'true') {
137
+ return true;
138
+ }
139
+ if (value === 'false') {
140
+ return false;
141
+ }
142
+ }
143
+ return fallback;
144
+ }
145
+ /**
146
+ * Extract title from proposal
147
+ */
148
+ function extractTitle(changeName, proposalContent) {
149
+ const lines = proposalContent.split(/\r?\n/);
150
+ const heading = lines.find((line) => /^#\s+/.test(line));
151
+ if (!heading) {
152
+ return `Spec 变更:${changeName}`;
153
+ }
154
+ return heading.replace(/^#\s+/, '').trim();
155
+ }
156
+ /**
157
+ * Extract checklist items from tasks.md
158
+ */
159
+ function extractChecklistItems(tasksContent) {
160
+ const lines = tasksContent.split(/\r?\n/);
161
+ const items = [];
162
+ for (const line of lines) {
163
+ const match = line.match(/^\s*[-*]\s+\[(?: |x|X)\]\s+(.+)\s*$/);
164
+ if (match) {
165
+ items.push(match?.[1]?.trim() || '');
166
+ }
167
+ }
168
+ return items;
169
+ }
170
+ /**
171
+ * Extract file candidates from text
172
+ */
173
+ function extractFileCandidates(texts) {
174
+ const merged = texts.filter(Boolean).join('\n');
175
+ const regex = /(?:^|[\s(])((?:server|web|docs|scripts|spec|\.harness|packages)\/[^\s):`'"]+\.[a-zA-Z0-9]+)(?=$|[\s),`'"])/gm;
176
+ const result = [];
177
+ let match = regex.exec(merged);
178
+ while (match) {
179
+ const file = ensurePosix(match?.[1]?.trim() || '');
180
+ if (file && !result.includes(file)) {
181
+ result.push(file);
182
+ }
183
+ match = regex.exec(merged);
184
+ }
185
+ return result;
186
+ }
187
+ /**
188
+ * Infer implementation validations
189
+ */
190
+ function inferImplementationValidations(checklistItems) {
191
+ const source = checklistItems.join('\n').toLowerCase();
192
+ const values = [];
193
+ if (/build|构建/.test(source)) {
194
+ values.push('build-passes');
195
+ }
196
+ if (/test|测试|回归/.test(source)) {
197
+ values.push('tests-pass');
198
+ }
199
+ if (/type|类型/.test(source)) {
200
+ values.push('typecheck-passes');
201
+ }
202
+ if (/lint|格式|规范/.test(source)) {
203
+ values.push('lint-passes');
204
+ }
205
+ if (values.length === 0) {
206
+ values.push('build-passes', 'tests-pass', 'typecheck-passes', 'lint-passes');
207
+ }
208
+ return values;
209
+ }
210
+ /**
211
+ * Infer review validations
212
+ */
213
+ function inferReviewValidations(checklistItems) {
214
+ const source = checklistItems.join('\n').toLowerCase();
215
+ const values = ['security-check', 'review-conclusion'];
216
+ if (/cover|覆盖率/.test(source)) {
217
+ values.splice(1, 0, 'coverage-ge-80');
218
+ }
219
+ return values;
220
+ }
221
+ /**
222
+ * Resolve structured config from change directory
223
+ */
224
+ function resolveStructuredConfig(changeDir, changeName) {
225
+ const manifestPath = path.resolve(changeDir, 'manifest.json');
226
+ const manifest = readJsonIfExists(manifestPath) || {};
227
+ return {
228
+ manifestPath: ensurePosix(path.relative(process.cwd(), manifestPath)),
229
+ manifest,
230
+ executionPath: ensurePosix(manifest.execution || `spec/changes/${changeName}/execution.json`),
231
+ };
232
+ }
@@ -0,0 +1,49 @@
1
+ /**
2
+ * spec/openspec-to-task/types.ts
3
+ * Type definitions for Spec to task sync
4
+ */
5
+ /**
6
+ * Sync options
7
+ */
8
+ export interface SyncOptions {
9
+ cwd?: string;
10
+ change?: string;
11
+ taskId?: string;
12
+ type?: string;
13
+ priority?: string;
14
+ worktree?: string;
15
+ output?: string;
16
+ force?: boolean;
17
+ dryRun?: boolean;
18
+ }
19
+ /**
20
+ * Sync result
21
+ */
22
+ export interface SyncResult {
23
+ success: boolean;
24
+ reason?: string;
25
+ message?: string;
26
+ taskId?: string;
27
+ taskPath?: string;
28
+ json?: string;
29
+ dryRun?: boolean;
30
+ }
31
+ /**
32
+ * Manifest JSON structure
33
+ */
34
+ export interface ManifestJson {
35
+ taskId?: string;
36
+ type?: string;
37
+ priority?: string;
38
+ title?: string;
39
+ files?: string[];
40
+ worktree?: string;
41
+ implementationValidation?: string[];
42
+ reviewValidation?: string[];
43
+ mergeStrategy?: {
44
+ type?: string;
45
+ deleteBranch?: boolean;
46
+ deleteWorktree?: boolean;
47
+ };
48
+ execution?: string;
49
+ }
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ /**
3
+ * spec/openspec-to-task/types.ts
4
+ * Type definitions for Spec to task sync
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,7 @@
1
+ /**
2
+ * sync-openspec-to-task.ts
3
+ * Backward-compatible re-export from openspec-to-task/ module
4
+ * @deprecated Import from '../spec/openspec-to-task/index' directly
5
+ */
6
+ export { syncSpecToTask, main, default } from './openspec-to-task/index';
7
+ export { SyncOptions, SyncResult, ManifestJson } from './openspec-to-task/types';
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ /**
3
+ * sync-openspec-to-task.ts
4
+ * Backward-compatible re-export from openspec-to-task/ module
5
+ * @deprecated Import from '../spec/openspec-to-task/index' directly
6
+ */
7
+ var __importDefault = (this && this.__importDefault) || function (mod) {
8
+ return (mod && mod.__esModule) ? mod : { "default": mod };
9
+ };
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.default = exports.main = exports.syncSpecToTask = void 0;
12
+ var index_1 = require("./openspec-to-task/index");
13
+ Object.defineProperty(exports, "syncSpecToTask", { enumerable: true, get: function () { return index_1.syncSpecToTask; } });
14
+ Object.defineProperty(exports, "main", { enumerable: true, get: function () { return index_1.main; } });
15
+ Object.defineProperty(exports, "default", { enumerable: true, get: function () { return __importDefault(index_1).default; } });
16
+ // Allow direct execution when invoked via spawnSync
17
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
18
+ const { main: runMain } = require('./openspec-to-task/index');
19
+ if (require.main === module) {
20
+ runMain();
21
+ }
@@ -0,0 +1,27 @@
1
+ /**
2
+ * sync-task-to-openspec.ts
3
+ * Sync task execution status back to Spec
4
+ */
5
+ export interface SyncOptions {
6
+ cwd?: string;
7
+ taskId?: string;
8
+ }
9
+ export interface SyncResult {
10
+ skipped: boolean;
11
+ reason?: string;
12
+ taskId?: string;
13
+ change?: string;
14
+ executionPath?: string;
15
+ }
16
+ /**
17
+ * Sync task to Spec
18
+ */
19
+ export declare function syncTaskToSpec(options?: SyncOptions): SyncResult;
20
+ /**
21
+ * Main entry point
22
+ */
23
+ export declare function main(): void;
24
+ declare const _default: {
25
+ syncTaskToSpec: typeof syncTaskToSpec;
26
+ };
27
+ export default _default;