planfs-cli 1.3.0 → 1.4.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 +58 -0
- package/dist/cli.d.ts +1 -1
- package/dist/cli.js +6 -544
- package/dist/cli.js.map +1 -1
- package/dist/commands/ai.d.ts +5 -1
- package/dist/commands/ai.js +93 -0
- package/dist/commands/ai.js.map +1 -1
- package/dist/commands/format.d.ts +9 -0
- package/dist/commands/format.js +98 -0
- package/dist/commands/format.js.map +1 -0
- package/dist/commands/inspect.d.ts +9 -0
- package/dist/commands/inspect.js +153 -0
- package/dist/commands/inspect.js.map +1 -0
- package/dist/commands/show.d.ts +2 -0
- package/dist/commands/show.js +27 -1
- package/dist/commands/show.js.map +1 -1
- package/dist/commands/validate.d.ts +6 -0
- package/dist/commands/validate.js +44 -7
- package/dist/commands/validate.js.map +1 -1
- package/dist/entity-commands.d.ts +5 -0
- package/dist/entity-commands.js +230 -0
- package/dist/entity-commands.js.map +1 -0
- package/dist/planning-commands.d.ts +5 -0
- package/dist/planning-commands.js +259 -0
- package/dist/planning-commands.js.map +1 -0
- package/dist/workflow-commands.d.ts +5 -0
- package/dist/workflow-commands.js +222 -0
- package/dist/workflow-commands.js.map +1 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -14,6 +14,8 @@ Command-line interface for PlanFS.
|
|
|
14
14
|
- **Show** - Display entity details
|
|
15
15
|
- **Create** - Create new entities
|
|
16
16
|
- **PR** - Generate pull request planning context
|
|
17
|
+
- **Format** - Check, preview, and explicitly apply conservative semantic Markdown repairs
|
|
18
|
+
- **Semantic context** - Share compact, traceable planning intent and relationship context between agents and people
|
|
17
19
|
|
|
18
20
|
## Installation
|
|
19
21
|
|
|
@@ -46,8 +48,14 @@ Validate the repository for errors:
|
|
|
46
48
|
```bash
|
|
47
49
|
planfs validate
|
|
48
50
|
planfs validate --verbose
|
|
51
|
+
planfs validate --semantic baseline
|
|
52
|
+
planfs validate --semantic automation-ready --lifecycle
|
|
53
|
+
planfs validate --semantic automation-ready --criterion-check-state error --format json
|
|
54
|
+
planfs validate --semantic automation-ready --nlp --language en
|
|
49
55
|
```
|
|
50
56
|
|
|
57
|
+
Semantic validation is opt-in and remains separate from existing YAML and repository-integrity checks. `baseline` checks loss-preserving Markdown interpretation; `automation-ready` applies entity content profiles; `--lifecycle` adds read-only status-sensitive policy. Ordinary criteria can be ignored or reported at `info`, `warning`, or `error` severity. `--strict` fails on repository or semantic warnings. Enabled semantic JSON appears under a separate `semantic` key, leaving default JSON unchanged.
|
|
58
|
+
|
|
51
59
|
### List
|
|
52
60
|
|
|
53
61
|
List entities:
|
|
@@ -103,6 +111,19 @@ planfs backlog list --format json
|
|
|
103
111
|
|
|
104
112
|
Backlog refinement states are `captured`, `needs-refinement`, `ready`, `deferred`, and `discarded`. Explicit non-ready backlog items are separate from next-work recommendations.
|
|
105
113
|
|
|
114
|
+
### AI Planning Context
|
|
115
|
+
|
|
116
|
+
Start with the repository summary, then retrieve bounded semantic context for relevant work:
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
planfs ai summary --only ready --compact
|
|
120
|
+
planfs ai context --id TASK-001
|
|
121
|
+
planfs ai context --id TASK-001 --format text
|
|
122
|
+
planfs ai context --id TASK-001 --nlp --language en
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
`ai context` uses the shared core semantic parser and returns intent, recognized sections, acceptance criteria, findings, decisions, questions, references, diagnostics, readiness, and resolved authoritative relationships. JSON retains source ranges and provenance for traceability; text presents the same contract for human review. Advisory prose analysis is local, optional, and never mutates metadata.
|
|
126
|
+
|
|
106
127
|
### Show
|
|
107
128
|
|
|
108
129
|
Display entity details:
|
|
@@ -110,8 +131,45 @@ Display entity details:
|
|
|
110
131
|
```bash
|
|
111
132
|
planfs show TASK-001
|
|
112
133
|
planfs show TASK-001 --format json
|
|
134
|
+
planfs show TASK-001 --nlp
|
|
135
|
+
planfs show TASK-001 --nlp --language en --format json
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
`--nlp` explicitly enables local, advisory English prose analysis. It reports promoted modality, negation, condition, date/duration, and possible relationship-mention signals with source locations. Analysis never edits the file or treats prose as authoritative metadata. It makes no network calls and downloads no model. Other languages return an advisory unsupported-language diagnostic without hiding the entity or failing the command.
|
|
139
|
+
|
|
140
|
+
Without `--nlp`, JSON output retains the existing entity shape. With `--nlp`, JSON is `{ "entity": ..., "analysis": ... }`; every signal is marked `nlp-inferred` and `authoritative: false`.
|
|
141
|
+
|
|
142
|
+
### Semantic Inspection
|
|
143
|
+
|
|
144
|
+
Inspect normalized Markdown content, authoritative relationships, diagnostics, and advisory suggestions through one stable surface:
|
|
145
|
+
|
|
146
|
+
```bash
|
|
147
|
+
planfs inspect TASK-001
|
|
148
|
+
planfs inspect TASK-001 --format json
|
|
149
|
+
planfs inspect TASK-001 --view acceptance-criteria --format json
|
|
150
|
+
planfs inspect TASK-001 --view relationships
|
|
151
|
+
planfs inspect TASK-001 --view raw --no-nlp
|
|
113
152
|
```
|
|
114
153
|
|
|
154
|
+
Semantic inspection runs the bundled local analyzer by default and can be made structural-only with `--no-nlp`. Normal text output shows deduplicated actionable suggestions; full JSON preserves analyzer identity, language, evidence, confidence, provenance, raw signals, exact source ranges, and raw Markdown. Analysis remains advisory and never modifies frontmatter. This does not change `validate`: analysis during validation is still explicitly enabled with `--nlp`.
|
|
155
|
+
|
|
156
|
+
Focused views are `all`, `acceptance-criteria`, `findings`, `sections`, `mentions`, `relationships`, and `raw`. See [Semantic Entity Inspection](../../docs/SEMANTIC_INSPECTION.md) for the stable envelope and integration examples.
|
|
157
|
+
|
|
158
|
+
### Semantic Formatting
|
|
159
|
+
|
|
160
|
+
Keep validation, formatting checks, previews, and writes explicit:
|
|
161
|
+
|
|
162
|
+
```bash
|
|
163
|
+
planfs validate --semantic automation-ready
|
|
164
|
+
planfs format TASK-001 --check
|
|
165
|
+
planfs format TASK-001 --format json
|
|
166
|
+
planfs format TASK-001 --apply --expected-fingerprint sha256:...
|
|
167
|
+
planfs format TASK-001 TASK-002 --format json
|
|
168
|
+
planfs format --all --check
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
`format` canonicalizes only uniquely recognized headings and acceptance/release checklist markers. Preview is the default and never writes. Apply requires the source fingerprint returned by preview; batch fingerprints use `ENTITY-ID=sha256:...`. Unknown sections, code, HTML, comments, links, images, line endings, and frontmatter remain unchanged. Duplicate recognized sections and unsafe regions are reported rather than merged or guessed. See [Semantic Markdown Formatting](../../docs/SEMANTIC_FORMATTING.md) for the complete safety contract.
|
|
172
|
+
|
|
115
173
|
### Create
|
|
116
174
|
|
|
117
175
|
Create new entities:
|
package/dist/cli.d.ts
CHANGED
package/dist/cli.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
"use strict";
|
|
3
3
|
/**
|
|
4
|
-
* Main CLI entry point
|
|
4
|
+
* Main CLI entry point.
|
|
5
5
|
*/
|
|
6
6
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
7
7
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
@@ -10,551 +10,13 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
10
10
|
exports.main = main;
|
|
11
11
|
const yargs_1 = __importDefault(require("yargs"));
|
|
12
12
|
const helpers_1 = require("yargs/helpers");
|
|
13
|
-
const
|
|
14
|
-
const
|
|
15
|
-
const
|
|
16
|
-
const list_1 = require("./commands/list");
|
|
17
|
-
const next_1 = require("./commands/next");
|
|
18
|
-
const show_1 = require("./commands/show");
|
|
19
|
-
const create_1 = require("./commands/create");
|
|
20
|
-
const backlog_1 = require("./commands/backlog");
|
|
21
|
-
const archive_1 = require("./commands/archive");
|
|
22
|
-
const branch_1 = require("./commands/branch");
|
|
23
|
-
const git_1 = require("./commands/git");
|
|
24
|
-
const pr_1 = require("./commands/pr");
|
|
25
|
-
const doctor_1 = require("./commands/doctor");
|
|
26
|
-
const migrate_1 = require("./commands/migrate");
|
|
27
|
-
const update_1 = require("./commands/update");
|
|
28
|
-
const filter_1 = require("./commands/filter");
|
|
29
|
-
const history_1 = require("./commands/history");
|
|
13
|
+
const entity_commands_1 = require("./entity-commands");
|
|
14
|
+
const planning_commands_1 = require("./planning-commands");
|
|
15
|
+
const workflow_commands_1 = require("./workflow-commands");
|
|
30
16
|
const package_json_1 = __importDefault(require("../package.json"));
|
|
31
17
|
async function main() {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
.command('ai <action>', 'AI-oriented planning summary and update helpers', (y) => y
|
|
35
|
-
.positional('action', {
|
|
36
|
-
describe: 'AI helper to run',
|
|
37
|
-
choices: ['summary', 'update-task', 'bulk-update-tasks', 'initialize']
|
|
38
|
-
})
|
|
39
|
-
.option('id', {
|
|
40
|
-
type: 'string',
|
|
41
|
-
description: 'Task ID to update'
|
|
42
|
-
})
|
|
43
|
-
.option('ids', {
|
|
44
|
-
type: 'array',
|
|
45
|
-
string: true,
|
|
46
|
-
description: 'Task IDs to bulk update, comma-separated or repeated'
|
|
47
|
-
})
|
|
48
|
-
.option('assignee', {
|
|
49
|
-
type: 'string',
|
|
50
|
-
description: 'Scope summary or set task assignee'
|
|
51
|
-
})
|
|
52
|
-
.option('epic', {
|
|
53
|
-
type: 'string',
|
|
54
|
-
description: 'Scope summary or set task epic'
|
|
55
|
-
})
|
|
56
|
-
.option('milestone', {
|
|
57
|
-
type: 'string',
|
|
58
|
-
description: 'Scope summary or set task milestone'
|
|
59
|
-
})
|
|
60
|
-
.option('estimate', {
|
|
61
|
-
type: 'string',
|
|
62
|
-
description: 'Set task estimate'
|
|
63
|
-
})
|
|
64
|
-
.option('status', {
|
|
65
|
-
type: 'array',
|
|
66
|
-
string: true,
|
|
67
|
-
choices: ['todo', 'in-progress', 'review', 'done'],
|
|
68
|
-
description: 'Scope summary by status or set task status'
|
|
69
|
-
})
|
|
70
|
-
.option('priority', {
|
|
71
|
-
type: 'string',
|
|
72
|
-
choices: ['low', 'medium', 'high', 'critical'],
|
|
73
|
-
description: 'Set task priority'
|
|
74
|
-
})
|
|
75
|
-
.option('refinement-state', {
|
|
76
|
-
type: 'array',
|
|
77
|
-
string: true,
|
|
78
|
-
choices: ['captured', 'needs-refinement', 'ready', 'deferred', 'discarded'],
|
|
79
|
-
description: 'Scope summary by refinement state or set task refinement state'
|
|
80
|
-
})
|
|
81
|
-
.option('due-date', {
|
|
82
|
-
type: 'string',
|
|
83
|
-
description: 'Set task due date'
|
|
84
|
-
})
|
|
85
|
-
.option('tags', {
|
|
86
|
-
type: 'string',
|
|
87
|
-
description: 'Set task tags as a comma-separated list'
|
|
88
|
-
})
|
|
89
|
-
.option('limit', {
|
|
90
|
-
type: 'number',
|
|
91
|
-
description: 'Maximum number of summary items per list'
|
|
92
|
-
})
|
|
93
|
-
.option('only', {
|
|
94
|
-
type: 'string',
|
|
95
|
-
choices: ['open', 'ready', 'blocked', 'review', 'stale', 'recent'],
|
|
96
|
-
description: 'Return only one planning summary section'
|
|
97
|
-
})
|
|
98
|
-
.option('compact', {
|
|
99
|
-
type: 'boolean',
|
|
100
|
-
default: false,
|
|
101
|
-
description: 'Emit minified JSON for lower-overhead agent context'
|
|
102
|
-
})
|
|
103
|
-
.option('expected-updated-at', {
|
|
104
|
-
type: 'string',
|
|
105
|
-
description: 'Refuse a task update if updatedAt changed since preview (use none for an unset timestamp)'
|
|
106
|
-
})
|
|
107
|
-
.option('command', {
|
|
108
|
-
type: 'string',
|
|
109
|
-
description: 'CLI command written by ai initialize (default: planfs)'
|
|
110
|
-
})
|
|
111
|
-
.option('dry-run', {
|
|
112
|
-
type: 'boolean',
|
|
113
|
-
default: false,
|
|
114
|
-
description: 'Preview task updates or awareness initialization without writing files'
|
|
115
|
-
})
|
|
116
|
-
.option('file', {
|
|
117
|
-
type: 'string',
|
|
118
|
-
default: 'AGENTS.md',
|
|
119
|
-
description: 'Agent instruction file to create or update'
|
|
120
|
-
})
|
|
121
|
-
.option('format', {
|
|
122
|
-
type: 'string',
|
|
123
|
-
choices: ['json', 'text'],
|
|
124
|
-
default: 'json',
|
|
125
|
-
description: 'Output format'
|
|
126
|
-
}), async (args) => {
|
|
127
|
-
const exitCode = await (0, ai_1.aiCommand)(process.cwd(), args.action, {
|
|
128
|
-
id: args.id,
|
|
129
|
-
ids: args.ids,
|
|
130
|
-
assignee: args.assignee,
|
|
131
|
-
epic: args.epic,
|
|
132
|
-
milestone: args.milestone,
|
|
133
|
-
estimate: args.estimate,
|
|
134
|
-
status: args.status,
|
|
135
|
-
priority: args.priority,
|
|
136
|
-
refinementState: args.refinementState,
|
|
137
|
-
dueDate: args.dueDate,
|
|
138
|
-
tags: args.tags,
|
|
139
|
-
limit: args.limit,
|
|
140
|
-
dryRun: args.dryRun,
|
|
141
|
-
file: args.file,
|
|
142
|
-
format: args.format,
|
|
143
|
-
only: args.only,
|
|
144
|
-
compact: args.compact,
|
|
145
|
-
expectedUpdatedAt: args.expectedUpdatedAt,
|
|
146
|
-
command: args.command
|
|
147
|
-
});
|
|
148
|
-
process.exit(exitCode);
|
|
149
|
-
})
|
|
150
|
-
.command('init', 'Initialize PlanFS repository structure', (y) => y.option('format', {
|
|
151
|
-
type: 'string',
|
|
152
|
-
choices: ['text', 'json'],
|
|
153
|
-
default: 'text',
|
|
154
|
-
description: 'Output format'
|
|
155
|
-
}), async (args) => {
|
|
156
|
-
const exitCode = await (0, init_1.initCommand)(process.cwd(), {
|
|
157
|
-
format: args.format
|
|
158
|
-
});
|
|
159
|
-
process.exit(exitCode);
|
|
160
|
-
})
|
|
161
|
-
.command('validate', 'Validate the PlanFS repository', (y) => y
|
|
162
|
-
.option('verbose', {
|
|
163
|
-
alias: 'v',
|
|
164
|
-
type: 'boolean',
|
|
165
|
-
description: 'Show detailed output',
|
|
166
|
-
default: false
|
|
167
|
-
})
|
|
168
|
-
.option('strict', {
|
|
169
|
-
type: 'boolean',
|
|
170
|
-
default: false,
|
|
171
|
-
description: 'Fail when validation warnings are present'
|
|
172
|
-
})
|
|
173
|
-
.option('format', {
|
|
174
|
-
type: 'string',
|
|
175
|
-
choices: ['text', 'json'],
|
|
176
|
-
default: 'text',
|
|
177
|
-
description: 'Output format'
|
|
178
|
-
}), async (args) => {
|
|
179
|
-
const exitCode = await (0, validate_1.validateCommand)(process.cwd(), {
|
|
180
|
-
verbose: args.verbose,
|
|
181
|
-
strict: args.strict,
|
|
182
|
-
format: args.format
|
|
183
|
-
});
|
|
184
|
-
process.exit(exitCode);
|
|
185
|
-
})
|
|
186
|
-
.command('doctor', 'Report actionable plan-health issues separately from historical references', (y) => y.option('format', { type: 'string', choices: ['text', 'json'], default: 'text' }), async (args) => {
|
|
187
|
-
process.exit(await (0, doctor_1.doctorCommand)(process.cwd(), { format: args.format }));
|
|
188
|
-
})
|
|
189
|
-
.command('migrate', 'Preview or apply a PlanFS format migration', (y) => y.option('apply', { type: 'boolean', default: false }).option('format', { type: 'string', choices: ['text', 'json'], default: 'text' }), async (args) => {
|
|
190
|
-
process.exit(await (0, migrate_1.migrateCommand)(process.cwd(), { apply: args.apply, format: args.format }));
|
|
191
|
-
})
|
|
192
|
-
.command('update <id>', 'Preview or update common entity metadata', (y) => y.positional('id', { type: 'string' }).option('title', { type: 'string' }).option('status', { type: 'string' }).option('owner', { type: 'string' }).option('assignee', { type: 'string' }).option('priority', { type: 'string' }).option('target-date', { type: 'string' }).option('clear', { type: 'array', string: true, description: 'Explicitly clear optional fields' }).option('expected-updated-at', { type: 'string' }).option('dry-run', { type: 'boolean', default: false }).option('format', { type: 'string', choices: ['text', 'json'], default: 'text' }), async (args) => {
|
|
193
|
-
const patch = { title: args.title, status: args.status, owner: args.owner, assignee: args.assignee, priority: args.priority, targetDate: args.targetDate };
|
|
194
|
-
for (const field of args.clear ?? [])
|
|
195
|
-
patch[field] = '__clear__';
|
|
196
|
-
process.exit(await (0, update_1.updateCommand)(process.cwd(), args.id, { patch, expectedUpdatedAt: args.expectedUpdatedAt, dryRun: args.dryRun, format: args.format }));
|
|
197
|
-
})
|
|
198
|
-
.command('filter <action>', 'Manage repository-shared saved filters', (y) => y.positional('action', { choices: ['list', 'show', 'save', 'delete'] }).option('id', { type: 'string' }).option('name', { type: 'string' }).option('description', { type: 'string' }).option('criteria', { type: 'string', description: 'Filter criteria as JSON' }).option('dry-run', { type: 'boolean', default: false }).option('format', { type: 'string', choices: ['text', 'json'], default: 'text' }), async (args) => process.exit(await (0, filter_1.filterCommand)(process.cwd(), args.action, { id: args.id, name: args.name, description: args.description, criteria: args.criteria, dryRun: args.dryRun, format: args.format })))
|
|
199
|
-
.command('history <id>', 'Show Git history for a PlanFS entity', (y) => y.positional('id', { type: 'string' }).option('format', { type: 'string', choices: ['text', 'json'], default: 'text' }), async (args) => process.exit(await (0, history_1.historyCommand)(process.cwd(), args.id, args.format)))
|
|
200
|
-
.command('branch', 'Show PlanFS changes on the current Git branch', (y) => y
|
|
201
|
-
.option('base', {
|
|
202
|
-
type: 'string',
|
|
203
|
-
description: 'Base branch or ref to compare against'
|
|
204
|
-
})
|
|
205
|
-
.option('format', {
|
|
206
|
-
type: 'string',
|
|
207
|
-
choices: ['text', 'json'],
|
|
208
|
-
default: 'text',
|
|
209
|
-
description: 'Output format'
|
|
210
|
-
}), async (args) => {
|
|
211
|
-
const exitCode = await (0, branch_1.branchCommand)(process.cwd(), {
|
|
212
|
-
base: args.base,
|
|
213
|
-
format: args.format
|
|
214
|
-
});
|
|
215
|
-
process.exit(exitCode);
|
|
216
|
-
})
|
|
217
|
-
.command('git <action> [message..]', 'Use Git-aware PlanFS helpers', (y) => y
|
|
218
|
-
.positional('action', {
|
|
219
|
-
describe: 'Git helper to run',
|
|
220
|
-
choices: ['commit-message', 'validate-message']
|
|
221
|
-
})
|
|
222
|
-
.positional('message', {
|
|
223
|
-
describe: 'Commit message to validate',
|
|
224
|
-
type: 'string'
|
|
225
|
-
})
|
|
226
|
-
.option('base', {
|
|
227
|
-
type: 'string',
|
|
228
|
-
description: 'Base branch or ref for commit message suggestions'
|
|
229
|
-
})
|
|
230
|
-
.option('format', {
|
|
231
|
-
type: 'string',
|
|
232
|
-
choices: ['text', 'json'],
|
|
233
|
-
default: 'text',
|
|
234
|
-
description: 'Output format'
|
|
235
|
-
}), async (args) => {
|
|
236
|
-
const message = Array.isArray(args.message)
|
|
237
|
-
? args.message.join(' ')
|
|
238
|
-
: args.message;
|
|
239
|
-
const exitCode = await (0, git_1.gitCommand)(process.cwd(), args.action, message, {
|
|
240
|
-
base: args.base,
|
|
241
|
-
format: args.format
|
|
242
|
-
});
|
|
243
|
-
process.exit(exitCode);
|
|
244
|
-
})
|
|
245
|
-
.command('pr <action>', 'Generate pull request planning context', (y) => y
|
|
246
|
-
.positional('action', {
|
|
247
|
-
describe: 'Pull request helper to run',
|
|
248
|
-
choices: ['summary', 'providers']
|
|
249
|
-
})
|
|
250
|
-
.option('base', {
|
|
251
|
-
type: 'string',
|
|
252
|
-
description: 'Base branch or ref to compare against'
|
|
253
|
-
})
|
|
254
|
-
.option('provider', {
|
|
255
|
-
type: 'string',
|
|
256
|
-
choices: ['github', 'gitlab', 'azure-devops'],
|
|
257
|
-
default: 'github',
|
|
258
|
-
description: 'Pull request provider'
|
|
259
|
-
})
|
|
260
|
-
.option('format', {
|
|
261
|
-
type: 'string',
|
|
262
|
-
choices: ['markdown', 'json'],
|
|
263
|
-
default: 'markdown',
|
|
264
|
-
description: 'Output format'
|
|
265
|
-
}), async (args) => {
|
|
266
|
-
const exitCode = await (0, pr_1.pullRequestCommand)(process.cwd(), args.action, {
|
|
267
|
-
base: args.base,
|
|
268
|
-
provider: args.provider,
|
|
269
|
-
format: args.format
|
|
270
|
-
});
|
|
271
|
-
process.exit(exitCode);
|
|
272
|
-
})
|
|
273
|
-
.command('archive <action>', 'Archive, restore, and browse hidden PlanFS tasks and epics', (y) => y
|
|
274
|
-
.positional('action', {
|
|
275
|
-
describe: 'Archive workflow to run',
|
|
276
|
-
choices: ['list', 'archive', 'restore', 'delete']
|
|
277
|
-
})
|
|
278
|
-
.option('id', {
|
|
279
|
-
type: 'string',
|
|
280
|
-
description: 'Task or epic ID'
|
|
281
|
-
})
|
|
282
|
-
.option('include-children', {
|
|
283
|
-
type: 'boolean',
|
|
284
|
-
default: false,
|
|
285
|
-
description: 'When archiving an epic, also archive child tasks'
|
|
286
|
-
})
|
|
287
|
-
.option('dry-run', {
|
|
288
|
-
type: 'boolean',
|
|
289
|
-
default: false,
|
|
290
|
-
description: 'Preview archive changes without writing files'
|
|
291
|
-
})
|
|
292
|
-
.option('expected-updated-at', {
|
|
293
|
-
type: 'string',
|
|
294
|
-
description: 'Refuse archive if the target updatedAt has changed'
|
|
295
|
-
})
|
|
296
|
-
.option('yes', {
|
|
297
|
-
type: 'boolean',
|
|
298
|
-
default: false,
|
|
299
|
-
description: 'Confirm permanent archive deletion'
|
|
300
|
-
})
|
|
301
|
-
.option('disposition', { type: 'string', choices: ['completed', 'cancelled', 'duplicate', 'deferred', 'superseded'], description: 'Reason for archiving unfinished work' })
|
|
302
|
-
.option('note', { type: 'string', description: 'Optional archive note' })
|
|
303
|
-
.option('format', {
|
|
304
|
-
type: 'string',
|
|
305
|
-
choices: ['text', 'json'],
|
|
306
|
-
default: 'text',
|
|
307
|
-
description: 'Output format'
|
|
308
|
-
}), async (args) => {
|
|
309
|
-
const exitCode = await (0, archive_1.archiveCommand)(process.cwd(), args.action, {
|
|
310
|
-
id: args.id,
|
|
311
|
-
includeChildren: args.includeChildren,
|
|
312
|
-
dryRun: args.dryRun,
|
|
313
|
-
expectedUpdatedAt: args.expectedUpdatedAt,
|
|
314
|
-
yes: args.yes,
|
|
315
|
-
disposition: args.disposition,
|
|
316
|
-
note: args.note,
|
|
317
|
-
format: args.format
|
|
318
|
-
});
|
|
319
|
-
process.exit(exitCode);
|
|
320
|
-
})
|
|
321
|
-
.command('backlog <action>', 'Manage backlog intake, refinement, and hygiene', (y) => y
|
|
322
|
-
.positional('action', {
|
|
323
|
-
describe: 'Backlog workflow to run',
|
|
324
|
-
choices: ['list', 'capture', 'set-state', 'review']
|
|
325
|
-
})
|
|
326
|
-
.option('title', {
|
|
327
|
-
alias: 't',
|
|
328
|
-
type: 'string',
|
|
329
|
-
description: 'Title for captured backlog items'
|
|
330
|
-
})
|
|
331
|
-
.option('id', {
|
|
332
|
-
type: 'string',
|
|
333
|
-
description: 'Task ID to update'
|
|
334
|
-
})
|
|
335
|
-
.option('state', {
|
|
336
|
-
type: 'string',
|
|
337
|
-
choices: ['captured', 'needs-refinement', 'ready', 'deferred', 'discarded'],
|
|
338
|
-
description: 'Backlog refinement state'
|
|
339
|
-
})
|
|
340
|
-
.option('assignee', {
|
|
341
|
-
type: 'string',
|
|
342
|
-
description: 'Filter or set assignee'
|
|
343
|
-
})
|
|
344
|
-
.option('epic', {
|
|
345
|
-
type: 'string',
|
|
346
|
-
description: 'Filter or set epic'
|
|
347
|
-
})
|
|
348
|
-
.option('milestone', {
|
|
349
|
-
type: 'string',
|
|
350
|
-
description: 'Filter or set milestone'
|
|
351
|
-
})
|
|
352
|
-
.option('priority', {
|
|
353
|
-
type: 'string',
|
|
354
|
-
choices: ['low', 'medium', 'high', 'critical'],
|
|
355
|
-
description: 'Filter or set priority'
|
|
356
|
-
})
|
|
357
|
-
.option('tag', {
|
|
358
|
-
type: 'array',
|
|
359
|
-
string: true,
|
|
360
|
-
description: 'Filter by tag'
|
|
361
|
-
})
|
|
362
|
-
.option('query', {
|
|
363
|
-
type: 'string',
|
|
364
|
-
description: 'Filter by text query'
|
|
365
|
-
})
|
|
366
|
-
.option('body', {
|
|
367
|
-
type: 'string',
|
|
368
|
-
description: 'Markdown body for captured backlog items'
|
|
369
|
-
})
|
|
370
|
-
.option('limit', {
|
|
371
|
-
type: 'number',
|
|
372
|
-
description: 'Maximum number of items to show'
|
|
373
|
-
})
|
|
374
|
-
.option('format', {
|
|
375
|
-
type: 'string',
|
|
376
|
-
choices: ['text', 'json'],
|
|
377
|
-
default: 'text',
|
|
378
|
-
description: 'Output format'
|
|
379
|
-
}), async (args) => {
|
|
380
|
-
const exitCode = await (0, backlog_1.backlogCommand)(process.cwd(), args.action, {
|
|
381
|
-
title: args.title,
|
|
382
|
-
id: args.id,
|
|
383
|
-
state: args.state,
|
|
384
|
-
assignee: args.assignee,
|
|
385
|
-
epic: args.epic,
|
|
386
|
-
milestone: args.milestone,
|
|
387
|
-
priority: args.priority,
|
|
388
|
-
tag: args.tag,
|
|
389
|
-
query: args.query,
|
|
390
|
-
body: args.body,
|
|
391
|
-
limit: args.limit,
|
|
392
|
-
format: args.format
|
|
393
|
-
});
|
|
394
|
-
process.exit(exitCode);
|
|
395
|
-
})
|
|
396
|
-
.command('next', 'List ranked next-work candidates', (y) => y
|
|
397
|
-
.option('assignee', {
|
|
398
|
-
type: 'string',
|
|
399
|
-
description: 'Filter by assignee'
|
|
400
|
-
})
|
|
401
|
-
.option('epic', {
|
|
402
|
-
type: 'string',
|
|
403
|
-
description: 'Filter by epic'
|
|
404
|
-
})
|
|
405
|
-
.option('milestone', {
|
|
406
|
-
type: 'string',
|
|
407
|
-
description: 'Filter by milestone'
|
|
408
|
-
})
|
|
409
|
-
.option('tag', {
|
|
410
|
-
type: 'array',
|
|
411
|
-
string: true,
|
|
412
|
-
description: 'Filter by tag'
|
|
413
|
-
})
|
|
414
|
-
.option('status', {
|
|
415
|
-
type: 'array',
|
|
416
|
-
string: true,
|
|
417
|
-
choices: ['todo', 'in-progress', 'review', 'done'],
|
|
418
|
-
description: 'Filter by status'
|
|
419
|
-
})
|
|
420
|
-
.option('include-blocked', {
|
|
421
|
-
type: 'boolean',
|
|
422
|
-
default: false,
|
|
423
|
-
description: 'Include blocked and missing-dependency tasks'
|
|
424
|
-
})
|
|
425
|
-
.option('explain', {
|
|
426
|
-
type: 'boolean',
|
|
427
|
-
default: false,
|
|
428
|
-
description: 'Show all ranking reasons'
|
|
429
|
-
})
|
|
430
|
-
.option('limit', {
|
|
431
|
-
type: 'number',
|
|
432
|
-
description: 'Maximum number of candidates to show'
|
|
433
|
-
})
|
|
434
|
-
.option('format', {
|
|
435
|
-
type: 'string',
|
|
436
|
-
choices: ['text', 'json'],
|
|
437
|
-
default: 'text',
|
|
438
|
-
description: 'Output format'
|
|
439
|
-
}), async (args) => {
|
|
440
|
-
const exitCode = await (0, next_1.nextCommand)(process.cwd(), {
|
|
441
|
-
assignee: args.assignee,
|
|
442
|
-
epic: args.epic,
|
|
443
|
-
milestone: args.milestone,
|
|
444
|
-
tag: args.tag,
|
|
445
|
-
status: args.status,
|
|
446
|
-
includeBlocked: args.includeBlocked,
|
|
447
|
-
explain: args.explain,
|
|
448
|
-
limit: args.limit,
|
|
449
|
-
format: args.format
|
|
450
|
-
});
|
|
451
|
-
process.exit(exitCode);
|
|
452
|
-
})
|
|
453
|
-
.command('list [type]', 'List entities', (y) => y
|
|
454
|
-
.positional('type', {
|
|
455
|
-
describe: 'Entity type to list',
|
|
456
|
-
choices: ['tasks', 'epics', 'milestones', 'decisions'],
|
|
457
|
-
default: 'tasks'
|
|
458
|
-
})
|
|
459
|
-
.option('status', {
|
|
460
|
-
type: 'string',
|
|
461
|
-
description: 'Filter by status'
|
|
462
|
-
})
|
|
463
|
-
.option('assignee', {
|
|
464
|
-
type: 'string',
|
|
465
|
-
description: 'Filter by assignee'
|
|
466
|
-
})
|
|
467
|
-
.option('epic', {
|
|
468
|
-
type: 'string',
|
|
469
|
-
description: 'Filter by epic'
|
|
470
|
-
})
|
|
471
|
-
.option('format', {
|
|
472
|
-
type: 'string',
|
|
473
|
-
choices: ['table', 'json'],
|
|
474
|
-
default: 'table',
|
|
475
|
-
description: 'Output format'
|
|
476
|
-
}), async (args) => {
|
|
477
|
-
const exitCode = await (0, list_1.listCommand)(process.cwd(), {
|
|
478
|
-
type: args.type,
|
|
479
|
-
status: args.status,
|
|
480
|
-
assignee: args.assignee,
|
|
481
|
-
epic: args.epic,
|
|
482
|
-
format: args.format
|
|
483
|
-
});
|
|
484
|
-
process.exit(exitCode);
|
|
485
|
-
})
|
|
486
|
-
.command('show <id>', 'Show entity details', (y) => y
|
|
487
|
-
.positional('id', {
|
|
488
|
-
describe: 'Entity ID to show'
|
|
489
|
-
})
|
|
490
|
-
.option('format', {
|
|
491
|
-
type: 'string',
|
|
492
|
-
choices: ['pretty', 'json'],
|
|
493
|
-
default: 'pretty'
|
|
494
|
-
}), async (args) => {
|
|
495
|
-
const exitCode = await (0, show_1.showCommand)(process.cwd(), args.id, {
|
|
496
|
-
format: args.format
|
|
497
|
-
});
|
|
498
|
-
process.exit(exitCode);
|
|
499
|
-
})
|
|
500
|
-
.command('create <type>', 'Create new entity', (y) => y
|
|
501
|
-
.positional('type', {
|
|
502
|
-
describe: 'Entity type to create',
|
|
503
|
-
choices: ['task', 'epic', 'milestone', 'decision']
|
|
504
|
-
})
|
|
505
|
-
.option('title', {
|
|
506
|
-
alias: 't',
|
|
507
|
-
type: 'string',
|
|
508
|
-
description: 'Entity title'
|
|
509
|
-
})
|
|
510
|
-
.option('status', {
|
|
511
|
-
type: 'string',
|
|
512
|
-
description: 'Initial status'
|
|
513
|
-
})
|
|
514
|
-
.option('priority', {
|
|
515
|
-
type: 'string',
|
|
516
|
-
description: 'Priority (for tasks)'
|
|
517
|
-
})
|
|
518
|
-
.option('assignee', {
|
|
519
|
-
type: 'string',
|
|
520
|
-
description: 'Assignee'
|
|
521
|
-
})
|
|
522
|
-
.option('owner', {
|
|
523
|
-
type: 'string',
|
|
524
|
-
description: 'Owner for epics and milestones'
|
|
525
|
-
})
|
|
526
|
-
.option('description', {
|
|
527
|
-
type: 'string',
|
|
528
|
-
description: 'Description/body for epics and milestones'
|
|
529
|
-
})
|
|
530
|
-
.option('target-date', {
|
|
531
|
-
type: 'string',
|
|
532
|
-
description: 'Target date for milestones'
|
|
533
|
-
})
|
|
534
|
-
.option('dry-run', {
|
|
535
|
-
type: 'boolean',
|
|
536
|
-
default: false,
|
|
537
|
-
description: 'Preview created Markdown without writing files'
|
|
538
|
-
})
|
|
539
|
-
.option('format', {
|
|
540
|
-
type: 'string',
|
|
541
|
-
choices: ['text', 'json'],
|
|
542
|
-
default: 'text',
|
|
543
|
-
description: 'Output format'
|
|
544
|
-
}), async (args) => {
|
|
545
|
-
const exitCode = await (0, create_1.createCommand)(process.cwd(), args.type, {
|
|
546
|
-
title: args.title,
|
|
547
|
-
status: args.status,
|
|
548
|
-
priority: args.priority,
|
|
549
|
-
assignee: args.assignee,
|
|
550
|
-
owner: args.owner,
|
|
551
|
-
description: args.description,
|
|
552
|
-
targetDate: args.targetDate,
|
|
553
|
-
dryRun: args.dryRun,
|
|
554
|
-
format: args.format
|
|
555
|
-
});
|
|
556
|
-
process.exit(exitCode);
|
|
557
|
-
})
|
|
18
|
+
const cli = (0, entity_commands_1.registerEntityCommands)((0, workflow_commands_1.registerWorkflowCommands)((0, planning_commands_1.registerPlanningCommands)((0, yargs_1.default)((0, helpers_1.hideBin)(process.argv)).version(package_json_1.default.version))));
|
|
19
|
+
await cli
|
|
558
20
|
.demandCommand(1, 'You must provide a command')
|
|
559
21
|
.help()
|
|
560
22
|
.strict()
|