@agentskit/doc-bridge 1.7.44 → 1.9.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.
Files changed (223) hide show
  1. package/CHANGELOG.md +471 -0
  2. package/CONTRIBUTING.md +29 -4
  3. package/README.md +87 -40
  4. package/SECURITY.md +7 -0
  5. package/action.yml +1 -1
  6. package/bin/ak-docs.js +2 -2
  7. package/bin/ak-verify.js +13 -7
  8. package/dist/cli/program.d.ts +3 -1
  9. package/dist/cli/program.js +15888 -6061
  10. package/dist/cli/program.js.map +1 -1
  11. package/dist/config/index.d.ts +1 -1
  12. package/dist/config/index.js +91 -9
  13. package/dist/config/index.js.map +1 -1
  14. package/dist/index-Beor6Yhi.d.ts +792 -0
  15. package/dist/index.d.ts +9979 -3257
  16. package/dist/index.js +15954 -5774
  17. package/dist/index.js.map +1 -1
  18. package/docs/MARKETPLACE.md +1 -1
  19. package/docs/PRD-documentation-efficiency-study.md +406 -0
  20. package/docs/PRD-knowledge-retrieval-and-enrichment.md +466 -0
  21. package/docs/RELEASE.md +22 -8
  22. package/docs/adr/0002-documentation-audit-boundary.md +22 -0
  23. package/docs/adr/0003-study-protocol-and-historical-evidence.md +40 -0
  24. package/docs/adr/0004-controlled-study-runner.md +25 -0
  25. package/docs/adr/0005-documentation-quality-and-criticality.md +20 -0
  26. package/docs/adr/0006-registry-semantic-grounding.md +20 -0
  27. package/docs/adr/0007-longitudinal-study-metrics.md +21 -0
  28. package/docs/adr/0008-study-verification-boundary.md +21 -0
  29. package/docs/adr/0009-study-provider-cli-adapter.md +25 -0
  30. package/docs/agent-corpus/INDEX.md +14 -3
  31. package/docs/agent-corpus/OVERVIEW.md +25 -0
  32. package/docs/agent-corpus/chat.md +7 -3
  33. package/docs/agent-corpus/cli.md +18 -2
  34. package/docs/agent-corpus/conformance.md +14 -2
  35. package/docs/agent-corpus/doc-bridge.md +48 -1
  36. package/docs/agent-corpus/doctor.md +10 -2
  37. package/docs/agent-corpus/gates.md +6 -2
  38. package/docs/agent-corpus/mcp.md +15 -2
  39. package/docs/agent-corpus/memory.md +6 -2
  40. package/docs/agent-corpus/query.md +35 -2
  41. package/docs/bench/README.md +122 -0
  42. package/docs/bench/retrieval-baseline-v1.json +28 -0
  43. package/docs/bench/retrieval-suite-v1.json +1033 -0
  44. package/docs/chat-and-rag.md +3 -2
  45. package/docs/for-agents.md +9 -1
  46. package/docs/getting-started.md +4 -11
  47. package/docs/guides/gate-ci.md +11 -1
  48. package/docs/guides/install-and-run.md +9 -65
  49. package/docs/index.md +22 -1
  50. package/docs/knowledge-engine-runbook.md +51 -4
  51. package/docs/landing/assets/context-payload-reduction.svg +21 -0
  52. package/docs/landing/assets/controlled-ab-comparison.svg +30 -0
  53. package/docs/landing/index.html +119 -5
  54. package/docs/loop-workflow.md +117 -0
  55. package/docs/mcp.md +6 -1
  56. package/docs/parity/public-claims-v1.json +145 -0
  57. package/docs/playbook/doc-bridge-pattern.md +1 -1
  58. package/docs/query.md +90 -2
  59. package/docs/recipes/index-pipeline.md +1 -1
  60. package/docs/schemas/agent-handoff-v1.md +15 -0
  61. package/docs/schemas/doc-bridge-index-v1.md +65 -0
  62. package/docs/spec/benchmark-v1.md +39 -1
  63. package/docs/spec/cli.md +30 -10
  64. package/docs/spec/config-v1.md +192 -8
  65. package/docs/spec/documentation-audit-v1.md +61 -0
  66. package/docs/spec/enrichment-overlay-v1.md +241 -0
  67. package/docs/spec/graph-signals-v1.md +92 -0
  68. package/docs/spec/incremental-scan-v1.md +102 -0
  69. package/docs/spec/markdown-analyzer-v1.md +73 -0
  70. package/docs/spec/mcp-knowledge-tools-v1.md +147 -0
  71. package/docs/spec/measured-enrichment-v1.md +229 -0
  72. package/docs/spec/public-parity-v1.md +119 -0
  73. package/docs/spec/registry-agents.md +6 -0
  74. package/docs/spec/render-v1.md +122 -0
  75. package/docs/spec/retrieval-index-v1.md +164 -0
  76. package/docs/spec/study-metrics-v1.md +58 -0
  77. package/docs/spec/study-protocol-v1.md +46 -0
  78. package/docs/spec/study-provider-cli-v1.md +116 -0
  79. package/docs/spec/study-runner-v1.md +35 -0
  80. package/docs/spec/study-task-suite-v1.md +41 -0
  81. package/docs/spec/study-verification-v1.md +40 -0
  82. package/docs/study/README.md +84 -0
  83. package/docs/study/ab-adjudicated-cost-analysis-v1.md +29 -0
  84. package/docs/study/ab-adjudicated-cost-plan-v1.json +33 -0
  85. package/docs/study/ab-adjudicated-cost-plan-v2-v1.json +33 -0
  86. package/docs/study/ab-adjudicated-cost-result-v1.json +80 -0
  87. package/docs/study/ab-baseline-analysis-v1.md +21 -0
  88. package/docs/study/ab-baseline-plan-v1.json +33 -0
  89. package/docs/study/ab-baseline-recovery-plan-v1.json +33 -0
  90. package/docs/study/ab-baseline-result-v1.json +79 -0
  91. package/docs/study/documentation-audit-round-2026-08-31.json +183 -0
  92. package/docs/study/historical-evidence-v1.json +252 -0
  93. package/docs/study/observation-ledger-v1.json +30632 -0
  94. package/docs/study/phase3-task-coverage-v1.json +34 -0
  95. package/docs/study/phase4-public-pilot-ledger-v1.json +1344 -0
  96. package/docs/study/phase4-public-pilot-result-v1.json +52 -0
  97. package/docs/study/phase4-public-pilot-run-plan-v1.json +26 -0
  98. package/docs/study/phase4-public-pilot-task-suite-v1.json +71 -0
  99. package/docs/study/pilot-round-2026-08-31.json +46 -0
  100. package/docs/study/protocol-v1.json +90 -0
  101. package/docs/study/publication-gate-v1.md +45 -0
  102. package/docs/study/quality-scorecard-cycle-plan.md +545 -0
  103. package/docs/study/quality-scorecard-v1.json +38 -0
  104. package/docs/study/round-1-adjudicated-smoke-v1.json +30642 -0
  105. package/docs/study/round-1-instrumentation-plan-v1.md +39 -0
  106. package/docs/study/round-2-expanded-adjudication-v1.json +91 -0
  107. package/docs/study/round-2-expanded-validation-v1.md +58 -0
  108. package/docs/study/round-3-evidence-contract-v1.json +75 -0
  109. package/docs/study/round-3-evidence-contract-v1.md +57 -0
  110. package/docs/study/round-4-confirmation-v1.json +75 -0
  111. package/docs/study/round-4-confirmation-v1.md +55 -0
  112. package/docs/study/run-plan-v1.json +33 -0
  113. package/docs/study/semantic-adjudication-cycle-8.md +20 -0
  114. package/docs/study/task-suite-v1.json +96 -0
  115. package/docs/study/token-efficiency-plan-v1.md +337 -0
  116. package/docs/study/token-efficiency-protocol-v2.json +62 -0
  117. package/docs/study/verification-binding-v1.json +27 -0
  118. package/docs/validation-cycle-plan.md +33 -0
  119. package/docs/verification-harness.md +15 -6
  120. package/ecosystem-claims.json +2 -2
  121. package/ecosystem-upstream.json +2 -2
  122. package/ecosystem.json +4 -4
  123. package/mcpb/manifest.json +9 -1
  124. package/package.json +89 -72
  125. package/scripts/check-ecosystem-upstream.mjs +36 -7
  126. package/scripts/report-visual-check.mjs +20 -3
  127. package/skills/doc-bridge-handoff/fixtures/synthetic-repo/docs/for-agents/packages/payments.md +7 -0
  128. package/skills/doc-bridge-handoff/scripts/resolve-handoff.mjs +1 -1
  129. package/src/agents/registry-adapter.ts +192 -24
  130. package/src/audit/documentation.ts +513 -0
  131. package/src/bench/baseline.ts +198 -0
  132. package/src/bench/overlay-delta.ts +139 -0
  133. package/src/bench/retrieval.ts +319 -0
  134. package/src/budget/compile.ts +91 -0
  135. package/src/budget/sections.ts +70 -0
  136. package/src/cli/demo.ts +2 -2
  137. package/src/cli/program.ts +699 -79
  138. package/src/cli/usage.ts +71 -0
  139. package/src/config/defaults.ts +1 -0
  140. package/src/config/index.ts +4 -0
  141. package/src/config/load-config.ts +7 -1
  142. package/src/config/schema.ts +121 -4
  143. package/src/conformance/documentation-standard-v1.ts +22 -14
  144. package/src/discovery/areas.ts +182 -0
  145. package/src/discovery/documentation.ts +255 -23
  146. package/src/discovery/identity.ts +24 -0
  147. package/src/discovery/incremental.ts +314 -0
  148. package/src/discovery/inputs.ts +110 -0
  149. package/src/discovery/markdown.ts +481 -0
  150. package/src/discovery/repository.ts +557 -125
  151. package/src/doctor/run-doctor.ts +246 -27
  152. package/src/enrich/approvals.ts +190 -0
  153. package/src/enrich/cache.ts +93 -0
  154. package/src/enrich/context-pack.ts +272 -0
  155. package/src/enrich/overlay.ts +255 -0
  156. package/src/enrich/review.ts +106 -0
  157. package/src/enrich/stage.ts +374 -0
  158. package/src/enrich/stats.ts +100 -0
  159. package/src/enrich/validate.ts +410 -0
  160. package/src/federation/llms.ts +74 -24
  161. package/src/findings/report.ts +103 -0
  162. package/src/fixes/proposals.ts +4 -3
  163. package/src/graph/build.ts +356 -0
  164. package/src/graph/memory.ts +208 -0
  165. package/src/index-builder/build-handoffs.ts +22 -11
  166. package/src/index-builder/build-index.ts +132 -3
  167. package/src/index-builder/human-adapters/fumadocs.ts +1 -1
  168. package/src/index-builder/llms-txt.ts +48 -8
  169. package/src/index-builder/project-corpus.ts +111 -0
  170. package/src/index-builder/watch-index.ts +1 -1
  171. package/src/index.ts +630 -2
  172. package/src/lib/bounded-text.ts +15 -10
  173. package/src/lib/fuzzy-match.ts +235 -0
  174. package/src/mcp/knowledge.ts +554 -0
  175. package/src/mcp/server.ts +113 -18
  176. package/src/metrics/benchmark.ts +21 -0
  177. package/src/parity/check.ts +309 -0
  178. package/src/parity/claims.ts +259 -0
  179. package/src/parity/resolve.ts +160 -0
  180. package/src/query/handoff.ts +326 -0
  181. package/src/query/load-index.ts +53 -1
  182. package/src/query/query.ts +92 -59
  183. package/src/query/search.ts +289 -92
  184. package/src/query/text.ts +155 -0
  185. package/src/reconciliation/reconcile.ts +148 -15
  186. package/src/render/data.ts +356 -0
  187. package/src/render/engine.ts +398 -0
  188. package/src/render/generated.ts +77 -0
  189. package/src/render/render.ts +209 -0
  190. package/src/render/template-source.ts +52 -0
  191. package/src/render/templates.ts +289 -0
  192. package/src/report/html.ts +23 -17
  193. package/src/retrieval/bm25.ts +161 -0
  194. package/src/retrieval/project.ts +495 -0
  195. package/src/retrieval/rank.ts +383 -0
  196. package/src/retrieval/weights.ts +39 -0
  197. package/src/retriever/doc-bridge-retriever.ts +100 -15
  198. package/src/rules/engine.ts +45 -12
  199. package/src/safety/repository.ts +1 -1
  200. package/src/schemas/agent-handoff.ts +56 -0
  201. package/src/schemas/budget.ts +37 -0
  202. package/src/schemas/doc-bridge-index.ts +53 -2
  203. package/src/schemas/enrichment.ts +369 -0
  204. package/src/schemas/json-schemas.ts +39 -2
  205. package/src/schemas/knowledge.ts +19 -3
  206. package/src/schemas/retrieval-index.ts +152 -0
  207. package/src/shims/graphology.d.ts +91 -0
  208. package/src/study/adjudication.ts +196 -0
  209. package/src/study/execution.ts +350 -0
  210. package/src/study/expectations.ts +219 -0
  211. package/src/study/metrics.ts +467 -0
  212. package/src/study/protocol.ts +271 -0
  213. package/src/study/provider-cli.ts +115 -0
  214. package/src/study/provider-telemetry.ts +47 -0
  215. package/src/study/quality-scorecard.ts +164 -0
  216. package/src/study/runner.ts +461 -0
  217. package/src/study/task-suite.ts +321 -0
  218. package/src/study/verification.ts +134 -0
  219. package/src/validate.ts +8 -5
  220. package/src/version.ts +1 -1
  221. package/src/workflow/engine.ts +36 -11
  222. package/dist/index-C2PCQSrB.d.ts +0 -2251
  223. package/scripts/verification-harness.mjs +0 -483
@@ -0,0 +1,52 @@
1
+ import { readFileSync } from 'node:fs'
2
+ import { resolve } from 'node:path'
3
+
4
+ import type { DocBridgeConfigV1 } from '../config/schema.js'
5
+ import { toPosix } from '../lib/paths.js'
6
+ import { compileTemplate, renderCompiledTemplate, type CompiledTemplate, type TemplateVariables } from './engine.js'
7
+ import { BUNDLED_TEMPLATES, type RenderTemplateName } from './templates.js'
8
+
9
+ /**
10
+ * Which template renders a name: the project's, when `render.templates` names one, otherwise
11
+ * the bundled one. An override is a file the project owns; it replaces the bundled template
12
+ * entirely and is compiled against the same engine, so a project changes its house style without
13
+ * a code change and a template that does not parse fails before anything is written.
14
+ */
15
+ export type TemplateSource = {
16
+ readonly name: RenderTemplateName
17
+ readonly source: string
18
+ /** `bundled`, or the override path as configured. */
19
+ readonly origin: string
20
+ }
21
+
22
+ export const resolveTemplateSource = (name: RenderTemplateName, config: DocBridgeConfigV1, root?: string): TemplateSource => {
23
+ const override = config.render?.templates?.[name]
24
+ if (!override) return { name, source: BUNDLED_TEMPLATES[name], origin: 'bundled' }
25
+ const path = root ? resolve(root, override) : resolve(override)
26
+ let source: string
27
+ try {
28
+ source = readFileSync(path, 'utf8')
29
+ } catch (error) {
30
+ throw new Error(`render.templates["${name}"] points at ${toPosix(override)}, which could not be read: ${error instanceof Error ? error.message : String(error)}`)
31
+ }
32
+ return { name, source, origin: toPosix(override) }
33
+ }
34
+
35
+ /*
36
+ * Compiled once per distinct source. The index builder and the conformance profile render
37
+ * `llms.txt` on every run, and parsing the same bundled template twice per run buys nothing.
38
+ */
39
+ const compiled = new Map<string, CompiledTemplate>()
40
+
41
+ const compile = (template: TemplateSource): CompiledTemplate => {
42
+ const key = JSON.stringify([template.name, template.origin, template.source])
43
+ let result = compiled.get(key)
44
+ if (!result) {
45
+ result = compileTemplate(template.source, template.origin === 'bundled' ? `template "${template.name}"` : template.origin)
46
+ compiled.set(key, result)
47
+ }
48
+ return result
49
+ }
50
+
51
+ export const renderNamedTemplate = (name: RenderTemplateName, variables: TemplateVariables, config: DocBridgeConfigV1, root?: string): string =>
52
+ renderCompiledTemplate(compile(resolveTemplateSource(name, config, root)), variables)
@@ -0,0 +1,289 @@
1
+ /**
2
+ * The bundled templates.
3
+ *
4
+ * They live in a TypeScript module rather than next to it as `.md` files because the package
5
+ * ships `dist/` built by tsup, which bundles source and nothing else: a template on disk is a
6
+ * template the published package does not have. `ak-docs render <name> --print-template` prints
7
+ * one, which is how a project starts an override under `render.templates`.
8
+ *
9
+ * knap syntax, with one rule the syntax does not advertise: a block tag whose output is empty
10
+ * swallows the line break after it, and a block whose output is not empty swallows the line
11
+ * break at its own start instead. So a list is written as `{% for %}` followed by a standalone
12
+ * `{% if not … %}` block for its empty state — exactly one of the two renders, exactly one line
13
+ * break is consumed, and the blank line before the next heading survives either way. A test
14
+ * renders every template through knap's own engine to keep these shapes honest.
15
+ */
16
+
17
+ export const RENDER_TEMPLATE_NAMES = ['llms.txt', 'area', 'ownership', 'change-digest', 'overlay-review'] as const
18
+
19
+ export type RenderTemplateName = (typeof RENDER_TEMPLATE_NAMES)[number]
20
+
21
+ export type RenderTemplateInfo = {
22
+ readonly name: RenderTemplateName
23
+ readonly description: string
24
+ /** What `--data` may point at, in place of the default source. */
25
+ readonly data: string
26
+ /** Whether the output is one Markdown page per unit rather than a single file. */
27
+ readonly multiPage: boolean
28
+ /** Whether the output carries generated-region markers. `llms.txt` is a whole-file artifact with its own consumers and carries none. */
29
+ readonly generatedRegion: boolean
30
+ }
31
+
32
+ export const RENDER_TEMPLATES: Readonly<Record<RenderTemplateName, RenderTemplateInfo>> = {
33
+ 'llms.txt': {
34
+ name: 'llms.txt',
35
+ description: 'The curated reading order for agents, as `ak-docs index` writes it',
36
+ data: 'a DocBridgeIndex (.doc-bridge/index.json)',
37
+ multiPage: false,
38
+ generatedRegion: false,
39
+ },
40
+ area: {
41
+ name: 'area',
42
+ description: 'One page per code area: purpose, modules, documents, related areas, checks and open findings',
43
+ data: 'a DocBridgeIndex (.doc-bridge/index.json)',
44
+ multiPage: true,
45
+ generatedRegion: true,
46
+ },
47
+ ownership: {
48
+ name: 'ownership',
49
+ description: 'One sidecar per ownership record: where to start, what to read, what to run',
50
+ data: 'a DocBridgeIndex (.doc-bridge/index.json)',
51
+ multiPage: true,
52
+ generatedRegion: true,
53
+ },
54
+ 'change-digest': {
55
+ name: 'change-digest',
56
+ description: 'Entities and documents whose content hash moved since the last scan, and the documents that should have moved with them',
57
+ data: 'the previous discovery snapshot to compare against (default: the last `ak-docs scan`)',
58
+ multiPage: false,
59
+ generatedRegion: true,
60
+ },
61
+ 'overlay-review': {
62
+ name: 'overlay-review',
63
+ description: 'Pending agent proposals with their evidence, for a human to judge',
64
+ data: 'an enrichment overlay (default: .doc-bridge/enrich/overlay.json)',
65
+ multiPage: false,
66
+ generatedRegion: true,
67
+ },
68
+ }
69
+
70
+ export const isRenderTemplateName = (value: string): value is RenderTemplateName =>
71
+ (RENDER_TEMPLATE_NAMES as readonly string[]).includes(value)
72
+
73
+ /*
74
+ * `llms.txt` must stay byte-identical to what the string concatenation produced, including the
75
+ * empty corpus: a preamble, a blank line, the heading, a blank line, the entries and a final
76
+ * newline — which for no entries is `## Knowledge` followed by three line breaks. An empty loop
77
+ * swallows the line break after `{% endfor %}`, so the empty case gets its own block: its three
78
+ * line breaks become two after the closing tag's line is trimmed and one after the block's own
79
+ * trim, which is the one the loop swallowed. The template ends at `{% endif %}` on purpose.
80
+ */
81
+ const LLMS_TXT = `{{ preamble }}
82
+
83
+ ## Knowledge
84
+
85
+ {% for entry in entries %}
86
+ - [{{ entry.title }}]({{ entry.url }}){% if entry.description %}: {{ entry.description }}{% endif %}
87
+ {% endfor %}
88
+ {% if not entries %}
89
+
90
+
91
+ {% endif %}`
92
+
93
+ const AREA = `{{ region.open }}
94
+ # Area \`{{ area.path }}\`
95
+
96
+ {{ area.purpose }}
97
+ {% if area.ownership %}
98
+
99
+ {{ area.ownership }}
100
+ {% endif %}
101
+
102
+ ## Modules
103
+
104
+ {% for module in area.modules %}
105
+ - \`{{ module.path }}\`{% if module.symbols %}: exports {{ module.symbols }}{% endif %}
106
+ {% endfor %}
107
+ {% if not area.modules %}
108
+ No module was observed in this area.
109
+ {% endif %}
110
+
111
+ ## Documents
112
+
113
+ {% for document in area.documents %}
114
+ - [{{ document.title }}]({{ document.path }}): {{ document.relation }}
115
+ {% endfor %}
116
+ {% if not area.documents %}
117
+ No document covers or mentions this area.
118
+ {% endif %}
119
+
120
+ ## Related areas
121
+
122
+ {% for related in area.related %}
123
+ - \`{{ related.path }}\`: {{ related.direction }}, {{ related.strength }} import(s) — {{ related.evidence }}
124
+ {% endfor %}
125
+ {% if not area.related %}
126
+ No import crosses this area's boundary.
127
+ {% endif %}
128
+
129
+ ## Checks
130
+
131
+ {% for check in area.checks %}
132
+ - \`{{ check }}\`
133
+ {% endfor %}
134
+ {% if not area.checks %}
135
+ No check is declared for this area.
136
+ {% endif %}
137
+ {% if area.checksSource %}
138
+
139
+ Source: {{ area.checksSource }}.
140
+ {% endif %}
141
+
142
+ ## Open findings
143
+
144
+ {% for finding in area.findings %}
145
+ - **{{ finding.code }}** ({{ finding.severity }}, {{ finding.status }}): {{ finding.message }} — \`{{ finding.evidence }}\`
146
+ {% endfor %}
147
+ {% if not area.findings %}
148
+ {{ area.findingsEmpty }}
149
+ {% endif %}
150
+ {{ region.close }}
151
+ `
152
+
153
+ const OWNERSHIP = `---
154
+ type: {{ owner.kind }}
155
+ id: {{ owner.id }}
156
+ editRoot: {{ owner.path }}
157
+ {% if owner.humanDoc %}
158
+ humanDoc: {{ owner.humanDoc }}
159
+ {% endif %}
160
+ ---
161
+
162
+ {{ region.open }}
163
+ # {{ owner.id }}
164
+
165
+ {{ owner.purpose }}
166
+
167
+ ## Start here
168
+
169
+ {{ owner.startHere }}
170
+
171
+ ## Read before editing
172
+
173
+ {% for path in owner.readBeforeEditing %}
174
+ - {{ path }}
175
+ {% endfor %}
176
+ {% if not owner.readBeforeEditing %}
177
+ Nothing beyond the start page.
178
+ {% endif %}
179
+
180
+ ## Edit roots
181
+
182
+ {% for path in owner.editRoots %}
183
+ - \`{{ path }}\`
184
+ {% endfor %}
185
+
186
+ ## Checks
187
+
188
+ {% for check in owner.checks %}
189
+ - \`{{ check }}\`
190
+ {% endfor %}
191
+ {% if not owner.checks %}
192
+ No check is declared.
193
+ {% endif %}
194
+ {% if owner.checksSource %}
195
+
196
+ Source: {{ owner.checksSource }}.
197
+ {% endif %}
198
+
199
+ ## Related areas
200
+
201
+ {% for related in owner.related %}
202
+ - \`{{ related.path }}\`: {{ related.direction }}, {{ related.strength }} import(s) — {{ related.evidence }}
203
+ {% endfor %}
204
+ {% if not owner.related %}
205
+ No import crosses this unit's boundary.
206
+ {% endif %}
207
+ {{ region.close }}
208
+ `
209
+
210
+ const CHANGE_DIGEST = `{{ region.open }}
211
+ # Change digest
212
+
213
+ Compared the current tree with the previous snapshot: {{ digest.summary }}.
214
+
215
+ ## Changed
216
+
217
+ {% for entity in digest.changed %}
218
+ - \`{{ entity.path }}\` ({{ entity.kind }}): {{ entity.previousHash }} → {{ entity.currentHash }}
219
+ {% endfor %}
220
+ {% if not digest.changed %}
221
+ No file-backed entity changed.
222
+ {% endif %}
223
+
224
+ ## Added
225
+
226
+ {% for entity in digest.added %}
227
+ - \`{{ entity.path }}\` ({{ entity.kind }}): {{ entity.currentHash }}
228
+ {% endfor %}
229
+ {% if not digest.added %}
230
+ Nothing was added.
231
+ {% endif %}
232
+
233
+ ## Removed
234
+
235
+ {% for entity in digest.removed %}
236
+ - \`{{ entity.path }}\` ({{ entity.kind }}): {{ entity.previousHash }}
237
+ {% endfor %}
238
+ {% if not digest.removed %}
239
+ Nothing was removed.
240
+ {% endif %}
241
+
242
+ ## Documentation to review
243
+
244
+ {% for document in digest.documentsToReview %}
245
+ - \`{{ document.path }}\`: {{ document.because }}
246
+ {% endfor %}
247
+ {% if not digest.documentsToReview %}
248
+ No unchanged document covers or mentions a changed entity.
249
+ {% endif %}
250
+ {{ region.close }}
251
+ `
252
+
253
+ const OVERLAY_REVIEW = `{{ region.open }}
254
+ # Overlay review
255
+
256
+ {% if overlay.present %}
257
+ {{ overlay.summary }}
258
+
259
+ {% for proposal in overlay.pending %}
260
+ ## {{ proposal.kind }}: \`{{ proposal.entity }}\`
261
+
262
+ {{ proposal.reason }}
263
+
264
+ Confidence {{ proposal.confidence }} · proposal \`{{ proposal.proposalId }}\`
265
+
266
+ {% for item in proposal.evidence %}
267
+ - {{ item.link }}
268
+ {% endfor %}
269
+ {% if not proposal.evidence %}
270
+ No evidence was attached to this proposal.
271
+ {% endif %}
272
+
273
+ {% endfor %}
274
+ {% if not overlay.pending %}
275
+ No proposal is pending review.
276
+ {% endif %}
277
+ {% else %}
278
+ No enrichment overlay exists for this repository. Run \`ak-docs enrich\` to produce one, or pass \`--data <overlay.json>\`.
279
+ {% endif %}
280
+ {{ region.close }}
281
+ `
282
+
283
+ export const BUNDLED_TEMPLATES: Readonly<Record<RenderTemplateName, string>> = {
284
+ 'llms.txt': LLMS_TXT,
285
+ area: AREA,
286
+ ownership: OWNERSHIP,
287
+ 'change-digest': CHANGE_DIGEST,
288
+ 'overlay-review': OVERLAY_REVIEW,
289
+ }