@hevmind/ask 0.1.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.
@@ -0,0 +1,164 @@
1
+ ---
2
+ name: build-digest
3
+ description: >-
4
+ Build the @hevmind/ask ask digest (.hev-ask/digest.json) for an Astro docs site
5
+ using your Claude Code subscription instead of an ANTHROPIC_API_KEY. Use when
6
+ the user asks to build, rebuild, or refresh the hev ask digest, knowledge
7
+ graph, KG, or search index, or after docs content changes. Runs `ask digest
8
+ corpus --shards-dir`, distils each shard in a fresh context, and runs
9
+ `ask digest assemble --input-dir`.
10
+ ---
11
+
12
+ # Build the hev ask digest
13
+
14
+ `@hevmind/ask` searches an Astro docs site. Its agentic loop, keyword ranking, and
15
+ suggested questions are powered by a committed ask digest at
16
+ `.hev-ask/digest.json`. Only the **distillation** needs a model — the node
17
+ structure, verbatim facts, overview map, and content hash are computed
18
+ deterministically by the CLI. This skill performs that distillation here, in
19
+ the user's subscription, so it costs **no API tokens on their own key**.
20
+
21
+ The corpus is split into **shards** (~200KB of text each, along slug-prefix
22
+ boundaries) and each shard is distilled in its own fresh context. Corpus size
23
+ is therefore never a context-limit problem — a bigger site just means more
24
+ shards. All state lives on disk in `.hev-ask/shards/`, so the build can be
25
+ stopped, resumed, and incrementally refreshed: after content edits, only the
26
+ shards whose content changed need re-distilling.
27
+
28
+ Run every command from the **site root** (the directory whose `astro.config.*`
29
+ registers `hevAsk()`). Prefer `pnpm exec ask digest …`; fall back to
30
+ `npx -p @hevmind/ask ask digest …` if pnpm isn't used. Pass the same content flags
31
+ the site's integration uses if they differ from the defaults (`--collection`,
32
+ `--base-path`, `--chunk-heading-depth`, `--content-glob`, `--digest-path`);
33
+ they must match across `corpus` and `assemble`.
34
+
35
+ **Never read a shard input file into the orchestrating context** (they hold
36
+ the full corpus text). The orchestrator works only from command output,
37
+ `manifest.json`, and `status`; shard contents are read by the per-shard
38
+ distillation agents.
39
+
40
+ ## Steps
41
+
42
+ 1. **Shard the corpus.**
43
+
44
+ ```sh
45
+ pnpm exec ask digest corpus --shards-dir .hev-ask/shards
46
+ ```
47
+
48
+ Deterministic and keyless. Writes one `input-<shard-id>.json` per shard
49
+ plus `manifest.json`, and reports `(N sections, M shards, P pending,
50
+ up-to-date|needs-rebuild)`. Re-running after content edits is safe and is
51
+ the refresh mechanism: unchanged shards keep their distillations; changed
52
+ ones are marked pending again.
53
+
54
+ 2. **Check state.** If the corpus reported `up-to-date` AND `0 pending`, the
55
+ committed digest already matches the content — **stop here** and tell the
56
+ user nothing needs rebuilding. Otherwise:
57
+
58
+ ```sh
59
+ pnpm exec ask digest status --shards-dir .hev-ask/shards
60
+ ```
61
+
62
+ lists which shards are `pending` or `stale` (distilled against older
63
+ content). Both need distilling.
64
+
65
+ 3. **Distil each pending/stale shard in a fresh context.** Spawn one agent per
66
+ shard (run a few in parallel; don't read shard contents yourself). Each
67
+ agent gets this prompt, with `<id>` filled in:
68
+
69
+ > Read ONLY `.hev-ask/shards/input-<id>.json` (from the site root). It has
70
+ > `shardId`, `shardHash`, and a `sections` array of `{ id, url, title,
71
+ > text }`. Write `.hev-ask/shards/distill-<id>.json` with exactly this
72
+ > shape:
73
+ >
74
+ > ```json
75
+ > {
76
+ > "shardHash": "<copy the shardHash from the input file verbatim>",
77
+ > "notes": "5-10 lines: what this shard covers, its key concepts, and how users talk about them.",
78
+ > "glossary": [
79
+ > { "term": "ask digest", "aliases": ["digest", "kg"], "definition": "One-line definition." }
80
+ > ],
81
+ > "summaries": [
82
+ > { "id": "<exact section id from sections>", "summary": "1-3 sentence distillation." }
83
+ > ]
84
+ > }
85
+ > ```
86
+ >
87
+ > Rules:
88
+ > - Emit **one `summaries` entry for every `id`** in `sections` — no more,
89
+ > no fewer. Use the exact id strings.
90
+ > - Summaries are what the search agent reasons from: faithful,
91
+ > self-contained, 1-3 sentences. **Paraphrase prose, but never restate
92
+ > code, flags, commands, or exact identifiers** — those are extracted
93
+ > verbatim by the CLI and would only drift if you retyped them.
94
+ > - `glossary`: at most the ~10 terms from this shard a real user would
95
+ > type (aliases like `k8s` for `kubernetes`); one-line definitions. The
96
+ > CLI dedupes and caps the merged glossary.
97
+ > - `notes` is NOT user-facing — it feeds a later site-wide synthesis pass.
98
+ > - Your final message: just the shard id and how many summaries you wrote.
99
+
100
+ If the run is interrupted, just re-run from step 1 — disk state is the
101
+ source of truth and `status` shows what's left.
102
+
103
+ 4. **Synthesize the global context.** Once every shard is distilled, extract
104
+ only the `notes` fields (small) — never the full distill files:
105
+
106
+ ```sh
107
+ python3 -c "import json,glob; [print('##', f.split('distill-')[1].removesuffix('.json'), '\n' + json.load(open(f)).get('notes','')) for f in sorted(glob.glob('.hev-ask/shards/distill-*.json'))]"
108
+ ```
109
+
110
+ From those notes, write `.hev-ask/shards/global.json`:
111
+
112
+ ```json
113
+ {
114
+ "context": "Compact markdown orientation: what the product/site is, its core concepts and feature areas, and how users talk about them.",
115
+ "suggestions": [
116
+ "A natural question a reader might type that these docs answer."
117
+ ],
118
+ "glossary": []
119
+ }
120
+ ```
121
+
122
+ `suggestions`: 3-5 questions phrased the way a user would ask them, each
123
+ genuinely answerable from these docs (they show in the overlay on open).
124
+
125
+ 5. **Assemble.**
126
+
127
+ ```sh
128
+ pnpm exec ask digest assemble --input-dir .hev-ask/shards
129
+ ```
130
+
131
+ Merges every current shard distillation with the global synthesis, derives
132
+ the deterministic parts, and writes `.hev-ask/digest.json`. Sections from
133
+ undistilled shards fall back to plain excerpts and are reported — the
134
+ digest stays usable mid-wave, but aim for 0 pending before committing.
135
+
136
+ 6. **Verify.**
137
+
138
+ ```sh
139
+ pnpm exec ask digest verify
140
+ ```
141
+
142
+ Anchor drift is fatal; coverage/fidelity warnings are informational.
143
+
144
+ 7. **Clean up and commit.** The shards directory is a local cache — it is the
145
+ resume/refresh state, so keep it on disk but out of git, and drop the bulky
146
+ input files (regenerated by `corpus` any time):
147
+
148
+ ```sh
149
+ rm -f .hev-ask/shards/input-*.json
150
+ git check-ignore -q .hev-ask/shards || echo ".hev-ask/shards/" >> .gitignore
151
+ git add .gitignore .hev-ask/digest.json
152
+ ```
153
+
154
+ Only `.hev-ask/digest.json` is committed.
155
+
156
+ ## Notes
157
+
158
+ - A small site may produce a single shard; the flow is the same (you can
159
+ distil it yourself instead of spawning an agent — a single shard's input is
160
+ small enough to read directly).
161
+ - `--shard-bytes` (default 200000) tunes shard size if a site's sections are
162
+ unusually dense.
163
+ - If `corpus` fails because no content is found, you're likely not in the
164
+ site root, or the collection name isn't `docs` — pass `--collection <name>`.