octie-cli 1.0.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.
- package/README.md +523 -0
- package/dist/cli/commands/approve.d.ts +27 -0
- package/dist/cli/commands/approve.d.ts.map +1 -0
- package/dist/cli/commands/approve.js +119 -0
- package/dist/cli/commands/approve.js.map +1 -0
- package/dist/cli/commands/batch.d.ts +15 -0
- package/dist/cli/commands/batch.d.ts.map +1 -0
- package/dist/cli/commands/batch.js +521 -0
- package/dist/cli/commands/batch.js.map +1 -0
- package/dist/cli/commands/create.d.ts +9 -0
- package/dist/cli/commands/create.d.ts.map +1 -0
- package/dist/cli/commands/create.js +321 -0
- package/dist/cli/commands/create.js.map +1 -0
- package/dist/cli/commands/delete.d.ts +9 -0
- package/dist/cli/commands/delete.d.ts.map +1 -0
- package/dist/cli/commands/delete.js +143 -0
- package/dist/cli/commands/delete.js.map +1 -0
- package/dist/cli/commands/export.d.ts +9 -0
- package/dist/cli/commands/export.d.ts.map +1 -0
- package/dist/cli/commands/export.js +66 -0
- package/dist/cli/commands/export.js.map +1 -0
- package/dist/cli/commands/find.d.ts +16 -0
- package/dist/cli/commands/find.d.ts.map +1 -0
- package/dist/cli/commands/find.js +252 -0
- package/dist/cli/commands/find.js.map +1 -0
- package/dist/cli/commands/get.d.ts +9 -0
- package/dist/cli/commands/get.d.ts.map +1 -0
- package/dist/cli/commands/get.js +74 -0
- package/dist/cli/commands/get.js.map +1 -0
- package/dist/cli/commands/graph.d.ts +9 -0
- package/dist/cli/commands/graph.d.ts.map +1 -0
- package/dist/cli/commands/graph.js +200 -0
- package/dist/cli/commands/graph.js.map +1 -0
- package/dist/cli/commands/import.d.ts +9 -0
- package/dist/cli/commands/import.d.ts.map +1 -0
- package/dist/cli/commands/import.js +807 -0
- package/dist/cli/commands/import.js.map +1 -0
- package/dist/cli/commands/init.d.ts +9 -0
- package/dist/cli/commands/init.d.ts.map +1 -0
- package/dist/cli/commands/init.js +57 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/list.d.ts +9 -0
- package/dist/cli/commands/list.d.ts.map +1 -0
- package/dist/cli/commands/list.js +175 -0
- package/dist/cli/commands/list.js.map +1 -0
- package/dist/cli/commands/merge.d.ts +9 -0
- package/dist/cli/commands/merge.d.ts.map +1 -0
- package/dist/cli/commands/merge.js +113 -0
- package/dist/cli/commands/merge.js.map +1 -0
- package/dist/cli/commands/serve.d.ts +9 -0
- package/dist/cli/commands/serve.d.ts.map +1 -0
- package/dist/cli/commands/serve.js +94 -0
- package/dist/cli/commands/serve.js.map +1 -0
- package/dist/cli/commands/update.d.ts +9 -0
- package/dist/cli/commands/update.d.ts.map +1 -0
- package/dist/cli/commands/update.js +423 -0
- package/dist/cli/commands/update.js.map +1 -0
- package/dist/cli/commands/wire.d.ts +15 -0
- package/dist/cli/commands/wire.d.ts.map +1 -0
- package/dist/cli/commands/wire.js +164 -0
- package/dist/cli/commands/wire.js.map +1 -0
- package/dist/cli/index.d.ts +7 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +100 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/output/json.d.ts +16 -0
- package/dist/cli/output/json.d.ts.map +1 -0
- package/dist/cli/output/json.js +29 -0
- package/dist/cli/output/json.js.map +1 -0
- package/dist/cli/output/markdown.d.ts +15 -0
- package/dist/cli/output/markdown.d.ts.map +1 -0
- package/dist/cli/output/markdown.js +206 -0
- package/dist/cli/output/markdown.js.map +1 -0
- package/dist/cli/output/table.d.ts +23 -0
- package/dist/cli/output/table.d.ts.map +1 -0
- package/dist/cli/output/table.js +150 -0
- package/dist/cli/output/table.js.map +1 -0
- package/dist/cli/utils/helpers.d.ts +126 -0
- package/dist/cli/utils/helpers.d.ts.map +1 -0
- package/dist/cli/utils/helpers.js +325 -0
- package/dist/cli/utils/helpers.js.map +1 -0
- package/dist/core/graph/algorithms.d.ts +11 -0
- package/dist/core/graph/algorithms.d.ts.map +1 -0
- package/dist/core/graph/algorithms.js +14 -0
- package/dist/core/graph/algorithms.js.map +1 -0
- package/dist/core/graph/cycle.d.ts +155 -0
- package/dist/core/graph/cycle.d.ts.map +1 -0
- package/dist/core/graph/cycle.js +297 -0
- package/dist/core/graph/cycle.js.map +1 -0
- package/dist/core/graph/index.d.ts +223 -0
- package/dist/core/graph/index.d.ts.map +1 -0
- package/dist/core/graph/index.js +475 -0
- package/dist/core/graph/index.js.map +1 -0
- package/dist/core/graph/operations.d.ts +240 -0
- package/dist/core/graph/operations.d.ts.map +1 -0
- package/dist/core/graph/operations.js +503 -0
- package/dist/core/graph/operations.js.map +1 -0
- package/dist/core/graph/sort.d.ts +76 -0
- package/dist/core/graph/sort.d.ts.map +1 -0
- package/dist/core/graph/sort.js +254 -0
- package/dist/core/graph/sort.js.map +1 -0
- package/dist/core/graph/traversal.d.ts +122 -0
- package/dist/core/graph/traversal.d.ts.map +1 -0
- package/dist/core/graph/traversal.js +336 -0
- package/dist/core/graph/traversal.js.map +1 -0
- package/dist/core/models/task-node.d.ts +328 -0
- package/dist/core/models/task-node.d.ts.map +1 -0
- package/dist/core/models/task-node.js +1090 -0
- package/dist/core/models/task-node.js.map +1 -0
- package/dist/core/registry/index.d.ts +102 -0
- package/dist/core/registry/index.d.ts.map +1 -0
- package/dist/core/registry/index.js +249 -0
- package/dist/core/registry/index.js.map +1 -0
- package/dist/core/registry/root-guard.d.ts +19 -0
- package/dist/core/registry/root-guard.d.ts.map +1 -0
- package/dist/core/registry/root-guard.js +28 -0
- package/dist/core/registry/root-guard.js.map +1 -0
- package/dist/core/storage/atomic-write.d.ts +181 -0
- package/dist/core/storage/atomic-write.d.ts.map +1 -0
- package/dist/core/storage/atomic-write.js +379 -0
- package/dist/core/storage/atomic-write.js.map +1 -0
- package/dist/core/storage/file-store.d.ts +148 -0
- package/dist/core/storage/file-store.d.ts.map +1 -0
- package/dist/core/storage/file-store.js +423 -0
- package/dist/core/storage/file-store.js.map +1 -0
- package/dist/core/storage/indexer.d.ts +138 -0
- package/dist/core/storage/indexer.d.ts.map +1 -0
- package/dist/core/storage/indexer.js +350 -0
- package/dist/core/storage/indexer.js.map +1 -0
- package/dist/core/utils/status-helpers.d.ts +59 -0
- package/dist/core/utils/status-helpers.d.ts.map +1 -0
- package/dist/core/utils/status-helpers.js +149 -0
- package/dist/core/utils/status-helpers.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/types/index.d.ts +504 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +182 -0
- package/dist/types/index.js.map +1 -0
- package/dist/web/routes/graph.d.ts +17 -0
- package/dist/web/routes/graph.d.ts.map +1 -0
- package/dist/web/routes/graph.js +277 -0
- package/dist/web/routes/graph.js.map +1 -0
- package/dist/web/routes/projects.d.ts +14 -0
- package/dist/web/routes/projects.d.ts.map +1 -0
- package/dist/web/routes/projects.js +102 -0
- package/dist/web/routes/projects.js.map +1 -0
- package/dist/web/routes/tasks.d.ts +17 -0
- package/dist/web/routes/tasks.d.ts.map +1 -0
- package/dist/web/routes/tasks.js +538 -0
- package/dist/web/routes/tasks.js.map +1 -0
- package/dist/web/server.d.ts +121 -0
- package/dist/web/server.d.ts.map +1 -0
- package/dist/web/server.js +389 -0
- package/dist/web/server.js.map +1 -0
- package/dist/web-ui/assets/index-BB0qvF1y.css +1 -0
- package/dist/web-ui/assets/index-Vmm72oKY.js +34 -0
- package/dist/web-ui/index.html +14 -0
- package/dist/web-ui/vite.svg +1 -0
- package/package.json +94 -0
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Create command - Create a new task with atomic task validation
|
|
3
|
+
*/
|
|
4
|
+
import { Command, Option } from 'commander';
|
|
5
|
+
import { v4 as uuidv4 } from 'uuid';
|
|
6
|
+
import { TaskNode } from '../../core/models/task-node.js';
|
|
7
|
+
import { getProjectPath, loadGraph, saveGraph, success, error, info, parseList } from '../utils/helpers.js';
|
|
8
|
+
import { AtomicTaskViolationError } from '../../types/index.js';
|
|
9
|
+
import chalk from 'chalk';
|
|
10
|
+
import { readFileSync, existsSync } from 'node:fs';
|
|
11
|
+
import { resolve } from 'node:path';
|
|
12
|
+
/**
|
|
13
|
+
* Display atomic task policy help
|
|
14
|
+
*/
|
|
15
|
+
function displayAtomicTaskPolicy() {
|
|
16
|
+
console.log('');
|
|
17
|
+
console.log(chalk.red.bold('⚠️ ATOMIC TASK POLICY ⚠️'));
|
|
18
|
+
console.log('');
|
|
19
|
+
console.log(chalk.yellow('Tasks MUST be atomic - small, specific, executable, and verifiable.'));
|
|
20
|
+
console.log('');
|
|
21
|
+
console.log(chalk.bold('What is an Atomic Task?'));
|
|
22
|
+
console.log(' • Single purpose: Does ONE thing well');
|
|
23
|
+
console.log(' • Executable: Can be completed in 2-8 hours (typical) or 1-2 days (max)');
|
|
24
|
+
console.log(' • Verifiable: Has quantitative success criteria');
|
|
25
|
+
console.log(' • Independent: Minimizes dependencies on other tasks');
|
|
26
|
+
console.log('');
|
|
27
|
+
console.log(chalk.red.bold('❌ BAD Examples (too vague or too large):'));
|
|
28
|
+
console.log(chalk.gray(' • "Fix authentication" (too vague - what specifically?)'));
|
|
29
|
+
console.log(chalk.gray(' • "Build auth system" (too large - split into: login, signup, password reset, etc.)'));
|
|
30
|
+
console.log(chalk.gray(' • "Improve performance" (not measurable - what metric?)'));
|
|
31
|
+
console.log(chalk.gray(' • "Code review" (not atomic - which files? what criteria?)'));
|
|
32
|
+
console.log('');
|
|
33
|
+
console.log(chalk.green.bold('✅ GOOD Examples (atomic):'));
|
|
34
|
+
console.log(chalk.gray(' • "Implement login endpoint with JWT" (specific, testable)'));
|
|
35
|
+
console.log(chalk.gray(' • "Add bcrypt password hashing with 10 rounds" (clear, verifiable)'));
|
|
36
|
+
console.log(chalk.gray(' • "Write unit tests for User model" (specific scope)'));
|
|
37
|
+
console.log(chalk.gray(' • "Fix NPE in AuthService.login method" (atomic bug fix)'));
|
|
38
|
+
console.log('');
|
|
39
|
+
console.log(chalk.bold('Validation Rules:'));
|
|
40
|
+
console.log(' • Title: 1-200 chars, must contain action verb');
|
|
41
|
+
console.log(' • Description: 50-10000 chars, must be specific');
|
|
42
|
+
console.log(' • Success Criteria: 1-10 items, must be quantitative');
|
|
43
|
+
console.log(' • Deliverables: 1-5 items, must be specific outputs');
|
|
44
|
+
console.log('');
|
|
45
|
+
console.log(chalk.yellow('If your task is rejected as non-atomic:'));
|
|
46
|
+
console.log(' → Split it into smaller, focused tasks');
|
|
47
|
+
console.log(' → Be more specific about what will be done');
|
|
48
|
+
console.log(' → Define measurable success criteria');
|
|
49
|
+
console.log(' → Limit scope to 2-8 hours of work');
|
|
50
|
+
console.log('');
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Create the create command
|
|
54
|
+
*/
|
|
55
|
+
export const createCommand = new Command('create')
|
|
56
|
+
.description('Create a new atomic task in the project')
|
|
57
|
+
.addOption(new Option('--title <string>', 'Task title (max 200 chars). Must contain action verb')
|
|
58
|
+
.env('OCTIE_TASK_TITLE')
|
|
59
|
+
.makeOptionMandatory(true))
|
|
60
|
+
.addOption(new Option('--description <string>', 'Detailed task description (min 50 chars, max 10000)')
|
|
61
|
+
.env('OCTIE_TASK_DESCRIPTION')
|
|
62
|
+
.makeOptionMandatory(true))
|
|
63
|
+
.addOption(new Option('--success-criterion <text>', 'Quantitative success criterion (can be specified multiple times)')
|
|
64
|
+
.argParser((value, previous) => [...(previous || []), value])
|
|
65
|
+
.env('OCTIE_SUCCESS_CRITERION')
|
|
66
|
+
.makeOptionMandatory(true))
|
|
67
|
+
.addOption(new Option('--deliverable <text>', 'Specific output expected (can be specified multiple times)')
|
|
68
|
+
.argParser((value, previous) => [...(previous || []), value])
|
|
69
|
+
.env('OCTIE_DELIVERABLE')
|
|
70
|
+
.makeOptionMandatory(true))
|
|
71
|
+
.option('-p, --priority <level>', 'Task priority: top | second | later', 'second')
|
|
72
|
+
.option('-b, --blockers <ids>', 'Comma-separated task IDs that block this task (creates graph edges for execution order)')
|
|
73
|
+
.option('-d, --dependencies <text>', 'Explanatory text: WHY this task depends on its blockers (required if --blockers is set)')
|
|
74
|
+
.addOption(new Option('-f, --related-files <paths>', 'File paths relevant to task (can be specified multiple times or comma-separated)')
|
|
75
|
+
.argParser((value, previous) => {
|
|
76
|
+
// Support both comma-separated and multiple flag usage
|
|
77
|
+
const items = value.includes(',') ? value.split(',').map(s => s.trim()) : [value.trim()];
|
|
78
|
+
return [...(previous || []), ...items.filter(Boolean)];
|
|
79
|
+
}))
|
|
80
|
+
.addOption(new Option('-c, --c7-verified <library:notes>', 'C7 library verification (format: library-id or library-id:notes, can be specified multiple times)')
|
|
81
|
+
.argParser((value, previous) => [...(previous || []), value]))
|
|
82
|
+
.addOption(new Option('-n, --notes <text>', 'Additional context or comments (can be specified multiple times)')
|
|
83
|
+
.argParser((value, previous) => [...(previous || []), value]))
|
|
84
|
+
.option('--notes-file <path>', 'Read notes from file (multi-line notes support)')
|
|
85
|
+
.option('-i, --interactive', 'Interactive mode with prompts')
|
|
86
|
+
.option('--project <path>', 'Path to Octie project directory')
|
|
87
|
+
.action(async (options, command) => {
|
|
88
|
+
try {
|
|
89
|
+
// Display atomic task policy on --help
|
|
90
|
+
if (process.argv.includes('--help') || process.argv.includes('-h')) {
|
|
91
|
+
displayAtomicTaskPolicy();
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
// Get global options (from parent) and merge with local options
|
|
95
|
+
const globalOpts = command.parent?.opts() || {};
|
|
96
|
+
const projectPath = await getProjectPath(options.project || globalOpts.project);
|
|
97
|
+
const graph = await loadGraph(projectPath);
|
|
98
|
+
// Parse multi-value options (argParser returns arrays)
|
|
99
|
+
const successCriteria = options.successCriterion || [];
|
|
100
|
+
const deliverables = options.deliverable || [];
|
|
101
|
+
// Validate priority - must be one of: top, second, later
|
|
102
|
+
const VALID_PRIORITIES = ['top', 'second', 'later'];
|
|
103
|
+
const priority = options.priority?.toLowerCase();
|
|
104
|
+
if (!VALID_PRIORITIES.includes(priority)) {
|
|
105
|
+
console.error(`Error: Invalid priority "${options.priority}". Must be one of: ${VALID_PRIORITIES.join(', ')}`);
|
|
106
|
+
process.exit(1);
|
|
107
|
+
}
|
|
108
|
+
// Parse C7 verifications (format: library-id or library-id:notes)
|
|
109
|
+
const c7Verifications = (options.c7Verified || []).map((entry) => {
|
|
110
|
+
// Handle Windows Git Bash path conversion: "/path" becomes "C:/Program Files/Git/path"
|
|
111
|
+
// Detect and strip the Git Bash prefix
|
|
112
|
+
let cleanEntry = entry;
|
|
113
|
+
const gitBashPrefix = /^[A-Za-z]:\/(\/)?Program Files\/Git\//;
|
|
114
|
+
if (gitBashPrefix.test(entry)) {
|
|
115
|
+
// Extract the original Unix path after "Program Files/Git/"
|
|
116
|
+
const match = entry.match(/Program Files\/Git\/(.*)$/);
|
|
117
|
+
if (match) {
|
|
118
|
+
cleanEntry = '/' + match[1];
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
// Now parse the library-id:notes format
|
|
122
|
+
const colonIndex = cleanEntry.indexOf(':');
|
|
123
|
+
if (colonIndex === -1) {
|
|
124
|
+
return {
|
|
125
|
+
library_id: cleanEntry.trim(),
|
|
126
|
+
verified_at: new Date().toISOString(),
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
return {
|
|
130
|
+
library_id: cleanEntry.substring(0, colonIndex).trim(),
|
|
131
|
+
verified_at: new Date().toISOString(),
|
|
132
|
+
notes: cleanEntry.substring(colonIndex + 1).trim(),
|
|
133
|
+
};
|
|
134
|
+
});
|
|
135
|
+
// Validate required fields
|
|
136
|
+
if (!options.title || options.title.trim().length === 0) {
|
|
137
|
+
error('Title is required and cannot be empty');
|
|
138
|
+
process.exit(1);
|
|
139
|
+
}
|
|
140
|
+
if (!options.description || options.description.trim().length === 0) {
|
|
141
|
+
error('Description is required and cannot be empty');
|
|
142
|
+
process.exit(1);
|
|
143
|
+
}
|
|
144
|
+
if (successCriteria.length === 0) {
|
|
145
|
+
error('At least one success criterion is required (--success-criterion)');
|
|
146
|
+
process.exit(1);
|
|
147
|
+
}
|
|
148
|
+
if (deliverables.length === 0) {
|
|
149
|
+
error('At least one deliverable is required (--deliverable)');
|
|
150
|
+
process.exit(1);
|
|
151
|
+
}
|
|
152
|
+
// Twin validation: blockers and dependencies must be provided together
|
|
153
|
+
const blockers = parseList(options.blockers || '');
|
|
154
|
+
const dependenciesText = (options.dependencies || '').trim();
|
|
155
|
+
if (blockers.length > 0 && !dependenciesText) {
|
|
156
|
+
error('When --blockers is provided, --dependencies explanation text is also required.');
|
|
157
|
+
info('The twin feature requires both blockers (task IDs) and dependencies (explanation).');
|
|
158
|
+
info('Example: --blockers abc123 --dependencies "Needs the API spec from abc123"');
|
|
159
|
+
process.exit(1);
|
|
160
|
+
}
|
|
161
|
+
if (dependenciesText && blockers.length === 0) {
|
|
162
|
+
error('When --dependencies is provided, --blockers task IDs are also required.');
|
|
163
|
+
info('The twin feature requires both blockers (task IDs) and dependencies (explanation).');
|
|
164
|
+
info('Example: --blockers abc123 --dependencies "Needs the API spec from abc123"');
|
|
165
|
+
process.exit(1);
|
|
166
|
+
}
|
|
167
|
+
// Handle notes: support both --notes (multiple) and --notes-file
|
|
168
|
+
let notes = [];
|
|
169
|
+
if (options.notesFile) {
|
|
170
|
+
// Read notes from file
|
|
171
|
+
const notesPath = resolve(options.notesFile);
|
|
172
|
+
if (!existsSync(notesPath)) {
|
|
173
|
+
error(`Notes file not found: ${notesPath}`);
|
|
174
|
+
process.exit(1);
|
|
175
|
+
}
|
|
176
|
+
try {
|
|
177
|
+
const fileContent = readFileSync(notesPath, 'utf-8').trim();
|
|
178
|
+
if (fileContent) {
|
|
179
|
+
notes.push(fileContent);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
catch (err) {
|
|
183
|
+
error(`Failed to read notes file: ${err instanceof Error ? err.message : 'Unknown error'}`);
|
|
184
|
+
process.exit(1);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
if (options.notes && Array.isArray(options.notes)) {
|
|
188
|
+
// Append all inline notes after file content
|
|
189
|
+
notes = notes.concat(options.notes.map((n) => n.trim()).filter(Boolean));
|
|
190
|
+
}
|
|
191
|
+
const notesText = notes.join('\n\n');
|
|
192
|
+
// Build task data
|
|
193
|
+
// Use graph.generateUniqueId() to ensure first 7 characters are unique
|
|
194
|
+
const taskId = graph.generateUniqueId();
|
|
195
|
+
const taskData = {
|
|
196
|
+
id: taskId,
|
|
197
|
+
title: options.title.trim(),
|
|
198
|
+
description: options.description.trim(),
|
|
199
|
+
// Status is now derived by TaskNode constructor (defaults to 'ready' if no blockers)
|
|
200
|
+
priority: priority,
|
|
201
|
+
success_criteria: successCriteria.map((text) => ({
|
|
202
|
+
id: uuidv4(),
|
|
203
|
+
text: text.trim(),
|
|
204
|
+
completed: false,
|
|
205
|
+
})),
|
|
206
|
+
deliverables: deliverables.map((text) => ({
|
|
207
|
+
id: uuidv4(),
|
|
208
|
+
text: text.trim(),
|
|
209
|
+
completed: false,
|
|
210
|
+
})),
|
|
211
|
+
blockers: parseList(options.blockers || ''),
|
|
212
|
+
dependencies: dependenciesText,
|
|
213
|
+
related_files: options.relatedFiles || [],
|
|
214
|
+
notes: notesText,
|
|
215
|
+
c7_verified: c7Verifications,
|
|
216
|
+
sub_items: [],
|
|
217
|
+
edges: [],
|
|
218
|
+
};
|
|
219
|
+
// Create task (includes atomic validation)
|
|
220
|
+
let task;
|
|
221
|
+
try {
|
|
222
|
+
task = new TaskNode(taskData);
|
|
223
|
+
}
|
|
224
|
+
catch (err) {
|
|
225
|
+
if (err instanceof Error) {
|
|
226
|
+
error(err.message);
|
|
227
|
+
// Show specific rejection reasons for atomic task violations
|
|
228
|
+
if (err instanceof AtomicTaskViolationError && err.violations.length > 0) {
|
|
229
|
+
console.log('');
|
|
230
|
+
console.log(chalk.yellow.bold('Specific issues found:'));
|
|
231
|
+
for (const violation of err.violations) {
|
|
232
|
+
console.log(chalk.red(' ✗ ') + violation);
|
|
233
|
+
}
|
|
234
|
+
console.log('');
|
|
235
|
+
info('See atomic task policy below for guidance');
|
|
236
|
+
displayAtomicTaskPolicy();
|
|
237
|
+
}
|
|
238
|
+
else if (err.message.includes('atomic') || err.message.includes('vague')) {
|
|
239
|
+
console.log('');
|
|
240
|
+
info('See atomic task policy above for guidance');
|
|
241
|
+
displayAtomicTaskPolicy();
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
else {
|
|
245
|
+
error('Failed to create task');
|
|
246
|
+
}
|
|
247
|
+
process.exit(1);
|
|
248
|
+
}
|
|
249
|
+
// Validate blockers exist and resolve short UUIDs to full UUIDs
|
|
250
|
+
const resolvedBlockers = [];
|
|
251
|
+
const invalidBlockers = [];
|
|
252
|
+
for (const blockerId of task.blockers) {
|
|
253
|
+
const resolvedTask = graph.getNodeByIdOrPrefix(blockerId);
|
|
254
|
+
if (resolvedTask) {
|
|
255
|
+
resolvedBlockers.push(resolvedTask.id);
|
|
256
|
+
}
|
|
257
|
+
else {
|
|
258
|
+
invalidBlockers.push(blockerId);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
if (invalidBlockers.length > 0) {
|
|
262
|
+
error(`Blocker task IDs not found: ${invalidBlockers.join(', ')}`);
|
|
263
|
+
process.exit(1);
|
|
264
|
+
}
|
|
265
|
+
// Update task blockers with resolved full UUIDs
|
|
266
|
+
task.blockers = resolvedBlockers;
|
|
267
|
+
// Add to graph
|
|
268
|
+
graph.addNode(task);
|
|
269
|
+
// Create edges from blockers to this task
|
|
270
|
+
for (const blockerId of task.blockers) {
|
|
271
|
+
graph.addEdge(blockerId, taskId);
|
|
272
|
+
}
|
|
273
|
+
// Save
|
|
274
|
+
await saveGraph(projectPath, graph);
|
|
275
|
+
// Success
|
|
276
|
+
success(`Task created: ${chalk.cyan(taskId)}`);
|
|
277
|
+
info(`Title: ${task.title}`);
|
|
278
|
+
info(`Priority: ${chalk.yellow(task.priority)}`);
|
|
279
|
+
if (task.blockers.length > 0) {
|
|
280
|
+
info(`Blocked by: ${task.blockers.map(id => chalk.cyan(id)).join(', ')}`);
|
|
281
|
+
if (task.dependencies) {
|
|
282
|
+
info(`Dependencies: ${task.dependencies}`);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
console.log('');
|
|
286
|
+
console.log(chalk.gray('View task:'), chalk.gray(`octie get ${taskId}`));
|
|
287
|
+
process.exit(0);
|
|
288
|
+
}
|
|
289
|
+
catch (err) {
|
|
290
|
+
if (err instanceof Error) {
|
|
291
|
+
error(err.message);
|
|
292
|
+
}
|
|
293
|
+
else {
|
|
294
|
+
error('Failed to create task');
|
|
295
|
+
}
|
|
296
|
+
process.exit(1);
|
|
297
|
+
}
|
|
298
|
+
});
|
|
299
|
+
// Add help text to display atomic task policy when --help is shown
|
|
300
|
+
createCommand.on('--help', () => {
|
|
301
|
+
displayAtomicTaskPolicy();
|
|
302
|
+
console.log('');
|
|
303
|
+
console.log(chalk.bold('Blockers & Dependencies (Twin Feature):'));
|
|
304
|
+
console.log(chalk.cyan(' --blockers (-b)') + ': Comma-separated task IDs that block this task.');
|
|
305
|
+
console.log(' Creates GRAPH EDGES affecting execution order.');
|
|
306
|
+
console.log(' Task A blocks Task B → A must complete before B starts.');
|
|
307
|
+
console.log('');
|
|
308
|
+
console.log(chalk.cyan(' --dependencies (-d)') + ': Explanatory text WHY this task depends on its blockers.');
|
|
309
|
+
console.log(' REQUIRED when --blockers is set (twin validation).');
|
|
310
|
+
console.log(' Does NOT affect execution order - pure metadata.');
|
|
311
|
+
console.log('');
|
|
312
|
+
console.log(chalk.yellow(' Example (both required together):'));
|
|
313
|
+
console.log(' octie create --title "Build Frontend" \\');
|
|
314
|
+
console.log(' --blockers abc123,def456 \\');
|
|
315
|
+
console.log(' --dependencies "Needs API spec from abc123 and auth from def456"');
|
|
316
|
+
console.log('');
|
|
317
|
+
console.log(chalk.red(' Error if only one provided:'));
|
|
318
|
+
console.log(' --blockers without --dependencies → Error: twin required');
|
|
319
|
+
console.log(' --dependencies without --blockers → Error: twin required');
|
|
320
|
+
});
|
|
321
|
+
//# sourceMappingURL=create.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create.js","sourceRoot":"","sources":["../../../src/cli/commands/create.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"delete.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/delete.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKpC;;GAEG;AACH,eAAO,MAAM,aAAa,SA8ItB,CAAC"}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Delete command - Delete a task from the graph
|
|
3
|
+
*/
|
|
4
|
+
import { Command } from 'commander';
|
|
5
|
+
import { getProjectPath, loadGraph, saveGraph, success, error, info, warning, confirmPrompt } from '../utils/helpers.js';
|
|
6
|
+
import chalk from 'chalk';
|
|
7
|
+
import { cutNode, cascadeDelete } from '../../core/graph/operations.js';
|
|
8
|
+
/**
|
|
9
|
+
* Create the delete command
|
|
10
|
+
*/
|
|
11
|
+
export const deleteCommand = new Command('delete')
|
|
12
|
+
.description('Delete a task from the project')
|
|
13
|
+
.argument('<id>', 'Task ID to delete (full UUID or first 7-8 characters)')
|
|
14
|
+
.option('--reconnect', 'Reconnect edges after deletion (A→B→C → A→C)')
|
|
15
|
+
.option('--cascade', 'Delete all dependent tasks (tasks that this task blocks)')
|
|
16
|
+
.option('--force', 'Skip confirmation prompt')
|
|
17
|
+
.addHelpText('after', `
|
|
18
|
+
Deletion Modes:
|
|
19
|
+
|
|
20
|
+
Default (simple delete):
|
|
21
|
+
Removes the task and its edges.
|
|
22
|
+
Dependent tasks have this task removed from their blockers.
|
|
23
|
+
Status of dependent tasks is recalculated.
|
|
24
|
+
|
|
25
|
+
--reconnect (splice into chain):
|
|
26
|
+
Before: A → B → C (A blocks B, B blocks C)
|
|
27
|
+
After: A → C (A blocks C directly)
|
|
28
|
+
Useful when removing an intermediate task in a chain.
|
|
29
|
+
|
|
30
|
+
--cascade (delete dependents):
|
|
31
|
+
Deletes this task AND all tasks that depend on it.
|
|
32
|
+
Warning: Can delete many tasks at once!
|
|
33
|
+
|
|
34
|
+
Task ID:
|
|
35
|
+
Supports full UUID or first 7-8 characters (short UUID).
|
|
36
|
+
|
|
37
|
+
Confirmation:
|
|
38
|
+
Prompts for confirmation unless --force is used.
|
|
39
|
+
Shows impact (how many tasks are affected) before deletion.
|
|
40
|
+
|
|
41
|
+
Examples:
|
|
42
|
+
$ octie delete abc12345 Delete task with confirmation
|
|
43
|
+
$ octie delete abc12345 --force Delete without confirmation
|
|
44
|
+
$ octie delete abc12345 --reconnect Reconnect chain after deletion
|
|
45
|
+
$ octie delete abc12345 --cascade Delete task and all dependents
|
|
46
|
+
`)
|
|
47
|
+
.action(async (id, options, command) => {
|
|
48
|
+
try {
|
|
49
|
+
// Get global options
|
|
50
|
+
const globalOpts = command.parent?.opts() || {};
|
|
51
|
+
const projectPath = await getProjectPath(globalOpts.project);
|
|
52
|
+
const graph = await loadGraph(projectPath);
|
|
53
|
+
// Support short UUID prefix lookup
|
|
54
|
+
const task = graph.getNodeByIdOrPrefix(id);
|
|
55
|
+
if (!task) {
|
|
56
|
+
error(`Task not found: ${id}`);
|
|
57
|
+
process.exit(1);
|
|
58
|
+
}
|
|
59
|
+
// Use the full ID for all subsequent operations
|
|
60
|
+
const fullId = task.id;
|
|
61
|
+
// Show impact
|
|
62
|
+
const dependents = graph.getOutgoingEdges(fullId);
|
|
63
|
+
const blockers = graph.getIncomingEdges(fullId);
|
|
64
|
+
console.log('');
|
|
65
|
+
console.log(chalk.bold('Task to delete:'));
|
|
66
|
+
console.log(` ${chalk.cyan(fullId.substring(0, 8))} - ${task.title}`);
|
|
67
|
+
console.log('');
|
|
68
|
+
if (dependents.length > 0) {
|
|
69
|
+
warning(`This task is blocking ${dependents.length} other task(s):`);
|
|
70
|
+
for (const depId of dependents) {
|
|
71
|
+
const depTask = graph.getNode(depId);
|
|
72
|
+
if (depTask) {
|
|
73
|
+
console.log(` - ${chalk.cyan(depId.substring(0, 8))} - ${depTask.title}`);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
console.log('');
|
|
77
|
+
}
|
|
78
|
+
if (blockers.length > 0) {
|
|
79
|
+
info(`This task is blocked by ${blockers.length} task(s):`);
|
|
80
|
+
for (const blockerId of blockers) {
|
|
81
|
+
const blockerTask = graph.getNode(blockerId);
|
|
82
|
+
if (blockerTask) {
|
|
83
|
+
console.log(` - ${chalk.cyan(blockerId.substring(0, 8))} - ${blockerTask.title}`);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
console.log('');
|
|
87
|
+
}
|
|
88
|
+
// Confirm deletion
|
|
89
|
+
if (!options.force) {
|
|
90
|
+
console.log(chalk.gray('(Use --force to skip confirmation)'));
|
|
91
|
+
const confirmed = await confirmPrompt(chalk.yellow('Delete this task? (y/N)'));
|
|
92
|
+
if (!confirmed) {
|
|
93
|
+
info('Deletion cancelled');
|
|
94
|
+
process.exit(0);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
// Create backup before deletion
|
|
98
|
+
warning('Creating backup before deletion...');
|
|
99
|
+
// Backup is automatic on save
|
|
100
|
+
// Perform deletion
|
|
101
|
+
if (options.reconnect) {
|
|
102
|
+
info('Reconnecting edges...');
|
|
103
|
+
cutNode(graph, fullId);
|
|
104
|
+
}
|
|
105
|
+
else if (options.cascade) {
|
|
106
|
+
info('Cascading deletion to dependents...');
|
|
107
|
+
const deletedIds = cascadeDelete(graph, fullId);
|
|
108
|
+
// Save
|
|
109
|
+
await saveGraph(projectPath, graph);
|
|
110
|
+
success(`Deleted ${deletedIds.length} task(s): ${deletedIds.map(id => id.substring(0, 8)).join(', ')}`);
|
|
111
|
+
process.exit(0);
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
// Simple removal - clean up blocker references from dependent tasks
|
|
115
|
+
// Get tasks that this task is blocking (outgoing edges)
|
|
116
|
+
const dependentTasks = graph.getOutgoingEdges(fullId);
|
|
117
|
+
for (const depId of dependentTasks) {
|
|
118
|
+
const depTask = graph.getNode(depId);
|
|
119
|
+
if (depTask && depTask.blockers.includes(fullId)) {
|
|
120
|
+
depTask.removeBlocker(fullId);
|
|
121
|
+
// Recalculate status since blocker was removed
|
|
122
|
+
depTask.recalculateStatus();
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
// Remove the node (this also removes graph edges)
|
|
126
|
+
graph.removeNode(fullId);
|
|
127
|
+
}
|
|
128
|
+
// Save
|
|
129
|
+
await saveGraph(projectPath, graph);
|
|
130
|
+
success(`Task deleted: ${chalk.cyan(fullId.substring(0, 8))}`);
|
|
131
|
+
process.exit(0);
|
|
132
|
+
}
|
|
133
|
+
catch (err) {
|
|
134
|
+
if (err instanceof Error) {
|
|
135
|
+
error(err.message);
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
error('Failed to delete task');
|
|
139
|
+
}
|
|
140
|
+
process.exit(1);
|
|
141
|
+
}
|
|
142
|
+
});
|
|
143
|
+
//# sourceMappingURL=delete.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"delete.js","sourceRoot":"","sources":["../../../src/cli/commands/delete.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"export.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/export.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAQpC;;GAEG;AACH,eAAO,MAAM,aAAa,SAwDtB,CAAC"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Export command - Export project data
|
|
3
|
+
*/
|
|
4
|
+
import { Command } from 'commander';
|
|
5
|
+
import { getProjectPath, loadGraph, success, error } from '../utils/helpers.js';
|
|
6
|
+
import { formatProjectMarkdown } from '../output/markdown.js';
|
|
7
|
+
import { formatProjectJSON } from '../output/json.js';
|
|
8
|
+
import chalk from 'chalk';
|
|
9
|
+
import { writeFileSync, mkdirSync } from 'node:fs';
|
|
10
|
+
import { dirname } from 'node:path';
|
|
11
|
+
/**
|
|
12
|
+
* Create the export command
|
|
13
|
+
*/
|
|
14
|
+
export const exportCommand = new Command('export')
|
|
15
|
+
.description('Export project data to file')
|
|
16
|
+
.option('-t, --type <format>', 'Export format: json, md (default: "json")')
|
|
17
|
+
.option('-o, --output <path>', 'Output file path')
|
|
18
|
+
.addHelpText('after', `
|
|
19
|
+
Examples:
|
|
20
|
+
$ octie export -o backup.json
|
|
21
|
+
$ octie export --type md -o tasks.md
|
|
22
|
+
|
|
23
|
+
Default: Writes to tasks.json (or tasks.md) if no -o specified
|
|
24
|
+
`)
|
|
25
|
+
.action(async (options, command) => {
|
|
26
|
+
try {
|
|
27
|
+
// Get global options
|
|
28
|
+
const globalOpts = command.parent?.opts() || {};
|
|
29
|
+
const projectPath = await getProjectPath(globalOpts.project);
|
|
30
|
+
const graph = await loadGraph(projectPath);
|
|
31
|
+
let output;
|
|
32
|
+
let defaultFileName;
|
|
33
|
+
switch (options.type) {
|
|
34
|
+
case 'md':
|
|
35
|
+
output = formatProjectMarkdown(graph);
|
|
36
|
+
defaultFileName = 'tasks.md';
|
|
37
|
+
break;
|
|
38
|
+
default:
|
|
39
|
+
output = formatProjectJSON(graph);
|
|
40
|
+
defaultFileName = 'tasks.json';
|
|
41
|
+
break;
|
|
42
|
+
}
|
|
43
|
+
// Write to file
|
|
44
|
+
const outputPath = options.output || defaultFileName;
|
|
45
|
+
// Create parent directory if it doesn't exist
|
|
46
|
+
try {
|
|
47
|
+
mkdirSync(dirname(outputPath), { recursive: true });
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
// Ignore error if directory already exists
|
|
51
|
+
}
|
|
52
|
+
writeFileSync(outputPath, output, 'utf-8');
|
|
53
|
+
success(`Exported to ${chalk.cyan(outputPath)}`);
|
|
54
|
+
process.exit(0);
|
|
55
|
+
}
|
|
56
|
+
catch (err) {
|
|
57
|
+
if (err instanceof Error) {
|
|
58
|
+
error(err.message);
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
error('Export failed');
|
|
62
|
+
}
|
|
63
|
+
process.exit(1);
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
//# sourceMappingURL=export.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"export.js","sourceRoot":"","sources":["../../../src/cli/commands/export.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAChF,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC;;GAEG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,IAAI,OAAO,CAAC,QAAQ,CAAC;KAC/C,WAAW,CAAC,6BAA6B,CAAC;KAC1C,MAAM,CAAC,qBAAqB,EAAE,2CAA2C,CAAC;KAC1E,MAAM,CAAC,qBAAqB,EAAE,kBAAkB,CAAC;KACjD,WAAW,CAAC,OAAO,EAAE;;;;;;CAMvB,CAAC;KACC,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE;IACjC,IAAI,CAAC;QACH,qBAAqB;QACrB,MAAM,UAAU,GAAG,OAAO,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;QAChD,MAAM,WAAW,GAAG,MAAM,cAAc,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;QAC7D,MAAM,KAAK,GAAG,MAAM,SAAS,CAAC,WAAW,CAAC,CAAC;QAE3C,IAAI,MAAc,CAAC;QACnB,IAAI,eAAuB,CAAC;QAE5B,QAAQ,OAAO,CAAC,IAAI,EAAE,CAAC;YACrB,KAAK,IAAI;gBACP,MAAM,GAAG,qBAAqB,CAAC,KAAK,CAAC,CAAC;gBACtC,eAAe,GAAG,UAAU,CAAC;gBAC7B,MAAM;YAER;gBACE,MAAM,GAAG,iBAAiB,CAAC,KAAK,CAAC,CAAC;gBAClC,eAAe,GAAG,YAAY,CAAC;gBAC/B,MAAM;QACV,CAAC;QAED,gBAAgB;QAChB,MAAM,UAAU,GAAG,OAAO,CAAC,MAAM,IAAI,eAAe,CAAC;QAErD,8CAA8C;QAC9C,IAAI,CAAC;YACH,SAAS,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACtD,CAAC;QAAC,MAAM,CAAC;YACP,2CAA2C;QAC7C,CAAC;QAED,aAAa,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;QAE3C,OAAO,CAAC,eAAe,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;QAEjD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,GAAG,YAAY,KAAK,EAAE,CAAC;YACzB,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACrB,CAAC;aAAM,CAAC;YACN,KAAK,CAAC,eAAe,CAAC,CAAC;QACzB,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Find command - Search and filter tasks with advanced options
|
|
3
|
+
*
|
|
4
|
+
* Provides powerful search capabilities:
|
|
5
|
+
* - Title substring matching
|
|
6
|
+
* - Full-text search across description, notes, criteria, deliverables
|
|
7
|
+
* - File reference search
|
|
8
|
+
* - C7 verification library search
|
|
9
|
+
* - Special filters: without-blockers, orphans, leaves
|
|
10
|
+
*/
|
|
11
|
+
import { Command } from 'commander';
|
|
12
|
+
/**
|
|
13
|
+
* Create the find command
|
|
14
|
+
*/
|
|
15
|
+
export declare const findCommand: Command;
|
|
16
|
+
//# sourceMappingURL=find.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"find.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/find.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAiPpC;;GAEG;AACH,eAAO,MAAM,WAAW,SAmDpB,CAAC"}
|