sdtk-wiki-kit 0.1.0 → 0.1.2

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.
@@ -7,6 +7,11 @@ Usage:
7
7
  sdtk-wiki --help
8
8
  sdtk-wiki --version
9
9
  sdtk-wiki init --help
10
+ sdtk-wiki ingest --help
11
+ sdtk-wiki compile --help
12
+ sdtk-wiki query --help
13
+ sdtk-wiki discover --help
14
+ sdtk-wiki maintain --help
10
15
  sdtk-wiki atlas build --help
11
16
  sdtk-wiki atlas open --help
12
17
  sdtk-wiki atlas watch --help
@@ -16,10 +21,25 @@ Usage:
16
21
  sdtk-wiki wiki discover --help
17
22
  sdtk-wiki wiki compile --help
18
23
  sdtk-wiki ask --help
24
+ sdtk-wiki search --help
19
25
  sdtk-wiki lint --help
20
26
 
27
+ Simple personal-brain workflow:
28
+ sdtk-wiki init --no-open
29
+ sdtk-wiki ingest <source-root>
30
+ sdtk-wiki compile --mode safe [--apply]
31
+ sdtk-wiki query "<query>"
32
+ sdtk-wiki lint
33
+ sdtk-wiki discover --plan
34
+ sdtk-wiki maintain --mode safe
35
+
21
36
  R1 command model:
22
37
  init Initialize the SDTK-WIKI workspace.
38
+ ingest Run local semantic extraction without handling timestamped JSON.
39
+ compile Run safe personal-brain compile preview, optionally apply.
40
+ query Search generated personal-brain pages locally without premium Ask.
41
+ discover Write a local-only discovery plan from WIKI gap evidence.
42
+ maintain Run safe lint, discover, and compile-preview maintenance reports.
23
43
  atlas build Build graph/viewer plus local wiki pages/provenance.
24
44
  atlas open Open or serve the local graph viewer.
25
45
  atlas watch Watch markdown sources and rebuild the graph.
@@ -27,10 +47,17 @@ R1 command model:
27
47
  wiki ingest Register one local source in metadata-only raw/provenance state.
28
48
  wiki prune Write a report-only dry-run stale managed-page review.
29
49
  wiki discover Write a local-only discovery plan from WIKI gap evidence.
30
- wiki compile Write a compile dry-run preview from a local plan.
50
+ wiki compile Preview or explicitly apply local personal-brain compile plans.
31
51
  ask Ask grounded questions over the built SDTK-WIKI graph.
52
+ search Search generated personal-brain pages locally without premium Ask.
32
53
  lint Write a report-first, non-destructive wiki lint report.
33
54
 
55
+ Advanced/audit workflow:
56
+ sdtk-wiki wiki extract --source-root <source-root> --dry-run
57
+ sdtk-wiki wiki compile --plan <extract-json> --dry-run
58
+ sdtk-wiki wiki compile --plan <apply-json> --apply --yes
59
+ sdtk-wiki search "<query>"
60
+
34
61
  Workspace paths:
35
62
  .sdtk/wiki New SDTK-WIKI workspace target.
36
63
  .sdtk/wiki/graph New SDTK-WIKI graph output target.
@@ -50,15 +77,23 @@ Premium Ask:
50
77
  Requires .sdtk/wiki/graph plus local entitlement/runtime preconditions.
51
78
  Query history, discover, compile, and cleanup automation are not enabled in R1.
52
79
 
80
+ Local Search:
81
+ sdtk-wiki query Beginner-friendly local deterministic search over .sdtk/wiki/personal-brain.
82
+ sdtk-wiki search Deterministic, read-only local search over .sdtk/wiki/personal-brain.
83
+ Does not require wiki.ask entitlement and does not perform LLM/RAG behavior.
84
+
53
85
  Maintenance:
86
+ sdtk-wiki discover --plan is a top-level alias for local-only discovery planning.
87
+ sdtk-wiki maintain --mode safe runs report-first lint/discover/compile-preview checks without apply.
54
88
  sdtk-wiki wiki prune --dry-run is report-only and writes under .sdtk/wiki/reports.
55
89
  It never deletes, archives, applies, or mutates .sdtk/atlas.`);
56
90
  console.log(`
57
91
  sdtk-wiki wiki discover --plan is plan-only and writes under .sdtk/wiki/reports.
58
92
  It never fetches web sources, ingests sources, compiles pages, applies edits, prunes, or mutates .sdtk/atlas.`);
59
93
  console.log(`
60
- sdtk-wiki wiki compile --dry-run writes a compile dry-run preview under .sdtk/wiki/reports.
61
- It never applies changes, rewrites pages, mutates raw/provenance files, or mutates .sdtk/atlas.`);
94
+ sdtk-wiki wiki compile --dry-run writes a markdown preview plus JSON sidecar under .sdtk/wiki/reports.
95
+ sdtk-wiki wiki compile --apply --yes consumes only the JSON sidecar and writes create-only personal-brain pages.
96
+ It never rewrites pages, mutates raw/provenance files, or mutates .sdtk/atlas.`);
62
97
  return 0;
63
98
  }
64
99
 
@@ -13,13 +13,14 @@ function cmdLintHelp() {
13
13
  sdtk-wiki lint [--project-path <path>]
14
14
 
15
15
  Purpose:
16
- Run report-first, non-destructive lint checks over canonical .sdtk/wiki content.
16
+ Run report-first, non-destructive lint checks over canonical .sdtk/wiki content and local source-quality evidence.
17
17
 
18
18
  Output:
19
19
  .sdtk/wiki/reports/lint-report-YYYY-MM-DD.md
20
20
 
21
21
  Behavior:
22
22
  Findings are written to the report and do not auto-modify wiki or source files.
23
+ Source-quality checks report mojibake-like text, missing source URLs, weak titles, duplicate repo/source candidates, low-confidence extraction, and raw/graph/provenance coverage mismatch.
23
24
  Completed lint runs exit 0 even when findings exist.
24
25
  Missing workspace or fatal report-write failures exit non-zero.
25
26
 
@@ -0,0 +1,345 @@
1
+ "use strict";
2
+
3
+ const fs = require("fs");
4
+ const path = require("path");
5
+ const { parseFlags } = require("../lib/args");
6
+ const { CliError, ValidationError } = require("../lib/errors");
7
+ const { runWikiCompileApply, runWikiCompileDryRun } = require("../lib/wiki-compile");
8
+ const { runWikiDiscoverPlan } = require("../lib/wiki-discover");
9
+ const { runWikiExtractDryRun } = require("../lib/wiki-extract");
10
+ const { runWikiLint } = require("../lib/wiki-lint");
11
+ const { runWikiSearch } = require("../lib/wiki-search");
12
+ const { getWikiReportsPath, resolveProjectPath } = require("../lib/wiki-paths");
13
+ const { printHumanResult } = require("./search");
14
+
15
+ const INGEST_FLAG_DEFS = {
16
+ help: { type: "boolean", alias: "h" },
17
+ "project-path": { type: "string" },
18
+ "source-root": { type: "string" },
19
+ };
20
+
21
+ const COMPILE_FLAG_DEFS = {
22
+ help: { type: "boolean", alias: "h" },
23
+ "project-path": { type: "string" },
24
+ mode: { type: "string" },
25
+ apply: { type: "boolean" },
26
+ };
27
+
28
+ const QUERY_FLAG_DEFS = {
29
+ help: { type: "boolean", alias: "h" },
30
+ "project-path": { type: "string" },
31
+ json: { type: "boolean" },
32
+ limit: { type: "string" },
33
+ };
34
+
35
+ const DISCOVER_FLAG_DEFS = {
36
+ help: { type: "boolean", alias: "h" },
37
+ "project-path": { type: "string" },
38
+ plan: { type: "boolean" },
39
+ };
40
+
41
+ const MAINTAIN_FLAG_DEFS = {
42
+ help: { type: "boolean", alias: "h" },
43
+ "project-path": { type: "string" },
44
+ mode: { type: "string" },
45
+ };
46
+
47
+ function ensureProjectPath(projectPath) {
48
+ const resolved = resolveProjectPath(projectPath || process.cwd());
49
+ if (!fs.existsSync(resolved) || !fs.statSync(resolved).isDirectory()) {
50
+ throw new ValidationError(`--project-path is not a valid directory: ${resolved}`);
51
+ }
52
+ return resolved;
53
+ }
54
+
55
+ function ensureSafeMode(mode, commandName) {
56
+ const resolvedMode = mode || "safe";
57
+ if (resolvedMode !== "safe") {
58
+ throw new ValidationError(
59
+ `sdtk-wiki ${commandName} supports only --mode safe in R1. Auto mode is deferred. No project files were changed.`
60
+ );
61
+ }
62
+ return resolvedMode;
63
+ }
64
+
65
+ function findLatestReport(projectPath, pattern) {
66
+ const reportsPath = getWikiReportsPath(projectPath);
67
+ if (!fs.existsSync(reportsPath) || !fs.statSync(reportsPath).isDirectory()) {
68
+ return null;
69
+ }
70
+ const matcher = new RegExp(`^${pattern}$`);
71
+ const files = fs.readdirSync(reportsPath)
72
+ .filter((name) => matcher.test(name))
73
+ .map((name) => {
74
+ const filePath = path.join(reportsPath, name);
75
+ return { filePath, mtimeMs: fs.statSync(filePath).mtimeMs };
76
+ })
77
+ .sort((a, b) => {
78
+ if (b.mtimeMs !== a.mtimeMs) return b.mtimeMs - a.mtimeMs;
79
+ return b.filePath.localeCompare(a.filePath);
80
+ });
81
+ return files.length > 0 ? files[0] : null;
82
+ }
83
+
84
+ function latestExtraction(projectPath) {
85
+ return findLatestReport(projectPath, "semantic-extraction-dry-run-.*\\.json");
86
+ }
87
+
88
+ function latestApplyPlan(projectPath) {
89
+ return findLatestReport(projectPath, "compile-apply-plan-.*\\.json");
90
+ }
91
+
92
+ function cmdIngestHelp() {
93
+ console.log(`SDTK-WIKI Ingest
94
+
95
+ Usage:
96
+ sdtk-wiki ingest <source-root> [--project-path <path>]
97
+ sdtk-wiki ingest --source-root <path> [--project-path <path>]
98
+
99
+ Purpose:
100
+ Run local semantic extraction over a Markdown source root and write a report under .sdtk/wiki/reports.
101
+
102
+ Safety:
103
+ Local sources only.
104
+ No source mutation, personal-brain page writes, graph rebuild, web fetch, Ask, raw/provenance mutation, or .sdtk/atlas mutation.
105
+
106
+ Next:
107
+ sdtk-wiki compile --mode safe`);
108
+ return 0;
109
+ }
110
+
111
+ function cmdCompileHelp() {
112
+ console.log(`SDTK-WIKI Compile
113
+
114
+ Usage:
115
+ sdtk-wiki compile --mode safe [--project-path <path>]
116
+ sdtk-wiki compile --mode safe --apply [--project-path <path>]
117
+
118
+ Purpose:
119
+ Use the latest semantic extraction report to write a compile preview and JSON sidecar, then optionally apply the sidecar.
120
+
121
+ Safety:
122
+ Safe mode is the only R1 mode.
123
+ --apply still uses the existing JSON sidecar contract.
124
+ No delete, archive, rewrite, raw/provenance mutation, source mutation, web fetch, Ask, or .sdtk/atlas mutation.`);
125
+ return 0;
126
+ }
127
+
128
+ function cmdQueryHelp() {
129
+ console.log(`SDTK-WIKI Query
130
+
131
+ Usage:
132
+ sdtk-wiki query [--project-path <path>] [--json] [--limit <n>] "<query>"
133
+
134
+ Purpose:
135
+ Deterministically search generated personal-brain Markdown pages.
136
+
137
+ Behavior:
138
+ Local search only.
139
+ No wiki.ask entitlement, LLM/RAG runtime, query history, or project mutation.
140
+ Use sdtk-wiki ask for premium grounded Q&A when wiki.ask preconditions are available.`);
141
+ return 0;
142
+ }
143
+
144
+ function cmdDiscoverHelp() {
145
+ console.log(`SDTK-WIKI Discover
146
+
147
+ Usage:
148
+ sdtk-wiki discover --plan [--project-path <path>]
149
+
150
+ Purpose:
151
+ Write a local-only discovery plan from existing wiki gap evidence.
152
+
153
+ Safety:
154
+ Plan-only. No web fetch, source ingest, compile, apply, prune, delete, archive, query history, Ask, or .sdtk/atlas mutation.`);
155
+ return 0;
156
+ }
157
+
158
+ function cmdMaintainHelp() {
159
+ console.log(`SDTK-WIKI Maintain
160
+
161
+ Usage:
162
+ sdtk-wiki maintain --mode safe [--project-path <path>]
163
+
164
+ Purpose:
165
+ Run a report-first maintenance cycle: lint, discover plan, and compile preview when an extraction report exists.
166
+
167
+ Safety:
168
+ Safe mode only.
169
+ No apply, delete, archive, source mutation, web fetch, Ask, query history, or .sdtk/atlas mutation.`);
170
+ return 0;
171
+ }
172
+
173
+ function resolveSourceRoot(flags, positional) {
174
+ if (flags["source-root"]) return flags["source-root"];
175
+ if (positional.length === 1) return positional[0];
176
+ if (positional.length > 1) {
177
+ throw new ValidationError("sdtk-wiki ingest accepts one source root. Quote paths that contain spaces. No project files were changed.");
178
+ }
179
+ throw new ValidationError("sdtk-wiki ingest requires <source-root> or --source-root <path>. No project files were changed.");
180
+ }
181
+
182
+ function cmdIngest(args) {
183
+ const { flags, positional } = parseFlags(args || [], INGEST_FLAG_DEFS);
184
+ if (flags.help) return cmdIngestHelp();
185
+ const projectPath = ensureProjectPath(flags["project-path"]);
186
+ const result = runWikiExtractDryRun({
187
+ projectPath,
188
+ sourceRootArg: resolveSourceRoot(flags, positional),
189
+ });
190
+ const extraction = result.extraction;
191
+
192
+ console.log(`[wiki] Semantic extraction report: ${result.reportPath}`);
193
+ console.log(`[wiki] Sources scanned: ${extraction.source_counts.scanned}`);
194
+ console.log(`[wiki] Sources indexed: ${extraction.source_counts.indexed}`);
195
+ console.log(`[wiki] Tool candidates: ${extraction.tool_entities.length}`);
196
+ console.log(`[wiki] Concept candidates: ${extraction.concepts.length}`);
197
+ console.log(`[wiki] Quality findings: ${extraction.source_quality_findings.length}`);
198
+ console.log("[wiki] No source files, personal-brain pages, raw/provenance state, graph outputs, or atlas compatibility files were modified.");
199
+ console.log("[wiki] Next: sdtk-wiki compile --mode safe");
200
+ return 0;
201
+ }
202
+
203
+ function runCompileDryRunFromLatestExtraction(projectPath) {
204
+ const extraction = latestExtraction(projectPath);
205
+ if (!extraction) {
206
+ throw new ValidationError(
207
+ "No semantic extraction report found. Run \"sdtk-wiki ingest <source-root>\" first. No project files were changed."
208
+ );
209
+ }
210
+ return runWikiCompileDryRun({ projectPath, planArg: extraction.filePath });
211
+ }
212
+
213
+ function ensureApplySidecar(projectPath) {
214
+ const extraction = latestExtraction(projectPath);
215
+ const sidecar = latestApplyPlan(projectPath);
216
+ if (!sidecar && !extraction) {
217
+ throw new ValidationError(
218
+ "No compile apply sidecar or semantic extraction report found. Run \"sdtk-wiki ingest <source-root>\" first. No project files were changed."
219
+ );
220
+ }
221
+ if (!sidecar || (extraction && extraction.mtimeMs > sidecar.mtimeMs)) {
222
+ const dryRun = runCompileDryRunFromLatestExtraction(projectPath);
223
+ return {
224
+ sidecarPath: dryRun.applyPlanPath,
225
+ dryRun,
226
+ createdFreshSidecar: true,
227
+ };
228
+ }
229
+ return {
230
+ sidecarPath: sidecar.filePath,
231
+ dryRun: null,
232
+ createdFreshSidecar: false,
233
+ };
234
+ }
235
+
236
+ function cmdCompile(args) {
237
+ const { flags } = parseFlags(args || [], COMPILE_FLAG_DEFS);
238
+ if (flags.help) return cmdCompileHelp();
239
+ ensureSafeMode(flags.mode, "compile");
240
+ const projectPath = ensureProjectPath(flags["project-path"]);
241
+
242
+ if (!flags.apply) {
243
+ const result = runCompileDryRunFromLatestExtraction(projectPath);
244
+ console.log(`[wiki] Compile dry-run preview: ${result.reportPath}`);
245
+ console.log(`[wiki] Compile apply JSON sidecar: ${result.applyPlanPath}`);
246
+ console.log(`[wiki] Operations: ${result.operations.length}`);
247
+ console.log(`[wiki] Unsupported operations: ${result.unsupportedCount}`);
248
+ console.log("[wiki] No wiki pages, raw sources, provenance, source files, or atlas compatibility files were modified.");
249
+ console.log("[wiki] Next: sdtk-wiki compile --mode safe --apply");
250
+ if (result.unsupportedCount > 0) {
251
+ throw new CliError(
252
+ `unsupported_operation: ${result.unsupportedCount} operation(s) are blocked. Review the compile dry-run preview report.`,
253
+ 1
254
+ );
255
+ }
256
+ return 0;
257
+ }
258
+
259
+ const sidecar = ensureApplySidecar(projectPath);
260
+ const result = runWikiCompileApply({ projectPath, planArg: sidecar.sidecarPath });
261
+ console.log(`[wiki] Compile apply plan: ${result.planPath}`);
262
+ if (sidecar.createdFreshSidecar) {
263
+ console.log(`[wiki] Refreshed compile dry-run preview: ${sidecar.dryRun.reportPath}`);
264
+ }
265
+ console.log(`[wiki] Created files: ${result.created.length}`);
266
+ console.log(`[wiki] Unchanged files: ${result.unchanged.length}`);
267
+ console.log(`[wiki] Source-quality warnings: ${result.sourceQualityWarningCount}`);
268
+ console.log("[wiki] No source files, raw sources, provenance descriptors, or atlas compatibility files were modified.");
269
+ console.log("[wiki] Next: sdtk-wiki query \"multi-agent\"");
270
+ return 0;
271
+ }
272
+
273
+ function cmdQuery(args) {
274
+ const { flags, positional } = parseFlags(args || [], QUERY_FLAG_DEFS);
275
+ if (flags.help) return cmdQueryHelp();
276
+ const query = positional.join(" ");
277
+ const result = runWikiSearch({
278
+ projectPath: flags["project-path"],
279
+ query,
280
+ limit: flags.limit,
281
+ });
282
+ if (flags.json) {
283
+ console.log(JSON.stringify(result, null, 2));
284
+ } else {
285
+ console.log("[wiki] Query mode: local deterministic search. Premium Ask is not used.");
286
+ printHumanResult(result);
287
+ }
288
+ return 0;
289
+ }
290
+
291
+ function cmdDiscover(args) {
292
+ const { flags } = parseFlags(args || [], DISCOVER_FLAG_DEFS);
293
+ if (flags.help) return cmdDiscoverHelp();
294
+ if (!flags.plan) {
295
+ throw new ValidationError("sdtk-wiki discover requires --plan. No web/fetch/apply/auto behavior is enabled. No project files were changed.");
296
+ }
297
+ const projectPath = ensureProjectPath(flags["project-path"]);
298
+ const result = runWikiDiscoverPlan({ projectPath });
299
+
300
+ console.log(`[wiki] Discovery plan report: ${result.reportPath}`);
301
+ console.log(`[wiki] Pages scanned: ${result.pageCount}`);
302
+ console.log(`[wiki] Plan items: ${result.items.length}`);
303
+ console.log("[wiki] No sources were fetched, ingested, compiled, applied, pruned, deleted, archived, or persisted.");
304
+ return 0;
305
+ }
306
+
307
+ function cmdMaintain(args) {
308
+ const { flags } = parseFlags(args || [], MAINTAIN_FLAG_DEFS);
309
+ if (flags.help) return cmdMaintainHelp();
310
+ ensureSafeMode(flags.mode, "maintain");
311
+ const projectPath = ensureProjectPath(flags["project-path"]);
312
+
313
+ const lint = runWikiLint({ projectPath });
314
+ const discover = runWikiDiscoverPlan({ projectPath });
315
+ const extraction = latestExtraction(projectPath);
316
+ let compile = null;
317
+ if (extraction) {
318
+ compile = runWikiCompileDryRun({ projectPath, planArg: extraction.filePath });
319
+ }
320
+
321
+ console.log(`[wiki] Maintain mode: safe`);
322
+ console.log(`[wiki] Lint report: ${lint.reportPath}`);
323
+ console.log(`[wiki] Discovery plan report: ${discover.reportPath}`);
324
+ if (compile) {
325
+ console.log(`[wiki] Compile dry-run preview: ${compile.reportPath}`);
326
+ console.log(`[wiki] Compile apply JSON sidecar: ${compile.applyPlanPath}`);
327
+ } else {
328
+ console.log("[wiki] Compile preview skipped: no semantic extraction report found. Run \"sdtk-wiki ingest <source-root>\".");
329
+ }
330
+ console.log("[wiki] No apply, source mutation, web fetch, Ask, query history, delete/archive, or atlas compatibility mutation was performed.");
331
+ return 0;
332
+ }
333
+
334
+ module.exports = {
335
+ cmdCompile,
336
+ cmdCompileHelp,
337
+ cmdDiscover,
338
+ cmdDiscoverHelp,
339
+ cmdIngest,
340
+ cmdIngestHelp,
341
+ cmdMaintain,
342
+ cmdMaintainHelp,
343
+ cmdQuery,
344
+ cmdQueryHelp,
345
+ };
@@ -0,0 +1,89 @@
1
+ "use strict";
2
+
3
+ const { parseFlags } = require("../lib/args");
4
+ const { runWikiSearch } = require("../lib/wiki-search");
5
+
6
+ const SEARCH_FLAG_DEFS = {
7
+ help: { type: "boolean", alias: "h" },
8
+ "project-path": { type: "string" },
9
+ json: { type: "boolean" },
10
+ limit: { type: "string" },
11
+ };
12
+
13
+ function parseSearchFlags(args) {
14
+ return parseFlags(args || [], SEARCH_FLAG_DEFS);
15
+ }
16
+
17
+ function printSearchHelp() {
18
+ console.log(`SDTK-WIKI Local Search
19
+
20
+ Usage:
21
+ sdtk-wiki search --project-path <path> "multi-agent"
22
+ sdtk-wiki search --project-path <path> --json --limit 10 "Claude Code"
23
+
24
+ Purpose:
25
+ Deterministically search generated personal-brain Markdown pages.
26
+
27
+ Inputs:
28
+ .sdtk/wiki/personal-brain/**/*.md
29
+
30
+ Behavior:
31
+ Read-only and non-premium.
32
+ No wiki.ask entitlement is required.
33
+ No LLM, RAG, web search, query history, compile/apply, prune, or project mutation is performed.`);
34
+ return 0;
35
+ }
36
+
37
+ function printHumanResult(result) {
38
+ const lines = [
39
+ `Query: ${result.query}`,
40
+ `Search mode: ${result.searchMode}`,
41
+ `Personal brain: ${result.personalBrainPath}`,
42
+ `Scanned files: ${result.scannedFiles}`,
43
+ `Matches: ${result.totalMatches}`,
44
+ "",
45
+ ];
46
+
47
+ if (result.matches.length === 0) {
48
+ lines.push("No local personal-brain matches found.");
49
+ } else {
50
+ result.matches.forEach((match, index) => {
51
+ lines.push(`${index + 1}. ${match.path}`);
52
+ lines.push(` title: ${match.title}`);
53
+ lines.push(` score: ${match.score}`);
54
+ lines.push(` why: ${match.why}`);
55
+ lines.push(` snippet: ${match.snippet}`);
56
+ lines.push("");
57
+ });
58
+ }
59
+
60
+ lines.push("No entitlement, LLM/RAG runtime, query history, or project mutation was used.");
61
+ console.log(lines.join("\n").trimEnd());
62
+ }
63
+
64
+ function cmdSearch(args) {
65
+ const { flags, positional } = parseSearchFlags(args || []);
66
+ if (flags.help) {
67
+ return printSearchHelp();
68
+ }
69
+ const query = positional.join(" ");
70
+ const result = runWikiSearch({
71
+ projectPath: flags["project-path"],
72
+ query,
73
+ limit: flags.limit,
74
+ });
75
+
76
+ if (flags.json) {
77
+ console.log(JSON.stringify(result, null, 2));
78
+ } else {
79
+ printHumanResult(result);
80
+ }
81
+ return 0;
82
+ }
83
+
84
+ module.exports = {
85
+ cmdSearch,
86
+ parseSearchFlags,
87
+ printHumanResult,
88
+ printSearchHelp,
89
+ };