diffwiki-core 0.12.0 → 0.13.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/dist/index.d.cts CHANGED
@@ -2,10 +2,10 @@ import { SearchDoc } from './bm25.cjs';
2
2
  export { RankableFields, rankDocs, tokenize } from './bm25.cjs';
3
3
  import { LogLevel, Logger } from '@logtape/logtape';
4
4
 
5
- /** Audience axis — who an article is for. Private is never published. Missing/invalid → 'public'. */
6
- type Audience = 'public' | 'private';
7
- /** Lifecycle axis — readiness. Draft is not yet published. Missing/invalid → 'published'. */
8
- type PublishStatus = 'draft' | 'published';
5
+ /** Audience axis — who an article is for. Private is never published; system is diffwiki-internal (hidden unless `showSystem`). Missing/invalid → 'public'. */
6
+ type Audience = 'public' | 'private' | 'system';
7
+ /** Lifecycle axis — readiness. Draft is unpublished; deprecated is superseded. Missing/invalid → 'published'. */
8
+ type PublishStatus = 'draft' | 'published' | 'deprecated';
9
9
  type CollectionType = 'global' | 'repo' | 'external';
10
10
  interface CollectionEntry {
11
11
  name: string;
@@ -13,6 +13,8 @@ interface CollectionEntry {
13
13
  /** Absolute path to the collection's content directory. */
14
14
  path: string;
15
15
  createdAt: string;
16
+ /** Marks a diffwiki-internal collection (e.g. `transcripts`). 'system' hides it unless `showSystem`. */
17
+ audience?: Audience;
16
18
  /** External only: stable git repo id (see `repoId`). Identity + dedupe key. */
17
19
  id?: string;
18
20
  /** External only: absolute repo root (branch/behind + open-at-root). */
@@ -29,6 +31,8 @@ interface Config {
29
31
  defaultSearch?: string;
30
32
  /** Editor command used by `diffwiki edit` (e.g. "code -w", "hx"). Falls back to $VISUAL/$EDITOR. */
31
33
  editor?: string;
34
+ /** Reveal system-audience content in search, nav, and the UI (default: false). Stored as boolean or "true". */
35
+ showSystem?: boolean;
32
36
  }
33
37
  interface Article {
34
38
  title: string;
@@ -83,6 +87,11 @@ interface ProjectCollection {
83
87
  /** Optional display order (ascending). Unset sorts after ordered ones, keeping list order. */
84
88
  order?: number;
85
89
  }
90
+ /** Optional recall/search context from `diffwiki.yaml` → `context`. */
91
+ interface ProjectContext {
92
+ /** Collection names recall/search should filter to by default. */
93
+ collections: string[];
94
+ }
86
95
  /**
87
96
  * Normalised repo-root `diffwiki.yaml`. The extended form carries `site` +
88
97
  * `collections[]`; the legacy `{ collection, path }` form is folded into a
@@ -91,6 +100,7 @@ interface ProjectCollection {
91
100
  interface ProjectConfig {
92
101
  site?: SiteConfig;
93
102
  collections: ProjectCollection[];
103
+ context?: ProjectContext;
94
104
  }
95
105
  /** A node in a collection's article tree. Branches have `children`; leaves have `slug`. */
96
106
  interface ArticleNode {
@@ -138,9 +148,12 @@ type PluginKind = 'search';
138
148
  declare const NATIVE_ENGINE = "native";
139
149
  interface QueryOptions {
140
150
  engine?: string;
141
- collection?: string;
151
+ /** Limit to a single collection name, or a set of names. Empty/undefined = all. */
152
+ collection?: string | string[];
142
153
  type?: string;
143
154
  limit?: number;
155
+ /** Reveal system-audience content (default: config `showSystem`, else false). */
156
+ showSystem?: boolean;
144
157
  }
145
158
  interface QueryHit {
146
159
  collection: string;
@@ -373,6 +386,8 @@ declare function readConfig(): Promise<Config>;
373
386
  declare function writeConfig(config: Config): Promise<void>;
374
387
  declare function setConfigValue(key: string, value: string): Promise<void>;
375
388
  declare function getConfigValue(key: string): Promise<string | undefined>;
389
+ /** Whether system-audience content should be shown (config `showSystem` set to true or "true"). */
390
+ declare function showSystemEnabled(): Promise<boolean>;
376
391
 
377
392
  declare function readRegistry(): Promise<Registry>;
378
393
  declare function writeRegistry(registry: Registry): Promise<void>;
@@ -382,6 +397,8 @@ declare function unregisterCollection(name: string): Promise<void>;
382
397
 
383
398
  /** Turn a title (or a "# Heading" line) into a filesystem-safe slug. */
384
399
  declare function slugify(input: string): string;
400
+ /** Slugify a `/`-separated path segment-by-segment, preserving the separators. */
401
+ declare function slugifyPath(input: string): string;
385
402
 
386
403
  interface ParsedArticle {
387
404
  title: string;
@@ -404,7 +421,9 @@ declare function serializeArticle(article: SerializableArticle): string;
404
421
  declare function listCollections(): Promise<CollectionEntry[]>;
405
422
  declare function findCollection(name: string): Promise<CollectionEntry | undefined>;
406
423
  declare function findCollectionById(id: string): Promise<CollectionEntry | undefined>;
407
- declare function createCollection(name: string): Promise<CollectionEntry>;
424
+ declare function createCollection(name: string, opts?: {
425
+ audience?: Audience;
426
+ }): Promise<CollectionEntry>;
408
427
  /**
409
428
  * Remove a collection from the registry. For `global` collections we own the
410
429
  * storage, so its directory is deleted too; for `repo` wikis we only deregister
@@ -490,6 +509,8 @@ declare const PROJECT_CONFIG_FILE = "diffwiki.yaml";
490
509
  * undefined when the file is absent (ENOENT); parse/other read errors propagate.
491
510
  */
492
511
  declare function readProjectConfig(dir: string): Promise<ProjectConfig | undefined>;
512
+ /** The `context.collections` list from `diffwiki.yaml`, or `[]` when absent. */
513
+ declare function readContextCollections(dir: string): Promise<string[]>;
493
514
  /**
494
515
  * Resolve `diffwiki.yaml` collections into registry-shaped CollectionEntry[] with
495
516
  * absolute paths (relative to the project root). Empty when no config / no
@@ -565,9 +586,13 @@ declare function fileTimestamps(absPath: string): Promise<FileTimestamps>;
565
586
  * In static builds, private (audience) or draft (status) articles are dropped
566
587
  * entirely (no nav row, and — since routes + per-doc JSON derive from this tree
567
588
  * — no route/JSON). */
568
- declare function toTreeNodes(coll: string, nodes: ArticleNode[]): TreeNode[];
569
- declare function buildCollections(): Promise<CollectionInfo[]>;
570
- declare function buildNavTree(): Promise<CollectionTree[]>;
589
+ declare function toTreeNodes(coll: string, nodes: ArticleNode[], showSystem?: boolean): TreeNode[];
590
+ declare function buildCollections(opts?: {
591
+ showSystem?: boolean;
592
+ }): Promise<CollectionInfo[]>;
593
+ declare function buildNavTree(opts?: {
594
+ showSystem?: boolean;
595
+ }): Promise<CollectionTree[]>;
571
596
  /**
572
597
  * Resolve a route to a rendered doc or a generated directory listing (or null).
573
598
  *
@@ -632,16 +657,7 @@ declare function resolveCollectionSelection(all: string[], sel?: CollectionSelec
632
657
  * @module
633
658
  */
634
659
 
635
- /**
636
- * Built-in JS-native search: BM25-ranked full-text search over an article's
637
- * title, body, tags, and collection name -- across every registered collection's
638
- * ABSOLUTE registry path (so in-repo wikis outside ~/.diffwiki are searched too).
639
- * No `find`/OS shelling -- cross-platform and dependency-free.
640
- *
641
- * When `term` is empty, returns all articles unranked (no score) to preserve
642
- * the "browse all" behavior.
643
- */
644
- declare function nativeSearch(term: string, collections: CollectionEntry[], collection?: string): Promise<QueryHit[]>;
660
+ declare function nativeSearch(term: string, collections: CollectionEntry[], collection?: string | string[], hideSystem?: boolean): Promise<QueryHit[]>;
645
661
  /**
646
662
  * Resolve the engine + type that `query()` would use when the caller passes no
647
663
  * explicit engine/type. Reads cached capabilities from the registry -- no spawn.
@@ -670,18 +686,6 @@ interface SearchOutcome {
670
686
  /** The captured failure message from the engine, when it errored. */
671
687
  error?: string;
672
688
  }
673
- /**
674
- * Search articles via the resolved search engine, surfacing engine failures.
675
- *
676
- * Routing precedence: explicit `opts.engine` -> `config.defaultSearch` ->
677
- * first enabled plugin -> native BM25.
678
- *
679
- * On ANY engine failure (no provider, or `handleSearch` throws) the error
680
- * message is CAPTURED, native BM25 is run as a fallback, and the outcome
681
- * reports `{ fellBackToNative: true, error }`. On success it reports
682
- * `{ fellBackToNative: false }` with the engine's hits. This lets callers
683
- * distinguish "the engine broke" from "the engine found nothing".
684
- */
685
689
  declare function search(term: string, opts?: QueryOptions): Promise<SearchOutcome>;
686
690
  /**
687
691
  * Search articles via the resolved search engine (native fallback on plugin
@@ -715,6 +719,28 @@ declare function buildSearchIndex(collection?: string): Promise<SearchDoc[]>;
715
719
  /** Run all diagnostics and return the results. */
716
720
  declare function doctor(): Promise<Diagnostic[]>;
717
721
 
722
+ type LintLevel = 'error' | 'warn';
723
+ interface LintFinding {
724
+ level: LintLevel;
725
+ rule: string;
726
+ message: string;
727
+ }
728
+ interface LintFileResult {
729
+ /** `<collection>/<relative-path>` label. */
730
+ path: string;
731
+ findings: LintFinding[];
732
+ }
733
+ interface LintResult {
734
+ files: LintFileResult[];
735
+ fileCount: number;
736
+ errorCount: number;
737
+ warnCount: number;
738
+ }
739
+ /** Stateless rules over a parsed article. */
740
+ declare function lintArticle(article: Pick<ParsedArticle, 'title' | 'tags' | 'status' | 'body'>): LintFinding[];
741
+ /** Lint every article in the resolved scope. `scope` = 'current' | 'all' | 'a,b,c'. */
742
+ declare function lintCollections(scope: string): Promise<LintResult>;
743
+
718
744
  /**
719
745
  * Centralized logging for diffwiki host code, built on LogTape.
720
746
  *
@@ -1059,4 +1085,4 @@ declare function findEnabledPlugin(kind: PluginKind, name?: string): Promise<Plu
1059
1085
  /** Find a plugin record by name (regardless of enabled state). */
1060
1086
  declare function findPluginRecord(name: string): Promise<PluginRecord | undefined>;
1061
1087
 
1062
- export { type AddExternalOptions, type Article, type ArticleContent, type ArticleNode, ArticleNotFoundError, type Audience, CollectionAlreadyAddedError, type CollectionEntry, CollectionExistsError, type CollectionGitStatus, type CollectionInfo, CollectionNotFoundError, type CollectionSelection, type CollectionSelectionResult, type CollectionTree, type CollectionType, type Config, type Diagnostic, type DiagnosticLevel, DiffwikiError, type DiffwikiLogLevel, type DocData, type EditTarget, type FileTimestamps, type GraphEdge, type GraphNode, type HomeCard, type InitOptions, type InstallOutcome, InvalidExportSelectionError, InvalidTargetError, type KnownPlugin, type LinkGraph, type ListingEntry, type LocalGraph, NATIVE_ENGINE, NoDefaultCollectionError, type NodeMeta, PROJECT_CONFIG_FILE, type PageData, type ParsedArticle, type PluginCapabilities, PluginError, type PluginEvent, type PluginHealth, type PluginKind, type PluginReadiness, type PluginRecord, type PluginRegistryFile, type ProjectCollection, type ProjectConfig, type PublishStatus, type QueryHit, type QueryOptions, REPO_CONFIG_FILE, type Registry, type RenderContext, type RenderedArticle, type RepoConfig, SearchDoc, type SearchMode, type SearchOutcome, type SearchProvider, type SerializableArticle, type SetupOutcome, type SetupStep, type SiteConfig, type SiteCopyright, type SiteHome, type TocItem, type TreeNode, type UpstreamStatus, WorktreeNotAllowedError, addExternalCollection, addTags, buildArticleTree, buildCollections, buildLinkGraph, buildNavTree, buildSearchIndex, buildSiteConfig, collectionDir, collectionGitStatus, collectionMeta, collectionsDir, configPath, createArticle, createCollection, currentBranch, deregisterPlugin, doctor, emitPluginEvent, ensureGitRepo, ensurePluginRoot, fileTimestamps, findCollection, findCollectionById, findEnabledPlugin, findPluginRecord, getConfigValue, getLogger, gitToplevel, initRepoWiki, installPlugin, invalidateLinkGraph, isLinkedWorktree, listArticleTree, listAvailablePlugins, listCollections, listEnabledPlugins, listPlugins, listSearchModes, loadSearchProvider, localGraph, nativeSearch, parseAddTarget, parseArticle, parsePathTarget, pluginsDir, pluginsRegistryPath, query, readArticle, readConfig, readPluginRegistry, readProjectConfig, readRegistry, readRepoConfig, readSiteConfig, registerCollection, registerPlugin, registryPath, removeArticle, removeCollection, removePlugin, removeTags, renderArticle, repoId, repoRemoteName, resolveCollectionSelection, resolveCwdCollection, resolveDefaultSearchMode, resolveEditTarget, resolveEditorCommand, resolveHome, resolveLogLevel, resolvePage, resolveProjectCollections, search, seedProjectHome, serializeArticle, setArticleMeta, setConfigValue, setTags, slugify, toTreeNodes, unregisterCollection, updateArticleBody, upsertPlugin, upstreamStatus, writeConfig, writePluginRegistry, writeRegistry };
1088
+ export { type AddExternalOptions, type Article, type ArticleContent, type ArticleNode, ArticleNotFoundError, type Audience, CollectionAlreadyAddedError, type CollectionEntry, CollectionExistsError, type CollectionGitStatus, type CollectionInfo, CollectionNotFoundError, type CollectionSelection, type CollectionSelectionResult, type CollectionTree, type CollectionType, type Config, type Diagnostic, type DiagnosticLevel, DiffwikiError, type DiffwikiLogLevel, type DocData, type EditTarget, type FileTimestamps, type GraphEdge, type GraphNode, type HomeCard, type InitOptions, type InstallOutcome, InvalidExportSelectionError, InvalidTargetError, type KnownPlugin, type LinkGraph, type LintFileResult, type LintFinding, type LintLevel, type LintResult, type ListingEntry, type LocalGraph, NATIVE_ENGINE, NoDefaultCollectionError, type NodeMeta, PROJECT_CONFIG_FILE, type PageData, type ParsedArticle, type PluginCapabilities, PluginError, type PluginEvent, type PluginHealth, type PluginKind, type PluginReadiness, type PluginRecord, type PluginRegistryFile, type ProjectCollection, type ProjectConfig, type ProjectContext, type PublishStatus, type QueryHit, type QueryOptions, REPO_CONFIG_FILE, type Registry, type RenderContext, type RenderedArticle, type RepoConfig, SearchDoc, type SearchMode, type SearchOutcome, type SearchProvider, type SerializableArticle, type SetupOutcome, type SetupStep, type SiteConfig, type SiteCopyright, type SiteHome, type TocItem, type TreeNode, type UpstreamStatus, WorktreeNotAllowedError, addExternalCollection, addTags, buildArticleTree, buildCollections, buildLinkGraph, buildNavTree, buildSearchIndex, buildSiteConfig, collectionDir, collectionGitStatus, collectionMeta, collectionsDir, configPath, createArticle, createCollection, currentBranch, deregisterPlugin, doctor, emitPluginEvent, ensureGitRepo, ensurePluginRoot, fileTimestamps, findCollection, findCollectionById, findEnabledPlugin, findPluginRecord, getConfigValue, getLogger, gitToplevel, initRepoWiki, installPlugin, invalidateLinkGraph, isLinkedWorktree, lintArticle, lintCollections, listArticleTree, listAvailablePlugins, listCollections, listEnabledPlugins, listPlugins, listSearchModes, loadSearchProvider, localGraph, nativeSearch, parseAddTarget, parseArticle, parsePathTarget, pluginsDir, pluginsRegistryPath, query, readArticle, readConfig, readContextCollections, readPluginRegistry, readProjectConfig, readRegistry, readRepoConfig, readSiteConfig, registerCollection, registerPlugin, registryPath, removeArticle, removeCollection, removePlugin, removeTags, renderArticle, repoId, repoRemoteName, resolveCollectionSelection, resolveCwdCollection, resolveDefaultSearchMode, resolveEditTarget, resolveEditorCommand, resolveHome, resolveLogLevel, resolvePage, resolveProjectCollections, search, seedProjectHome, serializeArticle, setArticleMeta, setConfigValue, setTags, showSystemEnabled, slugify, slugifyPath, toTreeNodes, unregisterCollection, updateArticleBody, upsertPlugin, upstreamStatus, writeConfig, writePluginRegistry, writeRegistry };
package/dist/index.d.ts CHANGED
@@ -2,10 +2,10 @@ import { SearchDoc } from './bm25.js';
2
2
  export { RankableFields, rankDocs, tokenize } from './bm25.js';
3
3
  import { LogLevel, Logger } from '@logtape/logtape';
4
4
 
5
- /** Audience axis — who an article is for. Private is never published. Missing/invalid → 'public'. */
6
- type Audience = 'public' | 'private';
7
- /** Lifecycle axis — readiness. Draft is not yet published. Missing/invalid → 'published'. */
8
- type PublishStatus = 'draft' | 'published';
5
+ /** Audience axis — who an article is for. Private is never published; system is diffwiki-internal (hidden unless `showSystem`). Missing/invalid → 'public'. */
6
+ type Audience = 'public' | 'private' | 'system';
7
+ /** Lifecycle axis — readiness. Draft is unpublished; deprecated is superseded. Missing/invalid → 'published'. */
8
+ type PublishStatus = 'draft' | 'published' | 'deprecated';
9
9
  type CollectionType = 'global' | 'repo' | 'external';
10
10
  interface CollectionEntry {
11
11
  name: string;
@@ -13,6 +13,8 @@ interface CollectionEntry {
13
13
  /** Absolute path to the collection's content directory. */
14
14
  path: string;
15
15
  createdAt: string;
16
+ /** Marks a diffwiki-internal collection (e.g. `transcripts`). 'system' hides it unless `showSystem`. */
17
+ audience?: Audience;
16
18
  /** External only: stable git repo id (see `repoId`). Identity + dedupe key. */
17
19
  id?: string;
18
20
  /** External only: absolute repo root (branch/behind + open-at-root). */
@@ -29,6 +31,8 @@ interface Config {
29
31
  defaultSearch?: string;
30
32
  /** Editor command used by `diffwiki edit` (e.g. "code -w", "hx"). Falls back to $VISUAL/$EDITOR. */
31
33
  editor?: string;
34
+ /** Reveal system-audience content in search, nav, and the UI (default: false). Stored as boolean or "true". */
35
+ showSystem?: boolean;
32
36
  }
33
37
  interface Article {
34
38
  title: string;
@@ -83,6 +87,11 @@ interface ProjectCollection {
83
87
  /** Optional display order (ascending). Unset sorts after ordered ones, keeping list order. */
84
88
  order?: number;
85
89
  }
90
+ /** Optional recall/search context from `diffwiki.yaml` → `context`. */
91
+ interface ProjectContext {
92
+ /** Collection names recall/search should filter to by default. */
93
+ collections: string[];
94
+ }
86
95
  /**
87
96
  * Normalised repo-root `diffwiki.yaml`. The extended form carries `site` +
88
97
  * `collections[]`; the legacy `{ collection, path }` form is folded into a
@@ -91,6 +100,7 @@ interface ProjectCollection {
91
100
  interface ProjectConfig {
92
101
  site?: SiteConfig;
93
102
  collections: ProjectCollection[];
103
+ context?: ProjectContext;
94
104
  }
95
105
  /** A node in a collection's article tree. Branches have `children`; leaves have `slug`. */
96
106
  interface ArticleNode {
@@ -138,9 +148,12 @@ type PluginKind = 'search';
138
148
  declare const NATIVE_ENGINE = "native";
139
149
  interface QueryOptions {
140
150
  engine?: string;
141
- collection?: string;
151
+ /** Limit to a single collection name, or a set of names. Empty/undefined = all. */
152
+ collection?: string | string[];
142
153
  type?: string;
143
154
  limit?: number;
155
+ /** Reveal system-audience content (default: config `showSystem`, else false). */
156
+ showSystem?: boolean;
144
157
  }
145
158
  interface QueryHit {
146
159
  collection: string;
@@ -373,6 +386,8 @@ declare function readConfig(): Promise<Config>;
373
386
  declare function writeConfig(config: Config): Promise<void>;
374
387
  declare function setConfigValue(key: string, value: string): Promise<void>;
375
388
  declare function getConfigValue(key: string): Promise<string | undefined>;
389
+ /** Whether system-audience content should be shown (config `showSystem` set to true or "true"). */
390
+ declare function showSystemEnabled(): Promise<boolean>;
376
391
 
377
392
  declare function readRegistry(): Promise<Registry>;
378
393
  declare function writeRegistry(registry: Registry): Promise<void>;
@@ -382,6 +397,8 @@ declare function unregisterCollection(name: string): Promise<void>;
382
397
 
383
398
  /** Turn a title (or a "# Heading" line) into a filesystem-safe slug. */
384
399
  declare function slugify(input: string): string;
400
+ /** Slugify a `/`-separated path segment-by-segment, preserving the separators. */
401
+ declare function slugifyPath(input: string): string;
385
402
 
386
403
  interface ParsedArticle {
387
404
  title: string;
@@ -404,7 +421,9 @@ declare function serializeArticle(article: SerializableArticle): string;
404
421
  declare function listCollections(): Promise<CollectionEntry[]>;
405
422
  declare function findCollection(name: string): Promise<CollectionEntry | undefined>;
406
423
  declare function findCollectionById(id: string): Promise<CollectionEntry | undefined>;
407
- declare function createCollection(name: string): Promise<CollectionEntry>;
424
+ declare function createCollection(name: string, opts?: {
425
+ audience?: Audience;
426
+ }): Promise<CollectionEntry>;
408
427
  /**
409
428
  * Remove a collection from the registry. For `global` collections we own the
410
429
  * storage, so its directory is deleted too; for `repo` wikis we only deregister
@@ -490,6 +509,8 @@ declare const PROJECT_CONFIG_FILE = "diffwiki.yaml";
490
509
  * undefined when the file is absent (ENOENT); parse/other read errors propagate.
491
510
  */
492
511
  declare function readProjectConfig(dir: string): Promise<ProjectConfig | undefined>;
512
+ /** The `context.collections` list from `diffwiki.yaml`, or `[]` when absent. */
513
+ declare function readContextCollections(dir: string): Promise<string[]>;
493
514
  /**
494
515
  * Resolve `diffwiki.yaml` collections into registry-shaped CollectionEntry[] with
495
516
  * absolute paths (relative to the project root). Empty when no config / no
@@ -565,9 +586,13 @@ declare function fileTimestamps(absPath: string): Promise<FileTimestamps>;
565
586
  * In static builds, private (audience) or draft (status) articles are dropped
566
587
  * entirely (no nav row, and — since routes + per-doc JSON derive from this tree
567
588
  * — no route/JSON). */
568
- declare function toTreeNodes(coll: string, nodes: ArticleNode[]): TreeNode[];
569
- declare function buildCollections(): Promise<CollectionInfo[]>;
570
- declare function buildNavTree(): Promise<CollectionTree[]>;
589
+ declare function toTreeNodes(coll: string, nodes: ArticleNode[], showSystem?: boolean): TreeNode[];
590
+ declare function buildCollections(opts?: {
591
+ showSystem?: boolean;
592
+ }): Promise<CollectionInfo[]>;
593
+ declare function buildNavTree(opts?: {
594
+ showSystem?: boolean;
595
+ }): Promise<CollectionTree[]>;
571
596
  /**
572
597
  * Resolve a route to a rendered doc or a generated directory listing (or null).
573
598
  *
@@ -632,16 +657,7 @@ declare function resolveCollectionSelection(all: string[], sel?: CollectionSelec
632
657
  * @module
633
658
  */
634
659
 
635
- /**
636
- * Built-in JS-native search: BM25-ranked full-text search over an article's
637
- * title, body, tags, and collection name -- across every registered collection's
638
- * ABSOLUTE registry path (so in-repo wikis outside ~/.diffwiki are searched too).
639
- * No `find`/OS shelling -- cross-platform and dependency-free.
640
- *
641
- * When `term` is empty, returns all articles unranked (no score) to preserve
642
- * the "browse all" behavior.
643
- */
644
- declare function nativeSearch(term: string, collections: CollectionEntry[], collection?: string): Promise<QueryHit[]>;
660
+ declare function nativeSearch(term: string, collections: CollectionEntry[], collection?: string | string[], hideSystem?: boolean): Promise<QueryHit[]>;
645
661
  /**
646
662
  * Resolve the engine + type that `query()` would use when the caller passes no
647
663
  * explicit engine/type. Reads cached capabilities from the registry -- no spawn.
@@ -670,18 +686,6 @@ interface SearchOutcome {
670
686
  /** The captured failure message from the engine, when it errored. */
671
687
  error?: string;
672
688
  }
673
- /**
674
- * Search articles via the resolved search engine, surfacing engine failures.
675
- *
676
- * Routing precedence: explicit `opts.engine` -> `config.defaultSearch` ->
677
- * first enabled plugin -> native BM25.
678
- *
679
- * On ANY engine failure (no provider, or `handleSearch` throws) the error
680
- * message is CAPTURED, native BM25 is run as a fallback, and the outcome
681
- * reports `{ fellBackToNative: true, error }`. On success it reports
682
- * `{ fellBackToNative: false }` with the engine's hits. This lets callers
683
- * distinguish "the engine broke" from "the engine found nothing".
684
- */
685
689
  declare function search(term: string, opts?: QueryOptions): Promise<SearchOutcome>;
686
690
  /**
687
691
  * Search articles via the resolved search engine (native fallback on plugin
@@ -715,6 +719,28 @@ declare function buildSearchIndex(collection?: string): Promise<SearchDoc[]>;
715
719
  /** Run all diagnostics and return the results. */
716
720
  declare function doctor(): Promise<Diagnostic[]>;
717
721
 
722
+ type LintLevel = 'error' | 'warn';
723
+ interface LintFinding {
724
+ level: LintLevel;
725
+ rule: string;
726
+ message: string;
727
+ }
728
+ interface LintFileResult {
729
+ /** `<collection>/<relative-path>` label. */
730
+ path: string;
731
+ findings: LintFinding[];
732
+ }
733
+ interface LintResult {
734
+ files: LintFileResult[];
735
+ fileCount: number;
736
+ errorCount: number;
737
+ warnCount: number;
738
+ }
739
+ /** Stateless rules over a parsed article. */
740
+ declare function lintArticle(article: Pick<ParsedArticle, 'title' | 'tags' | 'status' | 'body'>): LintFinding[];
741
+ /** Lint every article in the resolved scope. `scope` = 'current' | 'all' | 'a,b,c'. */
742
+ declare function lintCollections(scope: string): Promise<LintResult>;
743
+
718
744
  /**
719
745
  * Centralized logging for diffwiki host code, built on LogTape.
720
746
  *
@@ -1059,4 +1085,4 @@ declare function findEnabledPlugin(kind: PluginKind, name?: string): Promise<Plu
1059
1085
  /** Find a plugin record by name (regardless of enabled state). */
1060
1086
  declare function findPluginRecord(name: string): Promise<PluginRecord | undefined>;
1061
1087
 
1062
- export { type AddExternalOptions, type Article, type ArticleContent, type ArticleNode, ArticleNotFoundError, type Audience, CollectionAlreadyAddedError, type CollectionEntry, CollectionExistsError, type CollectionGitStatus, type CollectionInfo, CollectionNotFoundError, type CollectionSelection, type CollectionSelectionResult, type CollectionTree, type CollectionType, type Config, type Diagnostic, type DiagnosticLevel, DiffwikiError, type DiffwikiLogLevel, type DocData, type EditTarget, type FileTimestamps, type GraphEdge, type GraphNode, type HomeCard, type InitOptions, type InstallOutcome, InvalidExportSelectionError, InvalidTargetError, type KnownPlugin, type LinkGraph, type ListingEntry, type LocalGraph, NATIVE_ENGINE, NoDefaultCollectionError, type NodeMeta, PROJECT_CONFIG_FILE, type PageData, type ParsedArticle, type PluginCapabilities, PluginError, type PluginEvent, type PluginHealth, type PluginKind, type PluginReadiness, type PluginRecord, type PluginRegistryFile, type ProjectCollection, type ProjectConfig, type PublishStatus, type QueryHit, type QueryOptions, REPO_CONFIG_FILE, type Registry, type RenderContext, type RenderedArticle, type RepoConfig, SearchDoc, type SearchMode, type SearchOutcome, type SearchProvider, type SerializableArticle, type SetupOutcome, type SetupStep, type SiteConfig, type SiteCopyright, type SiteHome, type TocItem, type TreeNode, type UpstreamStatus, WorktreeNotAllowedError, addExternalCollection, addTags, buildArticleTree, buildCollections, buildLinkGraph, buildNavTree, buildSearchIndex, buildSiteConfig, collectionDir, collectionGitStatus, collectionMeta, collectionsDir, configPath, createArticle, createCollection, currentBranch, deregisterPlugin, doctor, emitPluginEvent, ensureGitRepo, ensurePluginRoot, fileTimestamps, findCollection, findCollectionById, findEnabledPlugin, findPluginRecord, getConfigValue, getLogger, gitToplevel, initRepoWiki, installPlugin, invalidateLinkGraph, isLinkedWorktree, listArticleTree, listAvailablePlugins, listCollections, listEnabledPlugins, listPlugins, listSearchModes, loadSearchProvider, localGraph, nativeSearch, parseAddTarget, parseArticle, parsePathTarget, pluginsDir, pluginsRegistryPath, query, readArticle, readConfig, readPluginRegistry, readProjectConfig, readRegistry, readRepoConfig, readSiteConfig, registerCollection, registerPlugin, registryPath, removeArticle, removeCollection, removePlugin, removeTags, renderArticle, repoId, repoRemoteName, resolveCollectionSelection, resolveCwdCollection, resolveDefaultSearchMode, resolveEditTarget, resolveEditorCommand, resolveHome, resolveLogLevel, resolvePage, resolveProjectCollections, search, seedProjectHome, serializeArticle, setArticleMeta, setConfigValue, setTags, slugify, toTreeNodes, unregisterCollection, updateArticleBody, upsertPlugin, upstreamStatus, writeConfig, writePluginRegistry, writeRegistry };
1088
+ export { type AddExternalOptions, type Article, type ArticleContent, type ArticleNode, ArticleNotFoundError, type Audience, CollectionAlreadyAddedError, type CollectionEntry, CollectionExistsError, type CollectionGitStatus, type CollectionInfo, CollectionNotFoundError, type CollectionSelection, type CollectionSelectionResult, type CollectionTree, type CollectionType, type Config, type Diagnostic, type DiagnosticLevel, DiffwikiError, type DiffwikiLogLevel, type DocData, type EditTarget, type FileTimestamps, type GraphEdge, type GraphNode, type HomeCard, type InitOptions, type InstallOutcome, InvalidExportSelectionError, InvalidTargetError, type KnownPlugin, type LinkGraph, type LintFileResult, type LintFinding, type LintLevel, type LintResult, type ListingEntry, type LocalGraph, NATIVE_ENGINE, NoDefaultCollectionError, type NodeMeta, PROJECT_CONFIG_FILE, type PageData, type ParsedArticle, type PluginCapabilities, PluginError, type PluginEvent, type PluginHealth, type PluginKind, type PluginReadiness, type PluginRecord, type PluginRegistryFile, type ProjectCollection, type ProjectConfig, type ProjectContext, type PublishStatus, type QueryHit, type QueryOptions, REPO_CONFIG_FILE, type Registry, type RenderContext, type RenderedArticle, type RepoConfig, SearchDoc, type SearchMode, type SearchOutcome, type SearchProvider, type SerializableArticle, type SetupOutcome, type SetupStep, type SiteConfig, type SiteCopyright, type SiteHome, type TocItem, type TreeNode, type UpstreamStatus, WorktreeNotAllowedError, addExternalCollection, addTags, buildArticleTree, buildCollections, buildLinkGraph, buildNavTree, buildSearchIndex, buildSiteConfig, collectionDir, collectionGitStatus, collectionMeta, collectionsDir, configPath, createArticle, createCollection, currentBranch, deregisterPlugin, doctor, emitPluginEvent, ensureGitRepo, ensurePluginRoot, fileTimestamps, findCollection, findCollectionById, findEnabledPlugin, findPluginRecord, getConfigValue, getLogger, gitToplevel, initRepoWiki, installPlugin, invalidateLinkGraph, isLinkedWorktree, lintArticle, lintCollections, listArticleTree, listAvailablePlugins, listCollections, listEnabledPlugins, listPlugins, listSearchModes, loadSearchProvider, localGraph, nativeSearch, parseAddTarget, parseArticle, parsePathTarget, pluginsDir, pluginsRegistryPath, query, readArticle, readConfig, readContextCollections, readPluginRegistry, readProjectConfig, readRegistry, readRepoConfig, readSiteConfig, registerCollection, registerPlugin, registryPath, removeArticle, removeCollection, removePlugin, removeTags, renderArticle, repoId, repoRemoteName, resolveCollectionSelection, resolveCwdCollection, resolveDefaultSearchMode, resolveEditTarget, resolveEditorCommand, resolveHome, resolveLogLevel, resolvePage, resolveProjectCollections, search, seedProjectHome, serializeArticle, setArticleMeta, setConfigValue, setTags, showSystemEnabled, slugify, slugifyPath, toTreeNodes, unregisterCollection, updateArticleBody, upsertPlugin, upstreamStatus, writeConfig, writePluginRegistry, writeRegistry };