dotmd-cli 0.24.0 → 0.24.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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/query.mjs +17 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dotmd-cli",
3
- "version": "0.24.0",
3
+ "version": "0.24.1",
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",
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)); }