@agentskit/doc-bridge 1.7.45 → 1.10.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 (213) hide show
  1. package/CHANGELOG.md +488 -0
  2. package/CONTRIBUTING.md +23 -0
  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 +15871 -6218
  10. package/dist/cli/program.js.map +1 -1
  11. package/dist/config/index.d.ts +1 -1
  12. package/dist/config/index.js +95 -6
  13. package/dist/config/index.js.map +1 -1
  14. package/dist/{index-BUL0q7s8.d.ts → index-7wYGbllW.d.ts} +134 -1
  15. package/dist/index.d.ts +9880 -1062
  16. package/dist/index.js +16143 -6127
  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/adr/0002-documentation-audit-boundary.md +22 -0
  22. package/docs/adr/0003-study-protocol-and-historical-evidence.md +40 -0
  23. package/docs/adr/0004-controlled-study-runner.md +25 -0
  24. package/docs/adr/0005-documentation-quality-and-criticality.md +20 -0
  25. package/docs/adr/0006-registry-semantic-grounding.md +20 -0
  26. package/docs/adr/0007-longitudinal-study-metrics.md +21 -0
  27. package/docs/adr/0008-study-verification-boundary.md +21 -0
  28. package/docs/adr/0009-study-provider-cli-adapter.md +25 -0
  29. package/docs/agent-corpus/INDEX.md +12 -1
  30. package/docs/agent-corpus/OVERVIEW.md +25 -0
  31. package/docs/agent-corpus/chat.md +5 -1
  32. package/docs/agent-corpus/cli.md +16 -0
  33. package/docs/agent-corpus/conformance.md +12 -0
  34. package/docs/agent-corpus/doc-bridge.md +47 -0
  35. package/docs/agent-corpus/doctor.md +8 -0
  36. package/docs/agent-corpus/gates.md +4 -0
  37. package/docs/agent-corpus/mcp.md +13 -0
  38. package/docs/agent-corpus/memory.md +4 -0
  39. package/docs/agent-corpus/query.md +33 -0
  40. package/docs/bench/README.md +122 -0
  41. package/docs/bench/retrieval-baseline-v1.json +28 -0
  42. package/docs/bench/retrieval-suite-v1.json +1033 -0
  43. package/docs/chat-and-rag.md +3 -2
  44. package/docs/for-agents.md +9 -1
  45. package/docs/getting-started.md +4 -11
  46. package/docs/guides/gate-ci.md +11 -1
  47. package/docs/guides/install-and-run.md +9 -65
  48. package/docs/index.md +22 -1
  49. package/docs/knowledge-engine-runbook.md +38 -3
  50. package/docs/landing/assets/context-payload-reduction.svg +21 -0
  51. package/docs/landing/assets/controlled-ab-comparison.svg +30 -0
  52. package/docs/landing/index.html +119 -5
  53. package/docs/loop-workflow.md +117 -0
  54. package/docs/mcp.md +6 -1
  55. package/docs/parity/public-claims-v1.json +145 -0
  56. package/docs/playbook/doc-bridge-pattern.md +1 -1
  57. package/docs/query.md +90 -2
  58. package/docs/recipes/index-pipeline.md +1 -1
  59. package/docs/schemas/agent-handoff-v1.md +15 -0
  60. package/docs/schemas/doc-bridge-index-v1.md +65 -0
  61. package/docs/spec/benchmark-v1.md +33 -1
  62. package/docs/spec/cli.md +30 -10
  63. package/docs/spec/config-v1.md +157 -8
  64. package/docs/spec/documentation-audit-v1.md +61 -0
  65. package/docs/spec/enrichment-overlay-v1.md +241 -0
  66. package/docs/spec/graph-signals-v1.md +92 -0
  67. package/docs/spec/incremental-scan-v1.md +102 -0
  68. package/docs/spec/markdown-analyzer-v1.md +73 -0
  69. package/docs/spec/mcp-knowledge-tools-v1.md +147 -0
  70. package/docs/spec/measured-enrichment-v1.md +229 -0
  71. package/docs/spec/public-parity-v1.md +119 -0
  72. package/docs/spec/registry-agents.md +6 -0
  73. package/docs/spec/render-v1.md +122 -0
  74. package/docs/spec/retrieval-index-v1.md +164 -0
  75. package/docs/spec/study-metrics-v1.md +58 -0
  76. package/docs/spec/study-protocol-v1.md +46 -0
  77. package/docs/spec/study-provider-cli-v1.md +116 -0
  78. package/docs/spec/study-runner-v1.md +35 -0
  79. package/docs/spec/study-task-suite-v1.md +41 -0
  80. package/docs/spec/study-verification-v1.md +40 -0
  81. package/docs/study/README.md +84 -0
  82. package/docs/study/ab-adjudicated-cost-analysis-v1.md +29 -0
  83. package/docs/study/ab-adjudicated-cost-plan-v1.json +33 -0
  84. package/docs/study/ab-adjudicated-cost-plan-v2-v1.json +33 -0
  85. package/docs/study/ab-adjudicated-cost-result-v1.json +80 -0
  86. package/docs/study/ab-baseline-analysis-v1.md +21 -0
  87. package/docs/study/ab-baseline-plan-v1.json +33 -0
  88. package/docs/study/ab-baseline-recovery-plan-v1.json +33 -0
  89. package/docs/study/ab-baseline-result-v1.json +79 -0
  90. package/docs/study/documentation-audit-round-2026-08-31.json +183 -0
  91. package/docs/study/historical-evidence-v1.json +252 -0
  92. package/docs/study/observation-ledger-v1.json +30632 -0
  93. package/docs/study/phase3-task-coverage-v1.json +34 -0
  94. package/docs/study/phase4-public-pilot-ledger-v1.json +1344 -0
  95. package/docs/study/phase4-public-pilot-result-v1.json +52 -0
  96. package/docs/study/phase4-public-pilot-run-plan-v1.json +26 -0
  97. package/docs/study/phase4-public-pilot-task-suite-v1.json +71 -0
  98. package/docs/study/pilot-round-2026-08-31.json +46 -0
  99. package/docs/study/protocol-v1.json +90 -0
  100. package/docs/study/publication-gate-v1.md +45 -0
  101. package/docs/study/quality-scorecard-cycle-plan.md +545 -0
  102. package/docs/study/quality-scorecard-v1.json +38 -0
  103. package/docs/study/round-1-adjudicated-smoke-v1.json +30642 -0
  104. package/docs/study/round-1-instrumentation-plan-v1.md +39 -0
  105. package/docs/study/round-2-expanded-adjudication-v1.json +91 -0
  106. package/docs/study/round-2-expanded-validation-v1.md +58 -0
  107. package/docs/study/round-3-evidence-contract-v1.json +75 -0
  108. package/docs/study/round-3-evidence-contract-v1.md +57 -0
  109. package/docs/study/round-4-confirmation-v1.json +75 -0
  110. package/docs/study/round-4-confirmation-v1.md +55 -0
  111. package/docs/study/run-plan-v1.json +33 -0
  112. package/docs/study/semantic-adjudication-cycle-8.md +20 -0
  113. package/docs/study/task-suite-v1.json +96 -0
  114. package/docs/study/token-efficiency-plan-v1.md +337 -0
  115. package/docs/study/token-efficiency-protocol-v2.json +62 -0
  116. package/docs/study/verification-binding-v1.json +27 -0
  117. package/docs/validation-cycle-plan.md +14 -0
  118. package/docs/verification-harness.md +11 -6
  119. package/ecosystem-claims.json +2 -2
  120. package/ecosystem-upstream.json +2 -2
  121. package/ecosystem.json +4 -4
  122. package/mcpb/manifest.json +9 -1
  123. package/package.json +34 -15
  124. package/scripts/check-ecosystem-upstream.mjs +34 -6
  125. package/skills/doc-bridge-handoff/fixtures/synthetic-repo/docs/for-agents/packages/payments.md +7 -0
  126. package/skills/doc-bridge-handoff/scripts/resolve-handoff.mjs +1 -1
  127. package/src/agents/registry-adapter.ts +192 -24
  128. package/src/audit/documentation.ts +513 -0
  129. package/src/bench/baseline.ts +198 -0
  130. package/src/bench/overlay-delta.ts +139 -0
  131. package/src/bench/retrieval.ts +319 -0
  132. package/src/budget/compile.ts +91 -0
  133. package/src/budget/sections.ts +70 -0
  134. package/src/cli/program.ts +684 -74
  135. package/src/cli/usage.ts +71 -0
  136. package/src/config/defaults.ts +1 -0
  137. package/src/config/index.ts +4 -0
  138. package/src/config/schema.ts +126 -2
  139. package/src/conformance/documentation-standard-v1.ts +8 -6
  140. package/src/discovery/areas.ts +197 -0
  141. package/src/discovery/documentation.ts +211 -5
  142. package/src/discovery/identity.ts +24 -0
  143. package/src/discovery/incremental.ts +314 -0
  144. package/src/discovery/inputs.ts +110 -0
  145. package/src/discovery/markdown.ts +481 -0
  146. package/src/discovery/repository.ts +485 -101
  147. package/src/doctor/run-doctor.ts +244 -12
  148. package/src/enrich/approvals.ts +190 -0
  149. package/src/enrich/cache.ts +93 -0
  150. package/src/enrich/context-pack.ts +272 -0
  151. package/src/enrich/overlay.ts +255 -0
  152. package/src/enrich/review.ts +106 -0
  153. package/src/enrich/stage.ts +374 -0
  154. package/src/enrich/stats.ts +100 -0
  155. package/src/enrich/validate.ts +410 -0
  156. package/src/federation/llms.ts +2 -4
  157. package/src/findings/report.ts +103 -0
  158. package/src/graph/build.ts +356 -0
  159. package/src/graph/memory.ts +208 -0
  160. package/src/index-builder/build-handoffs.ts +22 -11
  161. package/src/index-builder/build-index.ts +132 -3
  162. package/src/index-builder/llms-txt.ts +48 -8
  163. package/src/index-builder/project-corpus.ts +111 -0
  164. package/src/index.ts +630 -2
  165. package/src/lib/fuzzy-match.ts +235 -0
  166. package/src/mcp/knowledge.ts +554 -0
  167. package/src/mcp/server.ts +113 -18
  168. package/src/metrics/benchmark.ts +21 -0
  169. package/src/parity/check.ts +309 -0
  170. package/src/parity/claims.ts +259 -0
  171. package/src/parity/resolve.ts +160 -0
  172. package/src/query/handoff.ts +326 -0
  173. package/src/query/load-index.ts +53 -1
  174. package/src/query/query.ts +92 -59
  175. package/src/query/search.ts +289 -92
  176. package/src/query/text.ts +155 -0
  177. package/src/reconciliation/reconcile.ts +101 -10
  178. package/src/render/data.ts +356 -0
  179. package/src/render/engine.ts +398 -0
  180. package/src/render/generated.ts +77 -0
  181. package/src/render/render.ts +209 -0
  182. package/src/render/template-source.ts +52 -0
  183. package/src/render/templates.ts +289 -0
  184. package/src/report/html.ts +2 -2
  185. package/src/retrieval/bm25.ts +161 -0
  186. package/src/retrieval/project.ts +495 -0
  187. package/src/retrieval/rank.ts +383 -0
  188. package/src/retrieval/weights.ts +39 -0
  189. package/src/retriever/doc-bridge-retriever.ts +100 -15
  190. package/src/rules/engine.ts +30 -10
  191. package/src/schemas/agent-handoff.ts +56 -0
  192. package/src/schemas/budget.ts +37 -0
  193. package/src/schemas/doc-bridge-index.ts +53 -2
  194. package/src/schemas/enrichment.ts +369 -0
  195. package/src/schemas/json-schemas.ts +39 -2
  196. package/src/schemas/knowledge.ts +14 -1
  197. package/src/schemas/retrieval-index.ts +152 -0
  198. package/src/shims/graphology.d.ts +91 -0
  199. package/src/study/adjudication.ts +196 -0
  200. package/src/study/execution.ts +350 -0
  201. package/src/study/expectations.ts +219 -0
  202. package/src/study/metrics.ts +467 -0
  203. package/src/study/protocol.ts +271 -0
  204. package/src/study/provider-cli.ts +115 -0
  205. package/src/study/provider-telemetry.ts +47 -0
  206. package/src/study/quality-scorecard.ts +164 -0
  207. package/src/study/runner.ts +461 -0
  208. package/src/study/task-suite.ts +321 -0
  209. package/src/study/verification.ts +134 -0
  210. package/src/validate.ts +1 -4
  211. package/src/version.ts +1 -1
  212. package/src/workflow/engine.ts +36 -11
  213. package/scripts/verification-harness.mjs +0 -482
package/CHANGELOG.md CHANGED
@@ -1,5 +1,493 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.10.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 97851d0: Let a repository say which directories are not areas.
8
+
9
+ An area is the unit of architecture between a package and a file, derived as the first directory
10
+ level under a package's source roots. In a monorepo where every package keeps `tests/` and
11
+ `fixtures/` beside `src/`, that derives one area per directory — and the doctor's connectivity
12
+ dimension then asks for a document about a folder of test data. Dogfooding on a 26-package
13
+ monorepo, 43 of its 81 undocumented areas were `tests/` or `fixtures/`: the metric was mostly
14
+ measuring directories no documentation should describe.
15
+
16
+ `analysis.areas.exclude` takes glob patterns for directories that hold code without being a unit
17
+ of architecture. A matching candidate is not derived, and its modules fall to the most specific
18
+ area that still encloses them — or to none, which is the honest answer for a folder of fixtures.
19
+ An ownership record naming an excluded path still makes it an area: a person saying a directory is
20
+ a unit outranks a pattern saying it is not.
21
+
22
+ On that monorepo, excluding `**/tests`, `**/fixtures`, `**/__tests__` and `**/__fixtures__` took
23
+ areas from 103 to 53 and the documented share from 21% to 34%, before a single document was
24
+ written.
25
+
26
+ ## 1.9.0
27
+
28
+ ### Minor Changes
29
+
30
+ - 9a775a5: Add code areas — the unit of architecture between a package and a file — so reconciliation says
31
+ something useful about a single-package repository.
32
+
33
+ With `reconciliation.scope: "package"` and one package, every internal relation aggregated into a
34
+ self-loop the comparison skips: a thousand observed relations, zero diagnostics, and a health
35
+ score of 100 out of 100 that meant nothing. Most repositories are a single package. The ownership
36
+ configuration already named the missing unit (`path: "src/mcp"`); the graph had no entity for it.
37
+
38
+ `area:<dir>` entities are now derived from the first directory level under each package's source
39
+ roots, plus any path an ownership record names, with `contains` relations from the package, to
40
+ nested areas, and to each module. Each module belongs to exactly one area — the most specific —
41
+ so containment stays a tree and an aggregation has one answer per module. `analysis.areas.depth`
42
+ and `analysis.areas.roots` change what is derived without a code change.
43
+
44
+ `reconciliation.scope: "area"` compares at that level. On this repository it turns 0 diagnostics
45
+ into 177 `RELATION_UNDOCUMENTED` findings, each with file and line evidence.
46
+
47
+ An area that an ownership record names carries `metadata.ownershipId`, which makes two things
48
+ work that could not before. An ownership path no observed module or document lives under is now
49
+ reported as `OWNERSHIP_PATH_UNOBSERVED` with status `stale-or-unverified` — a renamed directory
50
+ was previously invisible, because the handoff still resolved. And an agent document declaring
51
+ `id` plus `editRoot` now resolves to the area it owns: that pair has always filled the ownership
52
+ map, but discovery never read it, so every such declaration became an unresolved reference.
53
+
54
+ The documentation audit measures coverage against areas when a repository has exactly one package.
55
+ It reported `Packages covered: 0/0` on this repository; it now reports `Areas covered: 9/36`, with
56
+ `metrics.coverageUnit` naming the unit and `AREA_DOCUMENTATION_MISSING` for an uncovered area.
57
+
58
+ A document naming a directory in inline code now produces a `mentions` relation to that area,
59
+ completing the part of the Markdown analyzer that was waiting for areas to exist.
60
+
61
+ `pipelineVersion` becomes `1.3.0` and the `repository` analyzer `1.2.0`. `DiscoverySnapshotV1`'s
62
+ schema version is unchanged: the new kind travels through the existing generic envelope.
63
+ - 9a775a5: Let a Registry agent enrich the knowledge graph without ever becoming an authority over it.
64
+
65
+ `EnrichmentProposalV1` is a discriminated union of eleven typed claims — classify a document,
66
+ summarize it, add an alias or an intent, mark it canonical for a scope, propose a relation, flag a
67
+ contradiction, a redundancy or a gap, hint at relevance, suggest an area — each with its own
68
+ deterministic validator and its own policy: low-risk kinds are accepted by policy, structural kinds
69
+ wait for a person, a gap is accepted as a finding and never as a fact, and an unknown kind is
70
+ rejected as `invalid-kind`. A proposal with no evidence, an unknown entity, an unknown diagnostic or
71
+ evidence outside the supplied artifacts is rejected at the boundary. `proposalId` is derived from
72
+ content, so re-running enrichment over an unchanged repository produces no duplicate entries.
73
+
74
+ `EnrichmentOverlayV1` at `.doc-bridge/enrich/overlay.json` stores what became of every proposal:
75
+ `accepted` with `acceptedAt` and `acceptedBy` (`policy` or a person, never the author), `pending`
76
+ with its approval id, `rejected` with a reason, and `stats` by kind. Each entry binds to the content
77
+ hash of the entity it describes: one changed file expires one entry at projection time, its siblings
78
+ survive, and a read never rewrites the file. Re-running the validators over a stored overlay
79
+ reproduces its partition.
80
+
81
+ A new workflow stage `enrich` sits between `reconcile` and `evaluate` and runs only from
82
+ `ak-docs enrich` or `check --enrich`. Agents receive context packs — one entity, its depth-one
83
+ neighbours, the open diagnostics that touch it and a redacted excerpt, under a 64 KB budget
84
+ (`intelligence.registry.maxPackBytes`) — over protocol `doc-bridge.registry-agent.v2`, batched by
85
+ area. Answers are cached under `.doc-bridge/enrich/cache/` keyed on task, agent identity and
86
+ version, prompt version and pack hash, so an unchanged repository makes zero agent calls and a
87
+ one-document change re-runs only the affected packs. Roles are configuration under
88
+ `intelligence.registry.roles` — curator for documents, reviewer for structure, adjudicator for
89
+ canonical conflicts and disputed contradictions, which must be a different identity and may never
90
+ judge its own proposals — and the default remains the existing corpus scanner as curator only.
91
+
92
+ Human approvals go through `createApprovalGate` from `@agentskit/core/hitl` over a file-backed
93
+ store under `.doc-bridge/approvals/`, shared by `ak-docs enrich approve|reject`, `ak-docs fix
94
+ approve` and MCP `docbridge.proposals` (`enrich-list`, `enrich-approve`, `enrich-reject`), bound to
95
+ both the proposal id and the target content hash. An approver equal to the author is refused.
96
+
97
+ Accepted entries enter the retrieval projection: aliases, summaries where a document has none,
98
+ intents and relations with `provenance: proposed` (drawn dashed in the HTML report), canonical
99
+ markers and rank hints as a per-entry signal worth at most 15 percent of the exact-id boost, so an
100
+ exact identifier match always outranks an overlay-boosted entry. With the Registry disabled, absent,
101
+ timing out or answering garbage, `check`, `index`, `search`, `query` and MCP are byte-identical to a
102
+ run with no overlay, and every observed entity and relation survives enrichment unchanged.
103
+ - 9a775a5: Compute graph signals with a graph library instead of ad-hoc counting, and expose the repository
104
+ graph through the ecosystem memory contract.
105
+
106
+ `centrality-risk` in the rules engine derived from the number of undocumented-relation findings
107
+ attached to an entity — documentation debt wearing the name of an architectural signal. A module
108
+ every import path runs through scored zero if it happened to be documented. It is now betweenness
109
+ over the import graph, and without a graph the rule reports nothing rather than reporting the wrong
110
+ thing under a name people act on. On this repository it flags `src/cli/program.ts` first, which is
111
+ the correct answer and one the old heuristic never gave.
112
+
113
+ `src/graph/build.ts` adds, on graphology:
114
+
115
+ - **canonicality** from PageRank over `links-to` and `covers`, so a documentation entry point
116
+ outranks a leaf page;
117
+ - **centrality** from normalized betweenness over `imports` and `re-exports`;
118
+ - **proximity** from bounded shortest paths, excluding `contains`, which is hierarchy and would put
119
+ every module in an area two hops from every other one;
120
+ - **import cycles** with every edge that forms them as evidence, reported as a new `IMPORT_CYCLE`
121
+ diagnostic — this repository has exactly one, between two `src/doctor` modules;
122
+ - **area suggestions** from seeded Louvain communities, emitted only as `coverage` with
123
+ `analyzer: graph` and `scope: area-suggestion:<path>`, status `not-analyzed`. A clustering
124
+ algorithm does not get to name the architecture.
125
+
126
+ `createDocBridgeGraphMemory(snapshot, overlay)` in `src/graph/memory.ts` projects the graph behind
127
+ `GraphMemory` from `@agentskit/memory`, so an agent built on AgentsKit walks repository structure
128
+ with the same `getNode`, `findEdges` and `neighbors` calls it uses for its own memory. Writes land
129
+ in a working layer above the projection and deletes mask rather than erase: the snapshot is an
130
+ observation, and nothing a caller writes should be mistaken for something the repository said.
131
+
132
+ The graph is never serialised and `DiscoverySnapshotV1` is unchanged. Insertion is sorted and every
133
+ score rounded, so metrics are identical across runs and after the input order is shuffled.
134
+ `pipelineVersion` becomes `1.4.0` with a `graph` analyzer version.
135
+ - 9a775a5: Give every file-backed entity its own content hash, and reuse unchanged entities between scans.
136
+
137
+ `EvidenceSchema.contentHash` had existed since the first schema and `discoverRepository` never
138
+ filled it: on this repository 0 of 369 entities carried one. Every cache and every overlay could
139
+ therefore be keyed only on "the whole repository changed", which is true between any two commits.
140
+ Now every `module`, `document` and `package` entity carries the hash of its file in its first
141
+ evidence item, and `external` entities carry none — a name in a manifest is not a file.
142
+
143
+ `discoverRepository({ previous })` accepts a snapshot from a previous scan and skips the TypeScript
144
+ and Markdown parses for files whose hash is unchanged. Reuse is only taken where it cannot change
145
+ the answer:
146
+
147
+ - an entity's own fields depend on its own bytes, so a hash match is enough for the entity;
148
+ - a relation depends on what else exists, so relation reuse also requires that the universe the
149
+ references resolve against is identical — module paths, packages and compiler options for a
150
+ module, and additionally document paths, area paths and which module declares each exported
151
+ symbol for a document. Both fingerprints are derived from the previous snapshot rather than
152
+ stored in it;
153
+ - the whole snapshot is refused unless it declares, and matches, this `pipelineVersion`, these
154
+ `analyzerVersions` and this `configurationHash`. An analyzer that learns to read more produces
155
+ different entities from identical bytes.
156
+
157
+ A replayed edge whose internal target is gone is dropped rather than carried — a renamed file must
158
+ not leave a graph asserting something the repository no longer contains — while an external or
159
+ unresolved endpoint is re-added, because it is in the snapshot only because the reused entity
160
+ referenced it.
161
+
162
+ Two `js-ts` facts only ever lived in a local variable, which made the aggregate `dynamic-imports`
163
+ and `runtime-wiring` entries unreproducible from the per-file ones — and a reused scan replays the
164
+ per-file ones. A literal `require` now sets the resolved-dynamic-import flag it always recorded
165
+ evidence for, and every observed runtime-wiring call leaves a per-file entry: `complete` when its
166
+ target is statically known, `not-analyzed` when it is not, where before a resolved call left no
167
+ record at all. Both make the aggregate derivable from what the snapshot actually carries.
168
+
169
+ One `coverage` entry with `scope: reused-entities` reports what a run reused and what it re-parsed,
170
+ so a fast run is explainable rather than suspicious. It is the only part of a snapshot that
171
+ describes the run rather than the repository: the entities, the relations and every other coverage
172
+ entry are byte-identical to a cold scan's. The CLI still scans cold, so its artifacts are unchanged
173
+ apart from the new entry. `pipelineVersion` becomes `1.5.0`, the `repository` analyzer `1.3.0` and `js-ts` `1.3.5`.
174
+ - 9a775a5: Read documentation with a real Markdown parser, and turn its prose into evidence-backed graph
175
+ edges.
176
+
177
+ Documentation used to be read with regular expressions: frontmatter by one, the `docbridge` block
178
+ by a hand-written YAML subset, and the prose not at all. Headings, links and inline code were
179
+ discarded — so on this repository, where 23 documents link to other documents and 14 cite source
180
+ paths, none of it produced a single edge.
181
+
182
+ A new `markdown` analyzer parses documents with remark (CommonMark plus GFM) and emits `observed`
183
+ relations with the file and line each claim was made on: `links-to` between documents,
184
+ `mentions` from a document to a module or package, and `mentions-symbol` from an inline code token
185
+ to the module that exports it. On this repository that is 154 `links-to`, 93 `mentions` and 50
186
+ `mentions-symbol` where there were none, and 55 of 104 documents now have an outgoing edge.
187
+
188
+ A symbol resolves to the module that declares it rather than a barrel that re-exports it, and a
189
+ name declared by two modules resolves to neither — the reference and its lines are reported as a
190
+ coverage note, because sending an agent to one of two possible definitions is worse than sending
191
+ it nowhere. Unresolved path-shaped references are matched with Jaro-Winkler and accepted only at
192
+ 0.92 or above with a single candidate, recorded as `confidence: 'fuzzy'`. Mentions inside a
193
+ `<!-- doc-bridge:generated -->` region are ignored, so Doc Bridge never reads its own output back
194
+ in as evidence. A document referencing more than 64 entities records `evidenceTruncated`.
195
+
196
+ Document entities now carry `title`, headings to depth three with their lines, a bounded
197
+ `summary`, `wordCount`, the frontmatter subset (`type`, `audience`, `owner`, `lifecycle`, `tier`),
198
+ any generated regions, and the file's content hash on its evidence. A document declaring
199
+ `audience` overrides the path heuristic that classifies it.
200
+
201
+ The `docbridge` block is now real YAML validated by a schema, so quoted lists, flow mappings,
202
+ anchors and multi-line strings work as they do everywhere else, and a schema violation names the
203
+ field. Every `DOCBRIDGE_*` diagnostic code is preserved, and a block YAML cannot read at all falls
204
+ back to the previous line-oriented scanner, which reports per line.
205
+
206
+ `pipelineVersion` becomes `1.2.0` and `analyzerVersions` gains `markdown`. The
207
+ `DiscoverySnapshotV1` envelope is unchanged.
208
+
209
+ Entity identity is consolidated into one module: `entityId` and `relationId` in
210
+ `src/discovery/identity.ts`, shared by the discovery analyzers and the retrieval projection, which
211
+ had grown a second copy. `projectedEntityId` (added in the unreleased corpus projection and never
212
+ published) is gone in favour of `entityId`.
213
+ - 9a775a5: Render the canonical artifacts as Markdown people can read, from templates rather than string
214
+ concatenation, and close the loop between what Doc Bridge writes and what it reads.
215
+
216
+ `ak-docs render <template> [--data <artifact>] [--output <path>]` ships five templates: `llms.txt`,
217
+ replacing the concatenation in the index builder byte for byte; `area`, one page per code area
218
+ with its purpose, modules, documents, related areas, checks and open findings; `ownership`, one
219
+ sidecar per ownership record; `change-digest`, the entities and documents whose content hash
220
+ moved since the last scan and the documents that should have moved with them; and
221
+ `overlay-review`, the pending agent proposals with their evidence links, with an explicit empty
222
+ state when no overlay exists. A project replaces any of them under `render.templates` without a
223
+ code change; `--print-template` prints the bundled source to start from.
224
+
225
+ Templates are `knap` 0.5 templates: parsed to an AST, interpreted without `eval`, and fed only
226
+ the variables Doc Bridge computes. The index pipeline is synchronous and knap's renderer is not,
227
+ so the AST is walked by a synchronous evaluator of Doc Bridge's own; a test renders every bundled
228
+ template through knap's engine as well and holds the two to identical bytes. Every bundled
229
+ template has a golden file, and rendering never calls an agent or reads the Registry.
230
+
231
+ Every generated Markdown region carries `<!-- doc-bridge:generated hash=… -->`. The Markdown
232
+ analyzer already skips mentions inside one; the documentation audit now recomputes the hash and
233
+ reports a region a person edited by hand as `GENERATED_REGION_EDITED` under
234
+ `generated-freshness`, so a regeneration never silently discards the edit. `llms.txt` carries no
235
+ marker and its bytes are unchanged for its existing consumers.
236
+ - 9a775a5: Answer an agent's question in one bounded MCP call, report findings in the shape the ecosystem
237
+ consumes, and stop the doctor from grading what it did not measure.
238
+
239
+ `knowledge.search { query, kinds?, limit?, explain?, budgetTokens? }` ranks the retrieval
240
+ projection with the same `searchIndex` the CLI uses — its results are what `ak-docs search`
241
+ prints for the same query and index, which a test compares — and adds a title and a body excerpt
242
+ to each. `knowledge.lookup { id | path, depth?, budgetTokens? }` returns, in one response, the
243
+ entity, its neighbours by relation kind (hierarchy included, up to three hops), the documents that
244
+ cover or mention it, the handoff `handoff.resolve` would return, the open diagnostics of the
245
+ latest reconciliation report that name it, and its evidence with excerpts. `format: 'text'` on
246
+ either renders the same payload through `formatRetrievedDocuments`.
247
+
248
+ When `budgetTokens` is present, both tools and `handoff.resolve` trim through `compileBudget`
249
+ (mirrored from `@agentskit/core`, which is an optional peer, and asserted identical to the real
250
+ function by test) in the declared order: evidence excerpts, then `related`, then neighbours, then
251
+ summaries. The response reports `tokens.total`, `fits`, the sections kept and dropped and
252
+ `tokenMethod: 'approximate'`. The entity, the evidence paths and hashes, the handoff fields and the
253
+ diagnostics are never dropped; a payload whose core exceeds the budget says `fits: false` rather
254
+ than truncating them. `AgentHandoffV1` gains an optional `budget` field. Every pre-existing tool
255
+ name, argument and payload is unchanged.
256
+
257
+ `ak-docs check --json --format finding` and `docbridge.diagnostics { format: 'finding' }` emit
258
+ every reconciliation diagnostic as a `Finding` from `@agentskit/core/finding` with severities from
259
+ `SEVERITY_ORDER` (`error → high`, `warn → medium`, `info → low`, nothing `critical`). The internal
260
+ diagnostic shapes do not change; this is a reporter.
261
+
262
+ The doctor measures three new dimensions and can lower the grade for them: reachability (the
263
+ share of the snapshot's document entities in the retrieval projection, 15 points), connectivity
264
+ (areas with a covering or mentioning document and documents with an edge into code, 15 points)
265
+ and the retrieval benchmark hit@3 over the golden suite at `retrieval.benchmark.suite` (10
266
+ points, `not-analyzed` and zero when no suite exists). The existing dimensions are rebalanced to
267
+ the remaining sixty. An A requires reachability at 100%, connectivity at 80% or more and a measured
268
+ hit@3 of 80% or more; on this repository the grade falls from 100/100 (A) to 91/100 (B), because
269
+ 20 of 39 areas have no document about them and 55 of 100 documents do not point at code. The
270
+ doctor's `ok` and exit code are unchanged.
271
+ - 9a775a5: Measure enrichment: what a run cost, what it invented, whether it improved retrieval at all — and
272
+ give the controlled study mechanical expectations, a third arm that reports its own readiness, and
273
+ tokens to first evidence.
274
+
275
+ The overlay reported what it accepted, which is the one number an agent cannot fail: a curator that
276
+ proposes a hundred things and has ninety rejected looked exactly like one that proposes ten good
277
+ ones. Nothing said whether any of it helped retrieval. And the study could not answer the question
278
+ either — its last round recorded zero semantic successes in both arms, because a task whose only
279
+ success criterion is a model's opinion produces no signal, and `registry-assisted` had been reserved
280
+ since the first suite without ever running.
281
+
282
+ `EnrichmentStats` now carries the whole shape of a run: counts per kind, a rejection histogram over
283
+ the closed reason list, cost as agent runs, input and output bytes, cache hit rate and measured wall
284
+ time, and `inventedReferences` — rejections that named something the repository does not contain,
285
+ counted apart from the rejection total because a curator wrong about a judgement and one making
286
+ things up are different problems. `enrichmentStability` compares a run with the previous one:
287
+ identical overlay hashes for a deterministic agent, and for a live model the share of proposal
288
+ identifiers present in both runs, over the union, so proposing fewer things does not read as more
289
+ stable. `stats` stays outside the overlay's content hash.
290
+
291
+ `ak-docs bench retrieval <suite> --overlay` and `ak-docs enrich --retrieval-delta` run the golden
292
+ suite twice over one snapshot — once with the accepted overlay projected, once without — and report
293
+ the delta in both text and JSON, with the case ids gained and lost at hit@3. Both project their own
294
+ indexes, so neither needs an index on disk. An overlay may leave retrieval unchanged and it may
295
+ improve it; if it lowers hit@3 the run exits 1 and says so, as a finding about the agent rather than
296
+ a new baseline.
297
+
298
+ A study task may declare `expectedEntities`, `expectedDocuments` and `retrievalQueries` as opaque
299
+ references, resolved to concrete entities and documents by a local `StudyExpectationsV1` file that
300
+ declares `scope: 'local'`, binds to the suite hash and is never published. `ak-docs study
301
+ expectations` turns the pair into an Open Eval Format suite and checks it with the same benchmark
302
+ that gates this repository's retrieval: an unresolved reference fails, and a task with no
303
+ expectations is reported unchecked rather than counted as a pass. A rubric item may now name the
304
+ mechanical check that decides it, and the model adjudicator receives only the items no checker can
305
+ settle — the settled ones travel beside them as context, not for review.
306
+
307
+ The assisted arm reports its own readiness. Missing provider, missing scenario or missing agent
308
+ identity make it unavailable, and its executions are then recorded as unavailable observations with
309
+ `errorCode: 'registry-unavailable'` rather than skipped or failed: a scenario absent from a ledger
310
+ is indistinguishable from one that was never planned. A missing `promptVersion` or `agentBudget` does
311
+ not cost the arm its run; it is reported as undeclared. `tokensToFirstEvidence` is a primary metric
312
+ per scenario, and the enrichment agent's own tokens, runs and cost are recorded apart from the
313
+ model's while still landing in the total.
314
+
315
+ The committed 24-task suite, run plan and ledgers are deliberately unchanged: the suite's hash is
316
+ bound to published artifacts, and the targets an expectations file would resolve belong to study
317
+ repositories that are not in this one.
318
+ - 6409c68: Add `ak-docs parity`: a registry of the claims this repository makes in public, the repository facts
319
+ they stand for, and a gate that fails when a public surface states something the repository has
320
+ moved past.
321
+
322
+ Four figures from the published A/B round appear in `README.md` and again in `docs/study/README.md`.
323
+ They agree today, and nothing made them agree: an edit to one, or a new round replacing the artifact
324
+ both quote, would leave two public surfaces stating a number the repository no longer measures, with
325
+ no mechanism for noticing but a person reading both pages on the same day.
326
+
327
+ `docs/parity/public-claims-v1.json` is a sealed registry. A claim names what it asserts, who owns
328
+ it, how it appears in prose (`{value}` inside a template, optionally worded differently per
329
+ surface), which surfaces must carry it, and where the canonical value comes from: a field in
330
+ `package.json`, a dotted path into a committed artifact, a sum across an array in one, a count over
331
+ the snapshot, a figure the doctor measured, or the presence of a CLI command. Numbers render the way
332
+ prose states them, and two transforms are signed on purpose — "18.46% fewer" and "39.75 seconds
333
+ lower" carry their direction in a word the checker cannot read, so a measurement that turns positive
334
+ stops resolving instead of matching the same digits for the opposite result.
335
+
336
+ The four outcomes stay apart because they need different actions: `PARITY_STALE` (a surface states a
337
+ value the repository moved past), `PARITY_MISSING` (a required surface omits the claim),
338
+ `PARITY_CONTRADICTION` (two public surfaces disagree — always blocking, and the one an agent cannot
339
+ resolve for itself) and `PARITY_NOT_ANALYZED` (the value could not be resolved: reported, never
340
+ counted as a pass). Every finding carries the claim's owner, the exact surface and line, both
341
+ values, a bounded redacted excerpt and a remediation. An exception accepts one finding on one
342
+ surface and requires a reason and an approver; it stays visible in the report rather than silencing
343
+ the claim.
344
+
345
+ `ak-docs parity [--claims <file>] [--json|--text]` exits 1 on a blocking finding, and CI runs it in
346
+ the dogfood step next to the index, the gate, the doctor and the retrieval benchmark. On this
347
+ repository the registry starts with seven claims over three surfaces, and the run that introduced it
348
+ found two real problems: a claim of mine pointed at the wrong field, and the command was not yet in
349
+ the CLI reference.
350
+
351
+ The report is publication-safe by construction — repository-relative paths, bounded excerpts,
352
+ secrets redacted, no document contents — and a test asserts that against a fixture containing a
353
+ secret-shaped string.
354
+ - 9a775a5: Project the repository's documents and modules into the index retrieval reads, and rank them with
355
+ field-weighted BM25.
356
+
357
+ `index.knowledge` previously held only the curated agent sidecars, while the discovery snapshot
358
+ held hundreds of documents and modules, so a query for an exported symbol or a file path had
359
+ nothing to resolve against — on the retrieval benchmark, none of the twenty exported-symbol
360
+ queries found its module and 47% of all queries returned nothing at all.
361
+
362
+ Every documentation file and source module is now an entry carrying its own content hash, its
363
+ tags, and (for a module) its exported symbols, projected from the same repository walk as the
364
+ discovery snapshot so the two cannot disagree about what exists. Ranking is field-weighted BM25
365
+ plus boosts for exact identity and multiplicative priors for query shape, over one tokenizer
366
+ shared by indexing and querying: English and Portuguese stopwords, accent folding, plural
367
+ collapsing, identifier and path expansion, and CJK bigrams. Weights and BM25 parameters are
368
+ configurable under `retrieval` and recorded in `index.retrieval`, so a retuned ranking is a
369
+ visibly different artifact.
370
+
371
+ Measured against the committed benchmark: hit@1 21.7% → 76.7%, hit@3 23.3% → 83.3%, mean
372
+ reciprocal rank 0.228 → 0.812, zero-result rate 46.7% → 5.0%, exported-symbol queries 0% → 100%.
373
+
374
+ Queries also stop rebuilding the index to check freshness. The index records an `inputs`
375
+ fingerprint of the files and configuration it was built from, so a query re-hashes the inputs
376
+ instead — `loadFreshDocBridgeIndex` on this repository went from over a second to about 170 ms. An
377
+ index written before `inputs` existed is still validated by the previous rebuild-and-compare.
378
+ - 9a775a5: Make the retrieval index a projection of the snapshot, explain every ranking, and derive handoffs
379
+ for any entity from the graph.
380
+
381
+ `buildDocBridgeIndex` used to run a scanner of its own: it walked the repository a second time,
382
+ parsed every module and document again, and produced records that shared nothing with the
383
+ snapshot but a file path — two views of one repository, built by two pipelines, free to disagree.
384
+ The index now carries `projection`, a `RetrievalIndexV1` built by `projectRetrievalIndex` as a pure
385
+ function of the snapshot, the accepted overlay and the configuration. Every entry is a snapshot
386
+ entity (or a route the configuration declares) with the entity's own content hash, provenance and
387
+ confidence, its graph position (PageRank, covered-by, mentioned-by, area, package, edges) and the
388
+ text the lexical ranker indexes. The projection's content hash is over its three input hashes, so
389
+ `IndexStaleError` keeps working; `knowledge[]` is still written and stays in step, without body
390
+ text, which now lives once. The index has no scanner of its own; `projectRepositoryCorpus` is gone
391
+ and `repositoryInputs` remains as the freshness fingerprint.
392
+
393
+ `searchIndex` keeps its signature and gains `{ explain, agent }`. Ranking (`src/retrieval/rank.ts`)
394
+ is BM25 over `title`, `headings`, `symbols`, `path`, `aliases`, `summary` and `body`, times the
395
+ query-shape prior, plus exact-identity boosts, graph proximity (scaled by the anchor's strength),
396
+ log-scaled canonicality, the `--agent` audience prior, and a zero-weighted hook for accepted agent
397
+ signals. `ak-docs search <term> --explain` names every component's contribution and the matched
398
+ terms per field; explaining never changes the ranking. Every result carries evidence, provenance
399
+ and confidence, where confidence is the entry's own for a direct match and the weaker of the entry
400
+ and the surfacing relation when a relation alone surfaced it. Per-token identity boosts apply only
401
+ to queries of at most two tokens: a sentence does not name a thing by containing one of its tokens.
402
+ On this repository's golden suite hit@3 rises from 83.3% to 88.3%, hit@1 from 76.7% to 78.3% and
403
+ MRR from 0.812 to 0.829.
404
+
405
+ `handoffForEntity(index, id, config, { root })` replaces `handoffForPackage` and answers for a
406
+ package, an area, a module or a document, by entity id, ownership id, alias or path. `editRoots` is
407
+ the unit itself or a module's area; `startHere` is the ownership agent document, then a document
408
+ that covers the target, then one that mentions it, then one links-to hop away, most canonical
409
+ first; `readBeforeEditing` adds the next two and `AGENTS.md`; `checks` report their origin in
410
+ `metadata.checksSource`, which the index builder now records where the decision is made;
411
+ `related` lists the strongest importing and imported areas with the import that proves each;
412
+ `explain` names the relation behind every field. `AgentHandoffV1` stays byte-compatible:
413
+ `related`, `explain`, `evidence` and `metadata` are optional additions and `target.type` gains
414
+ `area` and `document`. A `covers` declaration now also resolves by an area, module or document
415
+ path.
416
+
417
+ `createDocBridgeRetriever` returns `RetrievedDocument[]` from `@agentskit/core` with
418
+ `metadata: { kind, path, evidence, explain, confidence }`, so `createHybridRetriever` and
419
+ `formatRetrievedDocuments` consume Doc Bridge with no adapter — exercised against the real
420
+ packages. The original `retrieve('query', { limit })` still works.
421
+
422
+ The default field weights change with the field set (`id`, `tags` and `description` no longer
423
+ exist as fields; `headings`, `aliases` and `summary` do), `CORPUS_PROJECTION_VERSION` becomes 2 so
424
+ an index built by older code is stale by version, and a projected index is about three times the
425
+ size of the old one on this repository, because it now carries every entry's graph edges.
426
+
427
+ ### Patch Changes
428
+
429
+ - 93bc2ad: Stop writing an index that Doc Bridge's own reader refuses.
430
+
431
+ `knowledge[]` and `projection.entries` in `doc-bridge-index-v1` describe the same entries, and
432
+ their bounds disagreed: 10 000 against 50 000. A monorepo that projects 10 909 entries therefore
433
+ got an index `ak-docs index` reported building successfully and every reader rejected — `doctor`,
434
+ `search` and the MCP server all failed with a schema dump naming an array, on a repository whose
435
+ index was sitting on disk.
436
+
437
+ Both bounds are now one exported constant, `RETRIEVAL_MAX_ENTRIES`, shared by the Zod schema, the
438
+ published JSON Schema and the builder, and a test asserts the two agree rather than asserting the
439
+ number. The builder checks the bound before it writes, so a corpus that genuinely exceeds it is
440
+ reported where the count and the remedy are both known — narrow `corpus.*.include`, or split the
441
+ repository across more than one index — instead of becoming an unreadable file.
442
+ - 93bc2ad: Make Markdown reference resolution scale, so a large repository can be indexed at all.
443
+
444
+ Dogfooding Doc Bridge on a monorepo of 4 100 documents, 9 240 TypeScript files and 102 packages
445
+ found that `ak-docs scan` and `ak-docs index` did not complete — not slowly, but not at all within
446
+ fifteen minutes. The cost was superlinear in corpus size and concentrated in one place: a CPU
447
+ profile of a 401-document corpus put 56.5% of samples in `fuzzyMatchList`, the near-miss resolver
448
+ for path-shaped references.
449
+
450
+ Two things were wrong. The analyzer rebuilt the candidate universe — every document, module and
451
+ area path — once per document, which on that monorepo is tens of millions of string copies before
452
+ any analysis happens; the universe is now built once per run and passed in as
453
+ `MarkdownResolution.pathIndex`. And every unresolved reference ran a full Jaro-Winkler scan over
454
+ that universe, where almost every candidate cannot reach the 0.92 threshold for reasons that cost
455
+ far less to check than a similarity computation.
456
+
457
+ `createFuzzyCandidateIndex` precomputes, per candidate, its length and its character counts over a
458
+ fixed alphabet. A query then visits only the lengths that can pass, and within those skips any
459
+ candidate whose shared-character count is too low. Both tests are upper bounds on Jaro's match
460
+ count — `m` cannot exceed the shorter string, and cannot exceed the multiset intersection — so a
461
+ candidate they drop provably could not have matched. The filter is behaviour-preserving including
462
+ the order of tied scores, and a test asserts that a list universe and an index universe return
463
+ identical results over 646 candidates at four thresholds.
464
+
465
+ Measured on the same corpora: 908 documents went from 151 to 25 seconds, and the monorepo that
466
+ did not finish in fifteen minutes now scans in 100 seconds. `fuzzyMatchList` and
467
+ `resolveFuzzyReference` still accept a plain array, so the public contract and the mirror of
468
+ `@agentskit/core/fuzzy-match` are unchanged.
469
+
470
+ ## 1.8.0
471
+
472
+ ### Minor Changes
473
+
474
+ - 4ed42e3: Add configurable documentation tiers, criticality metadata checks, and independent quality-dimension assessments to the documentation audit.
475
+ - ee756a1: Add a bounded, shell-free generic CLI adapter for AgentsKit Registry proposals.
476
+ - ee756a1: Add a configurable documentation audit command with measurable quality, coverage, structure-gap, stale, contradiction, redundancy, and generated-document freshness-boundary findings.
477
+ - 4ed42e3: Add deterministic longitudinal study metrics with subgroup comparisons, uncertainty, missing-data handling, quality guardrails, and anonymization-safe cost measurements.
478
+ - 4ed42e3: Add versioned, anonymization-safe study protocol and historical evidence registry contracts with CLI validation and summaries.
479
+ - 4ed42e3: Add bounded controlled-study run plans, isolated command execution, provenance-safe observations, and idempotent observation ledgers.
480
+ - 4ed42e3: Add a versioned controlled-study task suite with deterministic variant assignment and outcome adjudication contracts.
481
+ - 4ed42e3: Add content-addressed controlled-study verification bindings for provenance, privacy, budget, recovery, and publication-safe evidence.
482
+
483
+ ### Patch Changes
484
+
485
+ - 5656632: Adopt the provider-neutral `@agentskit/harness@0.9.0` for fail-closed verification, YOLO intermediate execution, immutable evidence, and explicit UI and tracking gates.
486
+ - c1fed28: Refresh supported runtime and documentation dependencies, harden GitHub Actions pins, and keep the README freshness contract synchronized.
487
+ - 4ed42e3: Reject Registry-agent proposals that reference unknown diagnostics or evidence outside the supplied artifacts, and document alternate-agent and human-approval boundaries.
488
+ - ee756a1: Allow failed or cancelled workflow runs with changed inputs to be invalidated and retried, and bump the discovery pipeline identity when report artifacts change.
489
+ - 4ed42e3: Add a generic bounded CLI adapter and resumable `study run` execution for hosted model CLIs and AgentsKit Registry agents without requiring Ollama.
490
+
3
491
  ## 1.7.45
4
492
 
5
493
  ### Patch Changes
package/CONTRIBUTING.md CHANGED
@@ -1,3 +1,10 @@
1
+ ---
2
+ owner: maintainers
3
+ lifecycle: active
4
+ sourceOfTruth: CONTRIBUTING.md
5
+ validationPath: pnpm typecheck && pnpm test
6
+ ---
7
+
1
8
  # Contributing
2
9
 
3
10
  Thanks for helping improve `@agentskit/doc-bridge`.
@@ -28,6 +35,22 @@ pnpm build
28
35
  - Update docs and `CHANGELOG.md` when behavior changes.
29
36
  - Keep examples public and reproducible.
30
37
 
38
+ ## Why contribute?
39
+
40
+ Doc Bridge helps humans and coding agents navigate large repositories with less context and stronger evidence. The study is intentionally open and anonymized so contributors can improve the measurement surface as well as the product.
41
+
42
+ High-impact contribution areas:
43
+
44
+ - language and framework analyzers;
45
+ - documentation quality rules and contradiction detectors;
46
+ - architecture relation extraction;
47
+ - CLI, MCP, and documentation adapters;
48
+ - executable acceptance checks;
49
+ - anonymized benchmark tasks and replications;
50
+ - accessibility and report improvements.
51
+
52
+ Start with the [study overview](docs/study/README.md), run the chart check, and use the smallest reproducible example for a proposed change.
53
+
31
54
  ## Releases
32
55
 
33
56
  Use Changesets for versioned changes. A merged changeset on `master` starts the