@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 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;