dotmd-cli 0.15.1 → 0.16.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 CHANGED
@@ -423,6 +423,34 @@ dotmd lint # report issues
423
423
  dotmd lint --fix # fix all issues
424
424
  ```
425
425
 
426
+ ### Manage Statuses
427
+
428
+ ```bash
429
+ dotmd statuses # table view, all types
430
+ dotmd statuses --type plan # one type
431
+ dotmd statuses --json # machine-readable
432
+
433
+ dotmd statuses add paused --type plan --like blocked --quiet # clone blocked, then quiet
434
+ dotmd statuses set archived --type plan --no-quiet # tweak a flag
435
+ dotmd statuses remove obsolete --type plan # refuses if any docs use it
436
+
437
+ dotmd statuses migrate plan # array-form → rich-form
438
+ ```
439
+
440
+ `--like <existing>` is the affordance for "kinda like X but…" — clones every
441
+ flag from another status, then user flags override. Write commands print a flag
442
+ diff and prompt for confirmation; pass `--yes` to skip the prompt or
443
+ `--dry-run` to preview without writing. Edits are atomic: the rewrite lands in
444
+ a sibling temp file, is validated by re-importing it and running
445
+ `resolveConfig`, then renamed into place — a syntax error or new warning
446
+ leaves the original untouched.
447
+
448
+ **Lifecycle-override gotcha.** If your config has both rich-form `types` and an
449
+ explicit `export const lifecycle = {...}`, the explicit lifecycle silently
450
+ overrides per-status flags at runtime. `dotmd statuses` write commands refuse
451
+ to write into that state and recommend deleting the explicit `lifecycle` block;
452
+ pass `--ignore-lifecycle-override` to write anyway.
453
+
426
454
  ### Rename
427
455
 
428
456
  ```bash
package/bin/dotmd.mjs CHANGED
@@ -59,6 +59,7 @@ Create & Export:
59
59
 
60
60
  Setup:
61
61
  init Create starter config + docs directory
62
+ statuses [list|add|set|remove|migrate] Manage per-project status taxonomy
62
63
  watch [command] Re-run a command on file changes
63
64
  completions <shell> Shell completion script (bash, zsh)
64
65
 
@@ -449,6 +450,53 @@ Options:
449
450
  --list List all glossary terms
450
451
  --json Output as JSON`,
451
452
 
453
+ statuses: `dotmd statuses — manage per-project status taxonomy
454
+
455
+ Subcommands:
456
+ list [--type <t>] [--json] Default. Table view of every status × type with all flags.
457
+ --type accepts comma-separated types.
458
+ add <name> --type <t> [--like <e>] [flags...]
459
+ Add a new status. --like <existing> clones every flag from
460
+ another status; user flags override. Inserts before the
461
+ first terminal/archive status. Refuses if name already
462
+ exists or is invalid.
463
+ set <name> --type <t> <flags...> Edit flags on an existing status. Refuses if status doesn't
464
+ exist. Flags overwrite individually.
465
+ remove <name> --type <t> Delete a status entry. Refuses if any docs use the status
466
+ (lists offenders, suggests \`dotmd migrate\`). Warns if an
467
+ explicit lifecycle export references the name.
468
+ migrate <type> One-shot conversion of array-form types.<t>.statuses to
469
+ rich form, pulling in peer staleDays/context and per-status
470
+ requiresModule from taxonomy.moduleRequiredFor.
471
+
472
+ Flags accepted by add/set:
473
+ --context <expanded|listed|counted> Briefing layout bucket
474
+ --staleDays <n|null> Stale threshold; null = never stale
475
+ --requiresModule / --no-requiresModule
476
+ --terminal / --no-terminal Closure state — excluded from active-work scope
477
+ --archive / --no-archive Auto-move to archive dir on transition
478
+ --skipStale / --no-skipStale
479
+ --skipWarnings / --no-skipWarnings
480
+ --quiet / --no-quiet Sugar for skipStale + skipWarnings (explicit overrides win)
481
+
482
+ Workflow flags:
483
+ --yes Skip the confirmation prompt
484
+ --dry-run, -n Show the diff without writing
485
+ --ignore-lifecycle-override Write even when an explicit \`lifecycle\` export
486
+ would silently mask the per-status flags
487
+
488
+ Examples:
489
+ dotmd statuses # list everything
490
+ dotmd statuses add paused --type plan --like blocked --quiet
491
+ dotmd statuses set archived --type plan --no-quiet
492
+ dotmd statuses remove obsolete --type plan
493
+ dotmd statuses migrate plan # array → rich
494
+
495
+ Lifecycle-override gotcha: if your config has both rich-form types and an explicit
496
+ \`export const lifecycle\`, the runtime ignores per-status flags. The CLI refuses
497
+ to write in that case unless you pass --ignore-lifecycle-override; the recommended
498
+ fix is to delete the explicit \`lifecycle\` block so flags take effect.`,
499
+
452
500
  bulk: `dotmd bulk archive <f1> <f2> ... — archive multiple files at once
453
501
 
454
502
  Archives each file: sets status to archived, moves to archive
@@ -569,6 +617,7 @@ async function main() {
569
617
  if (command === 'migrate') { const { runMigrate } = await import('../src/migrate.mjs'); runMigrate(restArgs, config, { dryRun }); return; }
570
618
  if (command === 'fix-refs') { const { runFixRefs } = await import('../src/fix-refs.mjs'); runFixRefs(restArgs, config, { dryRun }); return; }
571
619
  if (command === 'doctor') { const { runDoctor } = await import('../src/doctor.mjs'); runDoctor(restArgs, config, { dryRun }); return; }
620
+ if (command === 'statuses') { const { runStatuses } = await import('../src/statuses.mjs'); await runStatuses(restArgs, config, { dryRun, type: typeArg }); return; }
572
621
 
573
622
  // All remaining commands need the index + render modules
574
623
  const { buildIndex } = await import('../src/index.mjs');
@@ -819,7 +868,7 @@ async function main() {
819
868
  'focus', 'query', 'plans', 'stale', 'actionable', 'index', 'pickup', 'finish', 'status', 'archive', 'bulk', 'touch', 'doctor',
820
869
  'unblocks', 'health', 'glossary',
821
870
  'fix-refs', 'lint', 'rename', 'migrate', 'notion', 'export', 'summary',
822
- 'watch', 'diff', 'new', 'init', 'completions',
871
+ 'watch', 'diff', 'new', 'init', 'completions', 'statuses',
823
872
  ];
824
873
  const matches = allCommands
825
874
  .map(c => ({ cmd: c, dist: levenshtein(command, c) }))
@@ -103,13 +103,20 @@ export const statuses = {
103
103
  };
104
104
 
105
105
  // Lifecycle behavior — which statuses trigger special handling.
106
- // When using rich status definitions, these are derived from per-status flags.
107
- export const lifecycle = {
108
- archiveStatuses: ['archived'], // auto-move to archiveDir on transition
109
- skipStaleFor: ['archived'], // skip staleness checks
110
- skipWarningsFor: ['archived'], // skip validation warnings (summary, etc.)
111
- terminalStatuses: ['archived', 'deprecated', 'reference', 'done'], // skip current_state/next_step warnings, exclude from stats scope
112
- };
106
+ //
107
+ // IMPORTANT: only enable this block if you're using ARRAY-form types (above) or
108
+ // no `types` definition. With rich-form types, the runtime derives these from
109
+ // per-status `terminal` / `archive` / `skipStale` / `skipWarnings` / `quiet`
110
+ // flags. An explicit `lifecycle` export sitting alongside rich-form types will
111
+ // SILENTLY OVERRIDE the per-status flags `dotmd statuses` will warn you
112
+ // before writing into a config in that state.
113
+ //
114
+ // export const lifecycle = {
115
+ // archiveStatuses: ['archived'], // auto-move to archiveDir on transition
116
+ // skipStaleFor: ['archived'], // skip staleness checks
117
+ // skipWarningsFor: ['archived'], // skip validation warnings (summary, etc.)
118
+ // terminalStatuses: ['archived', 'deprecated', 'reference'], // skip current_state/next_step warnings, exclude from stats scope
119
+ // };
113
120
 
114
121
  // Taxonomy validation — set fields to null to skip validation.
115
122
  // moduleRequiredFor is derived from requiresModule when using rich status definitions.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dotmd-cli",
3
- "version": "0.15.1",
3
+ "version": "0.16.0",
4
4
  "description": "CLI for managing markdown documents with YAML frontmatter — index, query, validate, graph, export, Notion sync, AI summaries.",
5
5
  "type": "module",
6
6
  "license": "MIT",