ws-search

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Wiki Search

Wiki 搜索

Find content in the user's wiki and answer from what's stored. Cite pages so the user can jump to them. Report gaps explicitly when the wiki doesn't cover the topic — never pad the answer with knowledge the wiki doesn't hold.
<!-- ws:core -->
在用户的 wiki 中查找内容,并仅依据已存储的信息回答。引用页面,方便用户跳转。明确报告 wiki 未涵盖的缺口——切勿用 wiki 中不存在的知识填充答案。
<!-- ws:core -->

The wiki model

wiki 模型

A wiki is a folder whose
index.md
carries a
## Spaces
heading.
## Spaces
is the navigation contract: every space directly inside is listed there as
- [label](path/index.md) — description
, and tools traverse only what it lists. Spaces nest recursively; each space is itself a wiki one level down. Plain folders (no
index.md
) just group files. The markdown dialect is Obsidian — wikilinks, frontmatter, callouts, embeds; the companion
obsidian-markdown
and
obsidian-bases
skills cover the syntax.
一个 wiki 是一个文件夹,其
index.md
带有
## Spaces
标题。
## Spaces
是导航契约:其中直接包含的每个 space 都在此处列为
- [label](path/index.md) — description
,工具也只能遍历其中列出的 space。space 可以递归嵌套;每个 space 本身就是下一层的 wiki。普通文件夹(没有
index.md
)仅用于归组文件。Markdown 方言是 Obsidian——支持 wikilinks、frontmatter、callouts、embeds;配套的
obsidian-markdown
和
obsidian-bases
skill 涵盖这些语法。

Resolving the wiki

解析 wiki

Resolution order: an explicit path from the user → the nearest CWD-ancestor folder that is a wiki, or carries a
.wiki-spaces/
folder that is one (a folder's own space) → the
wiki
key in
~/.config/wiki-spaces/config
. The user's words override the mechanics: "my wiki" means the configured one even when CWD sits inside another wiki (a company repo, say). When a CWD wiki and a different configured wiki both exist, announce which root you resolved; ask once if intent is ambiguous. Never silently operate on the wrong wiki.
解析顺序:用户给出的显式路径 → 最近的 CWD 祖先文件夹,该文件夹要么本身是 wiki,要么带有
.wiki-spaces/
文件夹而因此属于一个 wiki(即该文件夹自身的 space)→
~/.config/wiki-spaces/config
中的
wiki
键。
用户用词优先于上述机制:即使用户的 CWD 位于另一个 wiki(例如公司 repo)中,“我的 wiki”也指已配置的 wiki。当 CWD wiki 与另一个已配置 wiki 同时存在时,声明解析出的 root(根目录);如果意图不明确,询问一次。绝不能在未说明的情况下操作错误的 wiki。

The bundled script

内置 script

scripts/ws.py
sits next to this SKILL.md — stdlib python3 (3.9+), zero dependencies, read-only. It parses the contract, never the content: structure — traversal, scope, caps, drift — is the script's side; reading and judging meaning is yours. Invoke it by absolute path (your working directory is usually elsewhere):
  • python3 <skill-dir>/scripts/ws.py list --wiki <root>
    — spaces reachable via the
    ## Spaces
    contract, each with its entry description (
    --external
    to cross mounts).
  • … files --wiki <root>
    — markdown files reachable via the contract.
  • … grep <pattern> [-i] [-F] --wiki <root>
    — regex line search over those files,
    -F
    for a literal string (a name carrying metacharacters sweeps exact); prints
    rel:line: text
    , exits 1 on no match. The sweep primitive: a link worklist, a tag inventory, an escaping-reference check are each a pattern plus your judgment on the hits.
  • … check-size <target> [--stdin] --wiki <root>
    — cap verdict for a file; pipe planned content with
    --stdin
    to check before writing.
  • … audit --wiki <root>
    — contract drift, entries crossing a space boundary, over-cap or unreadable files, unhealthy mounts. Findings name their repair where one is safe to name (a
    missing entry
    prints the exact line to add); apply repairs as ordinary edits and re-run the audit to verify — the script never writes.
Trust the script's output over re-deriving structure by hand. Stdout is data; stderr carries the resolved root (
audit
prints it as its stdout header instead) and
note:
advisories naming whatever a walk skipped, the enclosing wiki when the root is nested inside one, and the configured wiki when the root is another — relay them when they could change the answer.
scripts/ws.py
位于本
SKILL.md
旁边——使用标准库 python3(3.9+),零依赖,只读。它只解析契约,从不解析内容:结构——遍历、scope、cap、drift——由脚本处理;读取内容和判断含义由你负责。应按绝对路径调用(你的工作目录通常在其他位置):
  • python3 <skill-dir>/scripts/ws.py list --wiki <root>
    ——列出通过
    ## Spaces
    契约可访问的 space,以及每个 space 的条目描述(
    --external
    可跨越 mount)。
  • … files --wiki <root>
    ——列出通过契约可访问的 Markdown 文件。
  • … grep <pattern> [-i] [-F] --wiki <root>
    ——在这些文件中进行正则行搜索;
    -F
    用于字面字符串(名称含元字符时,使用它进行精确扫查)。输出格式为
    rel:line: text
    ,无匹配时以状态码 1 退出。批量扫描的基元:链接工作清单、标签清单和转义引用检查,每项都由一个 pattern 加上你对命中项的判断完成。
  • … check-size <target> [--stdin] --wiki <root>
    ——判断文件是否符合 cap;可通过
    --stdin
    管道传入计划写入的内容,在写入前进行检查。
  • … audit --wiki <root>
    ——检查契约漂移、跨越 space 边界的条目、超 cap 或无法读取的文件,以及状态异常的 mount。发现问题时,只要能够安全确定修复方式,就应指出具体修复方法(例如
    missing entry
    会打印需要添加的确切行);将修复作为普通编辑应用,然后重新运行 audit 进行验证——script 本身绝不写入。
应信任 script 的输出,而不是手工重新推导结构。stdout 是数据;stderr 携带解析后的 root(
audit
则将其打印为 stdout 标题),并包含
note:
提示,说明遍历跳过了什么、root 嵌套在外层 wiki 中时的外层 wiki,以及 root 为另一个 wiki 时已配置的 wiki——如果这些信息可能改变答案,应予以转达。

Trust scope and size discipline

trust scope 与大小约束

Owned vs external is relative to the resolved root: anything under a folder named
shared/
(at any depth), a git submodule, or a symlink into either is external; a symlink to a folder outside the tree answers to where it sits, like a clone. Reads cross owned spaces by default and enter external ones only when the user explicitly asks. Writes stay inside the targeted space; any other space — owned or external — is written only on explicit instruction.
Caps are UTF-8 bytes including frontmatter, keyed by basename:
index.md
5000,
log.md
and
hot.md
100000, any other
*.md
15000.
  • Caps belong to the user: a wiki that wants different ones sets them in
    _meta/limits.md
    , and
    check-size
    reads them.
  • Check caps with
    check-size
    : pipe the planned content via
    --stdin
    before every write, new page or edit — a write that shrinks an over-cap file reports
    ok
    , progress, so repairs converge; a file checked on disk answers to the cap alone.
  • An overflow is a signal about shape, not just size: distill the page, reshape the space, or promote a page that has grown into one — never truncate, never raise the cap.
  • The exception is
    log.md
    : an over-cap log rolls — move it whole to
    _archives/log-<YYYYMMDD>.md
    and start a fresh one — so the history archives, never shrinks.
Conventions are opt-in per wiki. Read the markers present at the scope root (the space the user targeted, else the resolved root) —
log.md
,
_meta/taxonomy.md
,
_meta/limits.md
,
_meta/ignore.md
, frontmatter on pages,
_template.md
,
hot.md
,
.git
— and degrade gracefully when one is absent. If
log.md
exists, append one line per operation:
sh
printf '%s %s\n' "$(date -u +%Y-%m-%dT%H:%M:%SZ)" '<OP> <details>' >> <scope-root>/log.md
<!-- /ws:core -->
owned 与 external 是相对于解析后的 root 而言:
shared/
文件夹(任意深度)下的任何内容、git submodule,或指向二者之一的 symlink,都属于 external;指向树外文件夹的 symlink 归属于其实际所在位置,就像 clone 一样。默认情况下,读取可跨 owned space;仅在用户明确要求时才进入 external space。写入仅限于目标 space;任何其他 space——无论 owned 还是 external——只有得到明确指示才能写入。
cap 以包含 frontmatter 在内的 UTF-8 字节数计算,并按 basename 确定:
index.md
为 5000,
log.md
和
hot.md
为 100000,其他所有
*.md
为 15000。
  • cap 属于用户:某个 wiki 如需不同的 cap,可在
    _meta/limits.md
    中设置,
    check-size
    会读取这些值。
  • 使用
    check-size
    检查 cap:每次写入、新建页面或编辑之前,都应通过
    --stdin
    管道传入计划写入的内容。如果一次写入使原本超 cap 的文件缩小,则会报告
    ok
    ,从而让修复逐步收敛;检查磁盘上的文件时,仅依据 cap 给出结论。
  • 超限不仅是大小信号,也关乎结构形态:应提炼页面、重构 space,或将已经膨胀为完整 space 的页面提升为 space——绝不截断,也绝不提高 cap。
  • log.md
    是例外:超 cap 的日志会滚动归档——将整个文件移动到
    _archives/log-<YYYYMMDD>.md
    ,然后新建一个日志——因此历史记录会被归档,而不会缩减。
约定按 wiki 选择启用。读取目标 scope root(用户指定的 space,否则为解析后的 root)中存在的标记——
log.md
、
_meta/taxonomy.md
、
_meta/limits.md
、
_meta/ignore.md
、页面上的 frontmatter、
_template.md
、
hot.md
、
.git
——如果缺少其中某项,则优雅降级。如果存在
log.md
,每次操作追加一行:
sh
printf '%s %s\n' "$(date -u +%Y-%m-%dT%H:%M:%SZ)" '<OP> <details>' >> <scope-root>/log.md
<!-- /ws:core -->

Procedure

操作步骤

  1. Resolve the wiki (core block above). Announce the root when it came from CWD or could be ambiguous. Standing in a folder's own space, search here for what concerns the folder, and the configured wiki the script notes when the question reaches past it. No wiki anywhere → say so and offer to set one up via
    ws-update
    .
  2. Map the terrain. Run
    list
    for the space shape and
    files
    for the page inventory. Both are cheap; run them before any content search.
    • On a large wiki, slice the inventory rather than re-rooting it:
      files
      prints paths grouped by space, so read just the candidate spaces' slices — one walk, the root's trust scope and
      _meta/
      governing throughout.
    • Never re-root a search. A space taken as its own
      --wiki
      answers to its own fences — a mount the root walk calls external can read as owned there; the script notes the enclosing wiki when you do. Re-rooting is the stance for judging a space standalone (
      ws-update
      's share pre-flight), not for searching.
    • External mounts stay out unless the user asked — the stderr
      note:
      lines name what was skipped and which spaces are unreachable; when a skipped or unreachable space could hold the answer, say so and offer to cross or repair it.
  3. Pick the depth. "Just check", "do I have anything on X", or an agent pre-research probe → quick lookup: rank candidates structurally (step 4), read nothing, answer from names/summaries and say so. A real question → deep query: continue through step 6.
  4. Rank candidates structurally. Match the query against space labels and descriptions (
    ## Spaces
    entries), file names, and path segments. When frontmatter is in use,
    summary
    ,
    aliases
    , and
    tags
    rank pages without reading bodies —
    grep '^(tags|aliases|summary):' --wiki <root>
    sweeps that inventory in one call.
  5. Search content when structure alone doesn't settle it, cheapest first:
    1. A markdown-aware search backend when available (e.g. the qmd MCP — BM25 + semantic over markdown); its index knows nothing of trust scope — drop hits the root
      files
      walk wouldn't list.
    2. … grep '<term>' -i --wiki <root>
      — the universal fallback, always bundled; searches exactly the trust-scoped page set (no
      shared/
      , submodules, or
      _archives/
      ),
      --external
      only when the user asked.
  6. Read the top hits fully. Pages are cap-bounded, so whole files are affordable. Prefer 2–4 full pages over a dozen snippets.
  7. Answer from the wiki only. Cite every claim's page with a wikilink (
    [[path/to/page]]
    ). Carry over
    %%inferred%%
    /
    %%ambiguous%%
    provenance markers when the wiki uses them. Name what the wiki lacks as a gap, then offer to research and capture it via
    ws-update
    .
  8. Log one
    SEARCH
    line per the core block when
    log.md
    exists.
  1. 解析 wiki(见上方 core 块)。当 root 来自 CWD 或可能存在歧义时,声明该 root。若当前位于某个文件夹自身的 space,先在此搜索与该文件夹有关的内容;当问题延伸至当前范围之外时,再搜索 script 提示的已配置 wiki。若任何位置都没有 wiki,说明情况,并通过
    ws-update
    提议创建一个。
  2. 梳理结构。 运行
    list
    了解 space 结构,运行
    files
    获取页面清单。两者成本都很低;应在任何内容搜索之前运行。
    • 在大型 wiki 上,应对清单进行切分,而不是重新设 root:
      files
      会按 space 对路径分组,因此只需读取候选 space 对应的片段——只进行一次遍历,整个过程始终遵循 root 的 trust scope 和
      _meta/
      。
    • 搜索时绝不重新设 root。将某个 space 作为自己的
      --wiki
      时,它遵循自己的边界——root 遍历视为 external 的 mount,在那里可能被视为 owned;执行时 script 会提示 enclosing wiki。重新设 root 用于独立评判某个 space(
      ws-update
      的 share 预检),而不是用于搜索。
    • 除非用户明确要求,否则不要进入 external mount——stderr 中的
      note:
      行会指出被跳过或无法访问的 space;如果其中某个 space 可能包含答案,应说明情况,并提议跨越访问或修复它。
  3. 选择查询深度。 “只需查一下”“我对 X 有任何资料吗”,或 agent 预研探查 → 快速查询:按结构对候选项排序(步骤 4),不读取正文,根据名称或摘要作答,并说明这一点。真正的问题 → 深度查询:继续执行步骤 6。
  4. 按结构对候选项排序。 将查询与 space 标签及描述(
    ## Spaces
    条目)、文件名和路径片段进行匹配。使用 frontmatter 时,
    summary
    、
    aliases
    和
    tags
    可在不读取正文的情况下为页面排序——
    grep '^(tags|aliases|summary):' --wiki <root>
    一次调用即可完成整个清单的检索。
  5. 仅当结构无法确定时搜索内容,并优先采用成本最低的方式:
    1. 可用时采用 Markdown 感知搜索后端(例如 qmd MCP——对 markdown 执行 BM25 + semantic 搜索);其索引不了解 trust scope——丢弃 root 的
      files
      遍历不会列出的命中项。
    2. … grep '<term>' -i --wiki <root>
      ——通用回退方案,始终内置;只搜索 trust scope 内的页面集合(不包括
      shared/
      、submodule 或
      _archives/
      ),仅当用户明确要求时才使用
      --external
      。
  6. 完整读取最匹配的页面。 页面受 cap 限制,因此完整读取的成本可以接受。优先完整读取 2–4 个页面,而不是查看十几个片段。
  7. 仅依据 wiki 回答。 使用 wikilink(
    [[path/to/page]]
    )为每一项结论引用对应页面。如果 wiki 使用
    %%inferred%%
    /
    %%ambiguous%%
    provenance marker,则原样保留。明确指出 wiki 缺少哪些内容,然后提议通过
    ws-update
    研究并收录。
  8. 记录日志。 如果存在
    log.md
    ,按照 core 块的要求为每次搜索追加一行
    SEARCH
    。

Output

输出

From your wiki (<root>):
- <finding> — [[page]]
- <finding> — [[page]]
Gaps: <topics the wiki doesn't cover, or "none">
来自你的 wiki(<root>):
- <结论> — [[page]]
- <结论> — [[page]]
缺口:<wiki 未涵盖的主题,或“无”>