dotmd-cli 0.24.0 → 0.25.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/bin/dotmd.mjs CHANGED
@@ -56,7 +56,7 @@ Lifecycle:
56
56
  migrate <field> <old> <new> [f...]Batch update a frontmatter field value (optional file filter)
57
57
 
58
58
  Create & Export:
59
- new <type> <name> [body] Create doc of given type (plan, doc, prompt, research)
59
+ new <type> <name> [body] Create doc of given type (plan, doc, prompt)
60
60
  index [--write] Generate/update docs.md index block
61
61
  export [--format md|html|json] Export docs as markdown, HTML, or JSON
62
62
  notion import|export|sync [db-id] Notion database integration
@@ -396,9 +396,8 @@ Use --dry-run (-n) with --write to preview without writing.`,
396
396
 
397
397
  Types and their default destinations:
398
398
  plan docs/plans/<slug>.md (build-up template: Problem → Phases → Closeout)
399
- doc docs/<slug>.md (minimal reference doc)
399
+ doc docs/<slug>.md (build-up lite: Overview → Version History → Related)
400
400
  prompt docs/prompts/<slug>.md (saved prompt to seed a future session — body required)
401
- research docs/<slug>.md (audit / investigation)
402
401
 
403
402
  \`<type>\` can be omitted; defaults to \`doc\`.
404
403
  \`<name>\` is slugified for the filename.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dotmd-cli",
3
- "version": "0.24.0",
3
+ "version": "0.25.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",
@@ -119,7 +119,6 @@ function generateDocsCommand(config) {
119
119
  lines.push('- `dotmd new plan <name>` — scaffold new plan');
120
120
  lines.push('- `dotmd new doc <name>` — scaffold reference doc');
121
121
  lines.push('- `dotmd new prompt <name> "<body>"` — save a resume-prompt');
122
- lines.push('- `dotmd new research <name>` — scaffold an audit/investigation');
123
122
  lines.push('- `dotmd status <file> <status>` — transition status');
124
123
  lines.push('- `dotmd archive <file>` — archive with auto ref-fixing');
125
124
  lines.push('- `dotmd bulk archive <files>` — archive multiple at once');
package/src/config.mjs CHANGED
@@ -35,11 +35,6 @@ const DEFAULTS = {
35
35
  context: { expanded: ['active'], listed: ['draft', 'review'], counted: ['reference', 'deprecated', 'archived'] },
36
36
  staleDays: { draft: 30, active: 14, review: 14 },
37
37
  },
38
- research: {
39
- statuses: ['active', 'reference', 'archived'],
40
- context: { expanded: ['active'], listed: [], counted: ['reference', 'archived'] },
41
- staleDays: { active: 30 },
42
- },
43
38
  prompt: {
44
39
  statuses: ['pending', 'claimed', 'archived'],
45
40
  context: { expanded: ['pending'], listed: [], counted: ['claimed', 'archived'] },
package/src/new.mjs CHANGED
@@ -10,10 +10,36 @@ const pkg = JSON.parse(readFileSync(path.join(__dirname, '..', 'package.json'),
10
10
 
11
11
  const BUILTIN_TEMPLATES = {
12
12
  doc: {
13
- description: 'Reference doc, design note, glossary entry, etc.',
13
+ description: 'Reference doc, design note, module overview — build-up shape lite',
14
14
  defaultStatus: 'active',
15
- frontmatter: (s, d) => `type: doc\nstatus: ${s}\ncreated: ${d}\nupdated: ${d}`,
16
- body: (t) => `\n# ${t}\n`,
15
+ frontmatter: (s, d) => [
16
+ 'type: doc',
17
+ `status: ${s}`,
18
+ `created: ${d}`,
19
+ `updated: ${d}`,
20
+ 'modules: []',
21
+ 'surfaces: []',
22
+ 'domain:',
23
+ 'audience: internal',
24
+ 'related_plans: []',
25
+ 'related_docs: []',
26
+ ].join('\n'),
27
+ body: (t, ctx) => `
28
+ # ${t}
29
+
30
+ > One-line summary of what this doc covers.
31
+
32
+ ## Overview
33
+
34
+
35
+
36
+ ## Version History
37
+
38
+ - **${ctx?.today ?? ''}** Created.
39
+
40
+ ## Related Documentation
41
+
42
+ `,
17
43
  },
18
44
  plan: {
19
45
  description: 'Execution plan — build-up shape (Problem → Phases → Closeout) with phase status markers and Version History',
@@ -95,22 +121,6 @@ Status markers (put in heading text):
95
121
  <!-- Filled on archive: what shipped, key commits, deferrals dispositioned. -->
96
122
  `,
97
123
  },
98
- research: {
99
- description: 'Codebase audit or research investigation',
100
- defaultStatus: 'active',
101
- frontmatter: (s, d) => [
102
- 'type: research',
103
- `status: ${s}`,
104
- `created: ${d}`,
105
- `updated: ${d}`,
106
- `audited: ${d}`,
107
- 'audit_level: pass1',
108
- 'module:',
109
- 'source_of_truth: code',
110
- 'supports_plans: []',
111
- ].join('\n'),
112
- body: (t) => `\n# ${t}\n\n## Scope\n\n\n\n## Findings\n\n\n\n## Recommendations\n\n\n`,
113
- },
114
124
  prompt: {
115
125
  description: 'Saved prompt to seed a future Claude session — body is required',
116
126
  dir: 'prompts',
package/src/query.mjs CHANGED
@@ -104,6 +104,7 @@ export function parseQueryArgs(argv) {
104
104
  stale: false, hasNextStep: false, hasBlockers: false,
105
105
  checklistOpen: false, json: false, git: false,
106
106
  summarize: false, summarizeLimit: 5, model: undefined,
107
+ positionalTerms: [],
107
108
  };
108
109
 
109
110
  for (let i = 0; i < argv.length; i += 1) {
@@ -135,6 +136,14 @@ export function parseQueryArgs(argv) {
135
136
  if (arg === '--summarize') { filters.summarize = true; continue; }
136
137
  if (arg === '--summarize-limit' && next) { filters.summarizeLimit = Number.parseInt(next, 10) || 5; i += 1; continue; }
137
138
  if (arg === '--model' && next) { filters.model = next; i += 1; continue; }
139
+
140
+ // Positional terms: anything else that's not a flag becomes a substring
141
+ // filter token (AND-matched against slug + title). Lets users do:
142
+ // dotmd plans rls → matches rls-platform-rows, rls-location-anchored
143
+ // dotmd plans pii redesign → AND match: pii-data-model-redesign
144
+ if (typeof arg === 'string' && !arg.startsWith('-')) {
145
+ filters.positionalTerms.push(arg.toLowerCase());
146
+ }
138
147
  }
139
148
 
140
149
  return filters;
@@ -160,6 +169,14 @@ export function filterDocs(docs, filters, config) {
160
169
  result = result.filter(d => [d.title, d.summary, d.currentState, d.nextStep, d.path, ...(d.blockers ?? [])].filter(Boolean).join(' ').toLowerCase().includes(needle));
161
170
  }
162
171
 
172
+ // Positional substring filter: AND match against slug + title.
173
+ if (filters.positionalTerms?.length) {
174
+ result = result.filter(d => {
175
+ const haystack = [d.path, d.title].filter(Boolean).join(' ').toLowerCase();
176
+ return filters.positionalTerms.every(term => haystack.includes(term));
177
+ });
178
+ }
179
+
163
180
  if (filters.owner) { const n = filters.owner.toLowerCase(); result = result.filter(d => (d.owner ?? '').toLowerCase().includes(n)); }
164
181
  if (filters.surface) { const n = filters.surface.toLowerCase(); result = result.filter(d => (d.surfaces ?? []).some(s => s.toLowerCase() === n)); }
165
182
  if (filters.module) { const n = filters.module.toLowerCase(); result = result.filter(d => (d.modules ?? []).some(m => m.toLowerCase() === n)); }