@mandors/cli 0.0.1
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/.npmrc.example +18 -0
- package/.pre-commit-config.yaml +22 -0
- package/README.md +317 -0
- package/logo.png +0 -0
- package/npm/bin/mandor +32 -0
- package/npm/lib/api.js +216 -0
- package/npm/lib/config.js +153 -0
- package/npm/lib/download.js +83 -0
- package/npm/lib/index.js +138 -0
- package/npm/lib/install.js +92 -0
- package/npm/lib/resolve.js +148 -0
- package/npm/scripts/build.js +183 -0
- package/package.json +58 -0
package/.npmrc.example
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# NPM Configuration Template
|
|
2
|
+
# Copy this file to .npmrc and add your token
|
|
3
|
+
|
|
4
|
+
# Registry
|
|
5
|
+
registry=https://registry.npmjs.org/
|
|
6
|
+
|
|
7
|
+
# Authentication - replace ${NPM_TOKEN} with your token
|
|
8
|
+
# Get token from: https://www.npmjs.com/settings/tokens
|
|
9
|
+
//registry.npmjs.org/:_authToken=${NPM_TOKEN}
|
|
10
|
+
|
|
11
|
+
# Package access (required for scoped packages)
|
|
12
|
+
@mandors:registry=https://registry.npmjs.org/
|
|
13
|
+
|
|
14
|
+
# Save exact versions
|
|
15
|
+
save-exact=true
|
|
16
|
+
|
|
17
|
+
# Build config
|
|
18
|
+
ignore-scripts=false
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
repos:
|
|
2
|
+
# Go formatting and linting
|
|
3
|
+
- repo: https://github.com/dnephin/pre-commit-golang
|
|
4
|
+
rev: v0.5.1
|
|
5
|
+
hooks:
|
|
6
|
+
- id: go-fmt
|
|
7
|
+
- id: go-vet
|
|
8
|
+
types: [go]
|
|
9
|
+
exclude: '^tests/'
|
|
10
|
+
- id: go-mod-tidy
|
|
11
|
+
- id: go-build
|
|
12
|
+
types: [go]
|
|
13
|
+
exclude: '^tests/'
|
|
14
|
+
- id: go-unit-tests
|
|
15
|
+
|
|
16
|
+
# JavaScript/Node.js linting
|
|
17
|
+
- repo: https://github.com/pre-commit/mirrors-eslint
|
|
18
|
+
rev: v9.0.0
|
|
19
|
+
hooks:
|
|
20
|
+
- id: eslint
|
|
21
|
+
files: npm/lib/
|
|
22
|
+
types: [javascript]
|
package/README.md
ADDED
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
# Mandor - Event-Based Task Manager CLI for AI Agent Workflows
|
|
2
|
+
|
|
3
|
+
<p align="center">
|
|
4
|
+
<img src="logo.png" alt="Mandor CLI">
|
|
5
|
+
</p>
|
|
6
|
+
|
|
7
|
+
<p align="center">
|
|
8
|
+
<strong>Deterministic JSONL output | Streaming-native architecture | Schema-driven task management</strong>
|
|
9
|
+
</p>
|
|
10
|
+
|
|
11
|
+
<p align="center">
|
|
12
|
+
<a href="#installation">Installation</a> •
|
|
13
|
+
<a href="#quick-start">Quick Start</a> •
|
|
14
|
+
<a href="#commands">Commands</a> •
|
|
15
|
+
<a href="#examples">Examples</a>
|
|
16
|
+
</p>
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Overview
|
|
21
|
+
|
|
22
|
+
Mandor is a CLI tool for managing tasks, features, and issues in AI agent workflows:
|
|
23
|
+
|
|
24
|
+
- **Event-Based Architecture**: All changes logged in `events.jsonl`
|
|
25
|
+
- **JSONL Format**: Deterministic, append-only storage
|
|
26
|
+
- **Dependency Tracking**: Automatic status based on dependencies
|
|
27
|
+
- **Cross-Platform**: Go binary for macOS, Linux, Windows
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## Background: Why Mandor Was Built
|
|
32
|
+
|
|
33
|
+
Research on **Context Rot** reveals a critical challenge for AI agents: LLM performance degrades significantly as input token count increases.
|
|
34
|
+
|
|
35
|
+
### The Problem
|
|
36
|
+
|
|
37
|
+
AI agents working on long tasks accumulate conversation history, task notes, and context. Research shows:
|
|
38
|
+
|
|
39
|
+
| Factor | Impact |
|
|
40
|
+
|--------|--------|
|
|
41
|
+
| Input Length | Performance drops 10-40% as tokens increase |
|
|
42
|
+
| Irrelevant Content | Causes 15-30% error rate |
|
|
43
|
+
| Task Complexity | Reasoning degrades faster than retrieval |
|
|
44
|
+
|
|
45
|
+
Even simple retrieval tasks show degradation at scale. Benchmarks like "Needle in a Haystack" (NIAH) show near-perfect scores, but they test simple keyword matching - not real-world reasoning.
|
|
46
|
+
|
|
47
|
+
### Why Structured Task Management Helps
|
|
48
|
+
|
|
49
|
+
Instead of stuffing everything into the context window:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
# Instead of: "Remember the 15 tasks from our conversation..."
|
|
53
|
+
|
|
54
|
+
# Use Mandor to externalize state:
|
|
55
|
+
mandor task list --project api --status pending
|
|
56
|
+
# Returns compact JSON for parsing
|
|
57
|
+
|
|
58
|
+
mandor task detail auth-feature-abc-task-xyz789
|
|
59
|
+
# Exact state, no ambiguity
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Mandor provides:
|
|
63
|
+
- **Compact Context**: Replace verbose descriptions with structured JSON
|
|
64
|
+
- **Deterministic Output**: JSONL format is reliable to parse
|
|
65
|
+
- **Complete Audit Trail**: Event log shows what changed and when
|
|
66
|
+
- **Dependency Enforcement**: Auto-blocking prevents invalid states
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## Installation
|
|
71
|
+
|
|
72
|
+
### From Source
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
git clone https://github.com/budisantoso/mandor.git
|
|
76
|
+
cd mandor
|
|
77
|
+
go build -o build/mandor ./cmd/mandor
|
|
78
|
+
sudo mv build/mandor /usr/local/bin/
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### From NPM
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
npm install -g @mandor/cli
|
|
85
|
+
npx @mandor/cli init "My Project"
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
|
|
90
|
+
## Quick Start
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
# 1. Initialize workspace
|
|
94
|
+
mandor init "My Project"
|
|
95
|
+
|
|
96
|
+
# 2. Create project
|
|
97
|
+
mandor project create api --name "API Service" --goal "Implement REST API"
|
|
98
|
+
|
|
99
|
+
# 3. Create feature
|
|
100
|
+
mandor feature create "User Auth" --project api --goal "Implement login/logout"
|
|
101
|
+
|
|
102
|
+
# 4. Create task
|
|
103
|
+
mandor task create "Password Hashing" \
|
|
104
|
+
--feature api-feature-xxx \
|
|
105
|
+
--goal "Implement bcrypt hashing" \
|
|
106
|
+
--implementation-steps "Install bcrypt,Create utility,Write tests" \
|
|
107
|
+
--test-cases "Hash validation,Password comparison" \
|
|
108
|
+
--derivable-files "src/utils/password.ts" \
|
|
109
|
+
--library-needs "bcrypt"
|
|
110
|
+
|
|
111
|
+
# 5. Check status
|
|
112
|
+
mandor status
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
---
|
|
116
|
+
|
|
117
|
+
## Commands
|
|
118
|
+
|
|
119
|
+
### Workspace
|
|
120
|
+
|
|
121
|
+
| Command | Description |
|
|
122
|
+
|---------|-------------|
|
|
123
|
+
| `mandor init <name>` | Initialize workspace |
|
|
124
|
+
| `mandor status` | Show workspace status |
|
|
125
|
+
| `mandor config get/set/list` | Manage configuration |
|
|
126
|
+
|
|
127
|
+
### Project
|
|
128
|
+
|
|
129
|
+
| Command | Description |
|
|
130
|
+
|---------|-------------|
|
|
131
|
+
| `mandor project create <id> --name --goal` | Create project |
|
|
132
|
+
| `mandor project list` | List projects |
|
|
133
|
+
| `mandor project detail <id>` | Show project details |
|
|
134
|
+
| `mandor project update <id>` | Update metadata |
|
|
135
|
+
| `mandor project delete <id>` | Delete project |
|
|
136
|
+
|
|
137
|
+
### Feature
|
|
138
|
+
|
|
139
|
+
| Command | Description |
|
|
140
|
+
|---------|-------------|
|
|
141
|
+
| `mandor feature create <name> --project --goal` | Create feature |
|
|
142
|
+
| `mandor feature list [--project <id>]` | List features |
|
|
143
|
+
| `mandor feature detail <id>` | Show feature details |
|
|
144
|
+
| `mandor feature update <id>` | Update/cancel/reopen |
|
|
145
|
+
|
|
146
|
+
**Status flow:** `draft` → `active` → `done` (or `blocked` → `cancelled`)
|
|
147
|
+
|
|
148
|
+
### Task
|
|
149
|
+
|
|
150
|
+
| Command | Description |
|
|
151
|
+
|---------|-------------|
|
|
152
|
+
| `mandor task create <name> --feature --goal --implementation-steps --test-cases --derivable-files --library-needs` | Create task |
|
|
153
|
+
| `mandor task list [--feature <id>] [--project <id>] [--status <status>]` | List tasks |
|
|
154
|
+
| `mandor task detail <id>` | Show task details |
|
|
155
|
+
| `mandor task update <id>` | Update task |
|
|
156
|
+
| `mandor task ready [--project <id>] [--priority <P0-P5>]` | List ready tasks |
|
|
157
|
+
| `mandor task blocked [--project <id>]` | List blocked tasks |
|
|
158
|
+
|
|
159
|
+
**Status flow:** `pending` → `ready` → `in_progress` → `done` (or `blocked` → `cancelled`)
|
|
160
|
+
|
|
161
|
+
### Issue
|
|
162
|
+
|
|
163
|
+
| Command | Description |
|
|
164
|
+
|---------|-------------|
|
|
165
|
+
| `mandor issue create <name> --project --type --goal --affected-files --affected-tests --implementation-steps` | Create issue |
|
|
166
|
+
| `mandor issue list [--project <id>] [--type <type>] [--status <status>]` | List issues |
|
|
167
|
+
| `mandor issue detail <id>` | Show issue details |
|
|
168
|
+
| `mandor issue update <id>` | Update/resolve/wontfix/cancel |
|
|
169
|
+
| `mandor issue ready [--project <id>]` | List ready issues |
|
|
170
|
+
| `mandor issue blocked [--project <id>]` | List blocked issues |
|
|
171
|
+
|
|
172
|
+
**Issue types:** `bug`, `improvement`, `debt`, `security`, `performance`
|
|
173
|
+
**Status flow:** `open` → `ready` → `in_progress` → `resolved` (or `wontfix`/`blocked` → `cancelled`)
|
|
174
|
+
|
|
175
|
+
### Utility
|
|
176
|
+
|
|
177
|
+
| Command | Description |
|
|
178
|
+
|---------|-------------|
|
|
179
|
+
| `mandor populate [--markdown\|--json]` | Full CLI reference |
|
|
180
|
+
| `mandor completion [bash\|zsh\|fish]` | Shell completion |
|
|
181
|
+
|
|
182
|
+
---
|
|
183
|
+
|
|
184
|
+
## Entity Types
|
|
185
|
+
|
|
186
|
+
| Entity | File | Description |
|
|
187
|
+
|--------|------|-------------|
|
|
188
|
+
| Workspace | `.mandor/workspace.json` | Root container |
|
|
189
|
+
| Project | `.mandor/projects/<id>/project.jsonl` | Feature/task/issue grouping |
|
|
190
|
+
| Feature | `.mandor/projects/<id>/features.jsonl` | High-level functionality |
|
|
191
|
+
| Task | `.mandor/projects/<id>/tasks.jsonl` | Work item implementing feature |
|
|
192
|
+
| Issue | `.mandor/projects/<id>/issues.jsonl` | Bug/improvement/debt |
|
|
193
|
+
| Events | `.mandor/projects/<id>/events.jsonl` | Append-only audit trail |
|
|
194
|
+
|
|
195
|
+
### ID Format
|
|
196
|
+
|
|
197
|
+
| Entity | Format | Example |
|
|
198
|
+
|--------|--------|---------|
|
|
199
|
+
| Project | `<id>` | `api` |
|
|
200
|
+
| Feature | `<project>-feature-<nanoid>` | `api-feature-abc123` |
|
|
201
|
+
| Task | `<feature_id>-task-<nanoid>` | `api-feature-abc-task-xyz789` |
|
|
202
|
+
| Issue | `<project>-issue-<nanoid>` | `api-issue-abc123` |
|
|
203
|
+
|
|
204
|
+
---
|
|
205
|
+
|
|
206
|
+
## File Structure
|
|
207
|
+
|
|
208
|
+
```
|
|
209
|
+
.mandor/
|
|
210
|
+
├── workspace.json # Workspace metadata
|
|
211
|
+
└── projects/
|
|
212
|
+
└── <project_id>/
|
|
213
|
+
├── project.jsonl # Project metadata
|
|
214
|
+
├── schema.json # Project rules
|
|
215
|
+
├── features.jsonl # Feature state
|
|
216
|
+
├── tasks.jsonl # Task state
|
|
217
|
+
├── issues.jsonl # Issue state
|
|
218
|
+
└── events.jsonl # Append-only audit trail
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
---
|
|
222
|
+
|
|
223
|
+
## Dependency Management
|
|
224
|
+
|
|
225
|
+
### Status Based on Dependencies
|
|
226
|
+
|
|
227
|
+
- **Feature**: No deps → `draft`, all done → `active`, otherwise blocked
|
|
228
|
+
- **Task**: No deps → `ready`, all done → `ready`, otherwise pending
|
|
229
|
+
- **Issue**: No deps → `ready`, all resolved → `ready`, otherwise open
|
|
230
|
+
|
|
231
|
+
### Blocking
|
|
232
|
+
|
|
233
|
+
Cannot cancel entities that other entities depend on. Use `--force` to override.
|
|
234
|
+
|
|
235
|
+
---
|
|
236
|
+
|
|
237
|
+
## Configuration
|
|
238
|
+
|
|
239
|
+
### Priority Levels
|
|
240
|
+
|
|
241
|
+
| Priority | Description |
|
|
242
|
+
|----------|-------------|
|
|
243
|
+
| P0 | Critical - Must do |
|
|
244
|
+
| P1 | High - Important |
|
|
245
|
+
| P2 | Medium - Should do |
|
|
246
|
+
| P3 | Normal - Default |
|
|
247
|
+
| P4 | Low - Nice to have |
|
|
248
|
+
| P5 | Minimal - Can defer |
|
|
249
|
+
|
|
250
|
+
### Scope Options (Features)
|
|
251
|
+
|
|
252
|
+
`frontend`, `backend`, `fullstack`, `cli`, `desktop`, `mobile`
|
|
253
|
+
|
|
254
|
+
---
|
|
255
|
+
|
|
256
|
+
## Examples
|
|
257
|
+
|
|
258
|
+
### Complete Workflow
|
|
259
|
+
|
|
260
|
+
```bash
|
|
261
|
+
mandor init "My Project"
|
|
262
|
+
mandor project create api --name "API Service" --goal "Implement API"
|
|
263
|
+
|
|
264
|
+
mandor feature create "User Auth" --project api --goal "Login/logout/registration"
|
|
265
|
+
mandor feature create "Payments" --project api --goal "Stripe integration" \
|
|
266
|
+
--depends api-feature-xxx
|
|
267
|
+
|
|
268
|
+
FEATURE_ID=$(mandor feature list --project api --json | jq -r '.[0].id')
|
|
269
|
+
mandor task create "Password Hashing" \
|
|
270
|
+
--feature $FEATURE_ID \
|
|
271
|
+
--goal "Implement bcrypt" \
|
|
272
|
+
--implementation-steps "Install bcrypt,Create utility,Write tests" \
|
|
273
|
+
--test-cases "Hash validation" \
|
|
274
|
+
--derivable-files "src/utils/password.ts" \
|
|
275
|
+
--library-needs "bcrypt"
|
|
276
|
+
|
|
277
|
+
mandor issue create "Fix memory leak" --project api \
|
|
278
|
+
--type bug --goal "Fix goroutine leak" \
|
|
279
|
+
--affected-files "src/handlers/auth.go" \
|
|
280
|
+
--affected-tests "src/handlers/auth_test.go" \
|
|
281
|
+
--implementation-steps "Identify leak,Add cleanup"
|
|
282
|
+
|
|
283
|
+
mandor status
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
### Issue Lifecycle
|
|
287
|
+
|
|
288
|
+
```bash
|
|
289
|
+
mandor issue create "Security Fix" --project api \
|
|
290
|
+
--type security --goal "Fix vulnerability"
|
|
291
|
+
|
|
292
|
+
mandor issue update api-issue-xxx --status in_progress
|
|
293
|
+
mandor issue update api-issue-xxx --resolve # or --wontfix
|
|
294
|
+
mandor issue update api-issue-xxx --reopen # if needed
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
---
|
|
298
|
+
|
|
299
|
+
## Exit Codes
|
|
300
|
+
|
|
301
|
+
| Code | Meaning |
|
|
302
|
+
|------|---------|
|
|
303
|
+
| 0 | Success |
|
|
304
|
+
| 1 | System error (I/O, internal) |
|
|
305
|
+
| 2 | Validation error (not found, invalid input) |
|
|
306
|
+
| 3 | Permission error |
|
|
307
|
+
|
|
308
|
+
---
|
|
309
|
+
|
|
310
|
+
## Support
|
|
311
|
+
|
|
312
|
+
- Issues: https://github.com/budisantoso/mandor/issues
|
|
313
|
+
- Documentation: `/docs` directory
|
|
314
|
+
|
|
315
|
+
---
|
|
316
|
+
|
|
317
|
+
**Built for AI Agent Workflows**
|
package/logo.png
ADDED
|
Binary file
|
package/npm/bin/mandor
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @fileoverview Mandor CLI Node.js wrapper script
|
|
5
|
+
* @description Resolves the Mandor binary path and spawns the CLI with provided arguments
|
|
6
|
+
* @version 0.0.1
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
const { resolve } = require('./lib/resolve');
|
|
10
|
+
const { spawn } = require('child_process');
|
|
11
|
+
const path = require('path');
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Main entry point for the Mandor CLI wrapper
|
|
15
|
+
* @async
|
|
16
|
+
* @returns {Promise<void>} Resolves when the CLI process exits
|
|
17
|
+
* @throws {Error} If binary resolution fails
|
|
18
|
+
* @example
|
|
19
|
+
* // Run: mandor task list --project api
|
|
20
|
+
* await main();
|
|
21
|
+
*/
|
|
22
|
+
async function main() {
|
|
23
|
+
const binaryPath = await resolve();
|
|
24
|
+
const args = process.argv.slice(2);
|
|
25
|
+
const proc = spawn(binaryPath, args, {
|
|
26
|
+
stdio: 'inherit',
|
|
27
|
+
cwd: process.cwd()
|
|
28
|
+
});
|
|
29
|
+
proc.on('exit', process.exit);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
main().catch(console.error);
|
package/npm/lib/api.js
ADDED
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Mandor CLI programmatic API
|
|
3
|
+
* @description Node.js API for interacting with Mandor from JavaScript/TypeScript code
|
|
4
|
+
* @version 0.0.1
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const { spawn } = require('child_process');
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @typedef {Object} MandorOptions
|
|
11
|
+
* @property {string} [cwd] - Working directory (default: process.cwd())
|
|
12
|
+
* @property {boolean} [json] - Use JSON output format (default: false)
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* @typedef {Object} ProjectCreateOptions
|
|
17
|
+
* @property {string} [name] - Project display name
|
|
18
|
+
* @property {string} [goal] - Project goal description
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* @typedef {Object} TaskListOptions
|
|
23
|
+
* @property {string} [project] - Filter by project ID
|
|
24
|
+
* @property {string} [feature] - Filter by feature ID
|
|
25
|
+
* @property {string} [status] - Filter by status (pending, ready, in_progress, done, blocked, cancelled)
|
|
26
|
+
* @property {string} [priority] - Filter by priority (P0-P5)
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Mandor CLI wrapper class for programmatic access
|
|
31
|
+
* @class
|
|
32
|
+
* @version 0.0.1
|
|
33
|
+
* @example
|
|
34
|
+
* const mandor = new Mandor({ cwd: '/path/to/project', json: true });
|
|
35
|
+
* const tasks = await mandor.taskList({ project: 'api', status: 'pending' });
|
|
36
|
+
*/
|
|
37
|
+
class Mandor {
|
|
38
|
+
/**
|
|
39
|
+
* Creates a new Mandor instance
|
|
40
|
+
* @constructor
|
|
41
|
+
* @param {MandorOptions} [options] - Configuration options
|
|
42
|
+
* @example
|
|
43
|
+
* const mandor = new Mandor({ cwd: '/my/project', json: true });
|
|
44
|
+
*/
|
|
45
|
+
constructor(options = {}) {
|
|
46
|
+
/** @type {string} Working directory */
|
|
47
|
+
this.cwd = options.cwd || process.cwd();
|
|
48
|
+
/** @type {boolean} Use JSON output */
|
|
49
|
+
this.json = options.json || false;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Initializes a new Mandor workspace
|
|
54
|
+
* @async
|
|
55
|
+
* @param {string} name - Workspace name
|
|
56
|
+
* @returns {Promise<number>} Exit code from the CLI
|
|
57
|
+
* @throws {Error} If initialization fails
|
|
58
|
+
* @example
|
|
59
|
+
* await mandor.init('My AI Project');
|
|
60
|
+
*/
|
|
61
|
+
async init(name) {
|
|
62
|
+
return this._run('init', [name]);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Creates a new project
|
|
67
|
+
* @async
|
|
68
|
+
* @param {string} id - Project identifier (lowercase, hyphens only)
|
|
69
|
+
* @param {ProjectCreateOptions} [options] - Project options
|
|
70
|
+
* @returns {Promise<number>} Exit code from the CLI
|
|
71
|
+
* @example
|
|
72
|
+
* await mandor.projectCreate('api', {
|
|
73
|
+
* name: 'API Service',
|
|
74
|
+
* goal: 'Implement REST API with user management'
|
|
75
|
+
* });
|
|
76
|
+
*/
|
|
77
|
+
async projectCreate(id, options = {}) {
|
|
78
|
+
const args = ['project', 'create', id];
|
|
79
|
+
if (options.name) args.push('--name', options.name);
|
|
80
|
+
if (options.goal) args.push('--goal', options.goal);
|
|
81
|
+
return this._run(...args);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Lists tasks with optional filters
|
|
86
|
+
* @async
|
|
87
|
+
* @param {TaskListOptions} [options] - Filter options
|
|
88
|
+
* @returns {Promise<Object[]|number>} Task list (JSON) or exit code
|
|
89
|
+
* @example
|
|
90
|
+
* const tasks = await mandor.taskList({
|
|
91
|
+
* project: 'api',
|
|
92
|
+
* status: 'pending',
|
|
93
|
+
* json: true
|
|
94
|
+
* });
|
|
95
|
+
*/
|
|
96
|
+
async taskList(options = {}) {
|
|
97
|
+
const args = ['task', 'list'];
|
|
98
|
+
if (options.project) args.push('--project', options.project);
|
|
99
|
+
if (options.feature) args.push('--feature', options.feature);
|
|
100
|
+
if (options.status) args.push('--status', options.status);
|
|
101
|
+
if (options.priority) args.push('--priority', options.priority);
|
|
102
|
+
if (options.json) args.push('--json');
|
|
103
|
+
return this._run(...args);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Gets detailed information about a task
|
|
108
|
+
* @async
|
|
109
|
+
* @param {string} taskId - Task identifier
|
|
110
|
+
* @returns {Promise<Object|number>} Task details (JSON) or exit code
|
|
111
|
+
* @example
|
|
112
|
+
* const task = await mandor.taskDetail('api-feature-abc-task-xyz789', { json: true });
|
|
113
|
+
*/
|
|
114
|
+
async taskDetail(taskId) {
|
|
115
|
+
return this._run('task', 'detail', taskId);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Updates a task's status or metadata
|
|
120
|
+
* @async
|
|
121
|
+
* @param {string} taskId - Task identifier
|
|
122
|
+
* @param {Object} updates - Fields to update
|
|
123
|
+
* @returns {Promise<number>} Exit code from the CLI
|
|
124
|
+
* @example
|
|
125
|
+
* await mandor.taskUpdate('api-feature-abc-task-xyz789', {
|
|
126
|
+
* status: 'in_progress'
|
|
127
|
+
* });
|
|
128
|
+
*/
|
|
129
|
+
async taskUpdate(taskId, updates = {}) {
|
|
130
|
+
const args = ['task', 'update', taskId];
|
|
131
|
+
if (updates.status) args.push('--status', updates.status);
|
|
132
|
+
if (updates.name) args.push('--name', updates.name);
|
|
133
|
+
if (updates.priority) args.push('--priority', updates.priority);
|
|
134
|
+
return this._run(...args);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Lists features with optional filters
|
|
139
|
+
* @async
|
|
140
|
+
* @param {Object} [options] - Filter options
|
|
141
|
+
* @returns {Promise<Object[]|number>} Feature list (JSON) or exit code
|
|
142
|
+
* @example
|
|
143
|
+
* const features = await mandor.featureList({ project: 'api', json: true });
|
|
144
|
+
*/
|
|
145
|
+
async featureList(options = {}) {
|
|
146
|
+
const args = ['feature', 'list'];
|
|
147
|
+
if (options.project) args.push('--project', options.project);
|
|
148
|
+
if (options.status) args.push('--status', options.status);
|
|
149
|
+
if (options.json) args.push('--json');
|
|
150
|
+
return this._run(...args);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Lists issues with optional filters
|
|
155
|
+
* @async
|
|
156
|
+
* @param {Object} [options] - Filter options
|
|
157
|
+
* @returns {Promise<Object[]|number>} Issue list (JSON) or exit code
|
|
158
|
+
* @example
|
|
159
|
+
* const issues = await mandor.issueList({ project: 'api', type: 'bug', json: true });
|
|
160
|
+
*/
|
|
161
|
+
async issueList(options = {}) {
|
|
162
|
+
const args = ['issue', 'list'];
|
|
163
|
+
if (options.project) args.push('--project', options.project);
|
|
164
|
+
if (options.type) args.push('--type', options.type);
|
|
165
|
+
if (options.status) args.push('--status', options.status);
|
|
166
|
+
if (options.json) args.push('--json');
|
|
167
|
+
return this._run(...args);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Gets workspace status and statistics
|
|
172
|
+
* @async
|
|
173
|
+
* @param {Object} [options] - Options
|
|
174
|
+
* @returns {Promise<Object|number>} Status (JSON) or exit code
|
|
175
|
+
* @example
|
|
176
|
+
* const status = await mandor.status({ json: true });
|
|
177
|
+
*/
|
|
178
|
+
async status(options = {}) {
|
|
179
|
+
const args = ['status'];
|
|
180
|
+
if (options.json) args.push('--json');
|
|
181
|
+
return this._run(...args);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Internal method to run mandor CLI commands
|
|
186
|
+
* @private
|
|
187
|
+
* @async
|
|
188
|
+
* @param {...string} args - Command arguments
|
|
189
|
+
* @returns {Promise<Object|number>} Result based on json option
|
|
190
|
+
* @throws {Error} If process fails
|
|
191
|
+
*/
|
|
192
|
+
_run(...args) {
|
|
193
|
+
return new Promise((resolve, reject) => {
|
|
194
|
+
const proc = spawn('mandor', args, {
|
|
195
|
+
cwd: this.cwd,
|
|
196
|
+
stdio: this.json ? 'pipe' : 'inherit'
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
if (this.json) {
|
|
200
|
+
let data = '';
|
|
201
|
+
proc.stdout.on('data', chunk => data += chunk);
|
|
202
|
+
proc.on('close', (code) => {
|
|
203
|
+
try {
|
|
204
|
+
resolve(JSON.parse(data));
|
|
205
|
+
} catch {
|
|
206
|
+
resolve(data);
|
|
207
|
+
}
|
|
208
|
+
});
|
|
209
|
+
} else {
|
|
210
|
+
proc.on('close', resolve);
|
|
211
|
+
}
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
module.exports = Mandor;
|