dotmd-cli 0.14.3 → 0.14.4

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
@@ -430,27 +430,78 @@ When `dotmd init` runs in a directory with existing `.md` files, it scans them a
430
430
 
431
431
  ## Configuration
432
432
 
433
- Create `dotmd.config.mjs` at your project root (or run `dotmd init`):
433
+ Create `dotmd.config.mjs` at your project root (or run `dotmd init`).
434
+
435
+ ### Rich status definitions (recommended)
436
+
437
+ Define each status as an object that co-locates all behavioral properties. Adding a new status is one line in one place — no need to update separate `lifecycle`, `staleDays`, `context`, or `taxonomy` sections.
438
+
439
+ ```js
440
+ export const root = 'docs/plans';
441
+ export const archiveDir = 'archived';
442
+
443
+ export const types = {
444
+ plan: {
445
+ statuses: {
446
+ 'active': { context: 'expanded', staleDays: 14, requiresModule: true },
447
+ 'planned': { context: 'listed', staleDays: 30, requiresModule: true },
448
+ 'blocked': { context: 'listed', staleDays: 30, skipStale: true },
449
+ 'archived': { context: 'counted', archive: true, terminal: true, skipStale: true, skipWarnings: true },
450
+ },
451
+ },
452
+ };
453
+ ```
454
+
455
+ **Status properties:**
456
+
457
+ | Property | Type | Default | Effect |
458
+ |---|---|---|---|
459
+ | `context` | `'expanded'` \| `'listed'` \| `'counted'` | `'counted'` | Display mode in `dotmd context` |
460
+ | `staleDays` | `number` \| `null` | `null` | Days before doc is stale (`null` = never) |
461
+ | `requiresModule` | `boolean` | `false` | Require `module` in frontmatter |
462
+ | `terminal` | `boolean` | `false` | Skip `current_state`/`next_step` warnings |
463
+ | `archive` | `boolean` | `false` | Auto-move to `archiveDir` on transition |
464
+ | `skipStale` | `boolean` | `false` | Exempt from stale checks |
465
+ | `skipWarnings` | `boolean` | `false` | Exempt from validation warnings |
466
+
467
+ Object key order determines display order. The config resolver derives `statuses.order`, `lifecycle.*`, `taxonomy.moduleRequiredFor`, and `context.*` from these definitions. Explicit global sections still win when provided.
468
+
469
+ ### Array form (also supported)
470
+
471
+ The traditional array form remains fully backwards compatible:
434
472
 
435
473
  ```js
436
- export const root = 'docs/plans'; // string or array of paths
437
- export const archiveDir = 'archived'; // subdirectory for archived docs
474
+ export const types = {
475
+ plan: {
476
+ statuses: ['active', 'planned', 'blocked', 'archived'],
477
+ context: { expanded: ['active'], listed: ['planned', 'blocked'], counted: ['archived'] },
478
+ staleDays: { active: 14, planned: 30, blocked: 30 },
479
+ },
480
+ };
438
481
 
482
+ // When using array form, define behavior in separate sections:
439
483
  export const statuses = {
440
- order: ['draft', 'active', 'approved', 'superseded', 'archived'],
441
- staleDays: { draft: 7, active: 14, approved: 30 },
484
+ order: ['active', 'planned', 'blocked', 'archived'],
485
+ staleDays: { active: 14, planned: 30, blocked: 30 },
442
486
  };
443
487
 
444
488
  export const lifecycle = {
445
- archiveStatuses: ['archived'], // auto-move to archiveDir
489
+ archiveStatuses: ['archived'],
446
490
  skipStaleFor: ['archived'],
447
491
  skipWarningsFor: ['archived'],
448
- terminalStatuses: ['archived', 'deprecated', 'reference', 'done'],
492
+ terminalStatuses: ['archived'],
493
+ };
494
+
495
+ export const taxonomy = {
496
+ moduleRequiredFor: ['active', 'planned', 'blocked'],
449
497
  };
498
+ ```
450
499
 
500
+ ### Other config
501
+
502
+ ```js
451
503
  export const taxonomy = {
452
504
  surfaces: ['web', 'ios', 'backend', 'api', 'platform'],
453
- moduleRequiredFor: ['active', 'ready', 'planned', 'blocked'],
454
505
  };
455
506
 
456
507
  export const referenceFields = {
@@ -465,7 +516,7 @@ export const index = {
465
516
  };
466
517
  ```
467
518
 
468
- All exports are optional. Additional options: `types`, `context`, `display`, `presets`, `templates`, `excludeDirs`, `notion`. See [`dotmd.config.example.mjs`](dotmd.config.example.mjs) for the full reference.
519
+ All exports are optional. Additional options: `context`, `display`, `presets`, `templates`, `excludeDirs`, `notion`. See [`dotmd.config.example.mjs`](dotmd.config.example.mjs) for the full reference.
469
520
 
470
521
  Config discovery walks up from cwd looking for `dotmd.config.mjs` or `.dotmd.config.mjs`.
471
522
 
@@ -13,27 +13,58 @@ export const archiveDir = 'archived';
13
13
  // Directories to skip when scanning
14
14
  export const excludeDirs = ['evidence'];
15
15
 
16
- // Document types — each type has its own status vocabulary and context layout
16
+ // Document types — each type has its own status vocabulary and context layout.
17
17
  // Defaults: plan, doc, research. Override to customize statuses per type.
18
+ //
19
+ // Statuses can be defined as an array (names only) or as an object (rich form).
20
+ // The object form co-locates all behavioral properties with each status,
21
+ // eliminating the need for separate lifecycle, staleDays, context, and taxonomy sections.
22
+
23
+ // ─── Rich status definitions (recommended) ──────────────────────────────────
24
+ // Each status is an object with optional properties:
25
+ // context: 'expanded' | 'listed' | 'counted' (default: 'counted')
26
+ // staleDays: number | null — stale threshold (default: null = never stale)
27
+ // requiresModule: boolean — require `module` frontmatter (default: false)
28
+ // terminal: boolean — skip current_state/next_step warnings (default: false)
29
+ // archive: boolean — auto-move to archiveDir on transition (default: false)
30
+ // skipStale: boolean — exempt from stale checks (default: false)
31
+ // skipWarnings: boolean — exempt from validation warnings (default: false)
32
+ //
18
33
  // export const types = {
19
34
  // plan: {
20
- // statuses: ['in-session', 'active', 'planned', 'blocked', 'done', 'archived'],
21
- // context: { expanded: ['in-session', 'active'], listed: ['planned', 'blocked'], counted: ['done', 'archived'] },
22
- // staleDays: { 'in-session': 1, active: 14, planned: 30, blocked: 30 },
35
+ // statuses: {
36
+ // 'in-session': { context: 'expanded', staleDays: 1, requiresModule: true },
37
+ // 'active': { context: 'expanded', staleDays: 14, requiresModule: true },
38
+ // 'planned': { context: 'listed', staleDays: 30, requiresModule: true },
39
+ // 'blocked': { context: 'listed', staleDays: 30, requiresModule: true, skipStale: true },
40
+ // 'done': { context: 'counted', terminal: true, skipStale: true, skipWarnings: true },
41
+ // 'archived': { context: 'counted', archive: true, terminal: true, skipStale: true, skipWarnings: true },
42
+ // },
23
43
  // },
24
44
  // doc: {
25
- // statuses: ['draft', 'active', 'review', 'reference', 'deprecated', 'archived'],
26
- // context: { expanded: ['active'], listed: ['draft', 'review'], counted: ['reference', 'deprecated', 'archived'] },
27
- // staleDays: { draft: 30, active: 14, review: 14 },
45
+ // statuses: {
46
+ // 'draft': { context: 'listed', staleDays: 30 },
47
+ // 'active': { context: 'expanded', staleDays: 14 },
48
+ // 'review': { context: 'listed', staleDays: 14 },
49
+ // 'reference': { context: 'counted', skipStale: true },
50
+ // 'deprecated': { context: 'counted', terminal: true, skipStale: true },
51
+ // 'archived': { context: 'counted', archive: true, terminal: true, skipStale: true, skipWarnings: true },
52
+ // },
28
53
  // },
29
- // research: {
30
- // statuses: ['active', 'reference', 'archived'],
31
- // context: { expanded: ['active'], listed: [], counted: ['reference', 'archived'] },
32
- // staleDays: { active: 30 },
54
+ // };
55
+
56
+ // ─── Array form (also supported) ────────────────────────────────────────────
57
+ // When using array form, define behavior in separate statuses/lifecycle/taxonomy sections.
58
+ // export const types = {
59
+ // plan: {
60
+ // statuses: ['in-session', 'active', 'planned', 'blocked', 'done', 'archived'],
61
+ // context: { expanded: ['in-session', 'active'], listed: ['planned', 'blocked'], counted: ['done', 'archived'] },
62
+ // staleDays: { 'in-session': 1, active: 14, planned: 30, blocked: 30 },
33
63
  // },
34
64
  // };
35
65
 
36
66
  // Status workflow — fallback for docs without a type field. Order determines display grouping.
67
+ // When using rich status definitions, statuses.order and staleDays are derived automatically.
37
68
  export const statuses = {
38
69
  order: ['active', 'ready', 'planned', 'research', 'blocked', 'reference', 'archived'],
39
70
  // Additional statuses valid only in specific roots (merged with order)
@@ -52,7 +83,8 @@ export const statuses = {
52
83
  },
53
84
  };
54
85
 
55
- // Lifecycle behavior — which statuses trigger special handling
86
+ // Lifecycle behavior — which statuses trigger special handling.
87
+ // When using rich status definitions, these are derived from per-status flags.
56
88
  export const lifecycle = {
57
89
  archiveStatuses: ['archived'], // auto-move to archiveDir on transition
58
90
  skipStaleFor: ['archived'], // skip staleness checks
@@ -60,7 +92,8 @@ export const lifecycle = {
60
92
  terminalStatuses: ['archived', 'deprecated', 'reference', 'done'], // skip current_state/next_step warnings, exclude from stats scope
61
93
  };
62
94
 
63
- // Taxonomy validation — set fields to null to skip validation
95
+ // Taxonomy validation — set fields to null to skip validation.
96
+ // moduleRequiredFor is derived from requiresModule when using rich status definitions.
64
97
  export const taxonomy = {
65
98
  surfaces: ['web', 'ios', 'android', 'mobile', 'full-stack', 'frontend', 'backend', 'api', 'docs', 'ops', 'platform', 'infra', 'design'],
66
99
  moduleRequiredFor: ['active', 'ready', 'planned', 'blocked'],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dotmd-cli",
3
- "version": "0.14.3",
3
+ "version": "0.14.4",
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",