ai-capability-framework 1.0.3 → 1.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.
Files changed (246) hide show
  1. package/CHANGELOG.md +42 -0
  2. package/README.md +38 -30
  3. package/ROADMAP.md +14 -0
  4. package/dist/cli.d.ts.map +1 -1
  5. package/dist/cli.js +32 -1
  6. package/dist/discovery/bindings.d.ts +7 -0
  7. package/dist/discovery/bindings.d.ts.map +1 -0
  8. package/dist/discovery/bindings.js +24 -0
  9. package/dist/discovery/budget.d.ts +17 -0
  10. package/dist/discovery/budget.d.ts.map +1 -0
  11. package/dist/discovery/budget.js +77 -0
  12. package/dist/discovery/configuration.d.ts +10 -0
  13. package/dist/discovery/configuration.d.ts.map +1 -0
  14. package/dist/discovery/configuration.js +63 -0
  15. package/dist/discovery/corpus.d.ts +8 -0
  16. package/dist/discovery/corpus.d.ts.map +1 -0
  17. package/dist/discovery/corpus.js +64 -0
  18. package/dist/discovery/diagnostics.d.ts +15 -0
  19. package/dist/discovery/diagnostics.d.ts.map +1 -0
  20. package/dist/discovery/diagnostics.js +11 -0
  21. package/dist/discovery/discoverer.d.ts +23 -0
  22. package/dist/discovery/discoverer.d.ts.map +1 -0
  23. package/dist/discovery/discoverer.js +261 -0
  24. package/dist/discovery/embedding-configuration.d.ts +12 -0
  25. package/dist/discovery/embedding-configuration.d.ts.map +1 -0
  26. package/dist/discovery/embedding-configuration.js +81 -0
  27. package/dist/discovery/embedding-types.d.ts +75 -0
  28. package/dist/discovery/embedding-types.d.ts.map +1 -0
  29. package/dist/discovery/embedding-types.js +1 -0
  30. package/dist/discovery/embeddings.d.ts +38 -0
  31. package/dist/discovery/embeddings.d.ts.map +1 -0
  32. package/dist/discovery/embeddings.js +71 -0
  33. package/dist/discovery/evaluation-validation.d.ts +8 -0
  34. package/dist/discovery/evaluation-validation.d.ts.map +1 -0
  35. package/dist/discovery/evaluation-validation.js +19 -0
  36. package/dist/discovery/evaluation.d.ts +84 -0
  37. package/dist/discovery/evaluation.d.ts.map +1 -0
  38. package/dist/discovery/evaluation.js +310 -0
  39. package/dist/discovery/export.d.ts +14 -0
  40. package/dist/discovery/export.d.ts.map +1 -0
  41. package/dist/discovery/export.js +81 -0
  42. package/dist/discovery/facade.d.ts +82 -0
  43. package/dist/discovery/facade.d.ts.map +1 -0
  44. package/dist/discovery/facade.js +266 -0
  45. package/dist/discovery/fingerprint.d.ts +71 -0
  46. package/dist/discovery/fingerprint.d.ts.map +1 -0
  47. package/dist/discovery/fingerprint.js +67 -0
  48. package/dist/discovery/index-builder.d.ts +3 -0
  49. package/dist/discovery/index-builder.d.ts.map +1 -0
  50. package/dist/discovery/index-builder.js +129 -0
  51. package/dist/discovery/index-validation.d.ts +12 -0
  52. package/dist/discovery/index-validation.d.ts.map +1 -0
  53. package/dist/discovery/index-validation.js +117 -0
  54. package/dist/discovery/index.d.ts +32 -0
  55. package/dist/discovery/index.d.ts.map +1 -0
  56. package/dist/discovery/index.js +18 -0
  57. package/dist/discovery/json-snapshot.d.ts +3 -0
  58. package/dist/discovery/json-snapshot.d.ts.map +1 -0
  59. package/dist/discovery/json-snapshot.js +11 -0
  60. package/dist/discovery/lexical.d.ts +12 -0
  61. package/dist/discovery/lexical.d.ts.map +1 -0
  62. package/dist/discovery/lexical.js +26 -0
  63. package/dist/discovery/metadata.d.ts +4 -0
  64. package/dist/discovery/metadata.d.ts.map +1 -0
  65. package/dist/discovery/metadata.js +33 -0
  66. package/dist/discovery/ranking.d.ts +7 -0
  67. package/dist/discovery/ranking.d.ts.map +1 -0
  68. package/dist/discovery/ranking.js +68 -0
  69. package/dist/discovery/replay.d.ts +50 -0
  70. package/dist/discovery/replay.d.ts.map +1 -0
  71. package/dist/discovery/replay.js +175 -0
  72. package/dist/discovery/retrieval-policy.d.ts +5 -0
  73. package/dist/discovery/retrieval-policy.d.ts.map +1 -0
  74. package/dist/discovery/retrieval-policy.js +10 -0
  75. package/dist/discovery/router.d.ts +39 -0
  76. package/dist/discovery/router.d.ts.map +1 -0
  77. package/dist/discovery/router.js +98 -0
  78. package/dist/discovery/selection-attempt.d.ts +20 -0
  79. package/dist/discovery/selection-attempt.d.ts.map +1 -0
  80. package/dist/discovery/selection-attempt.js +39 -0
  81. package/dist/discovery/selection-cards.d.ts +12 -0
  82. package/dist/discovery/selection-cards.d.ts.map +1 -0
  83. package/dist/discovery/selection-cards.js +79 -0
  84. package/dist/discovery/selection-configuration.d.ts +18 -0
  85. package/dist/discovery/selection-configuration.d.ts.map +1 -0
  86. package/dist/discovery/selection-configuration.js +71 -0
  87. package/dist/discovery/selection-response.d.ts +13 -0
  88. package/dist/discovery/selection-response.d.ts.map +1 -0
  89. package/dist/discovery/selection-response.js +47 -0
  90. package/dist/discovery/selection-types.d.ts +18 -0
  91. package/dist/discovery/selection-types.d.ts.map +1 -0
  92. package/dist/discovery/selection-types.js +1 -0
  93. package/dist/discovery/selection.d.ts +6 -0
  94. package/dist/discovery/selection.d.ts.map +1 -0
  95. package/dist/discovery/selection.js +145 -0
  96. package/dist/discovery/types.d.ts +291 -0
  97. package/dist/discovery/types.d.ts.map +1 -0
  98. package/dist/discovery/types.js +1 -0
  99. package/dist/discovery/usage.d.ts +2 -0
  100. package/dist/discovery/usage.d.ts.map +1 -0
  101. package/dist/discovery/usage.js +1 -0
  102. package/dist/discovery/vectors.d.ts +5 -0
  103. package/dist/discovery/vectors.d.ts.map +1 -0
  104. package/dist/discovery/vectors.js +43 -0
  105. package/dist/discovery/versions.d.ts +37 -0
  106. package/dist/discovery/versions.d.ts.map +1 -0
  107. package/dist/discovery/versions.js +36 -0
  108. package/dist/evals-live/live-eval-runner.d.ts +1 -0
  109. package/dist/evals-live/live-eval-runner.d.ts.map +1 -1
  110. package/dist/evals-live/live-eval-runner.js +12 -1
  111. package/dist/evals-live/types.d.ts +3 -0
  112. package/dist/evals-live/types.d.ts.map +1 -1
  113. package/dist/generated/manifest-types.d.ts +3655 -0
  114. package/dist/generated/manifest-types.d.ts.map +1 -1
  115. package/dist/loader.d.ts.map +1 -1
  116. package/dist/loader.js +8 -0
  117. package/dist/mcp-server/server.d.ts.map +1 -1
  118. package/dist/mcp-server/server.js +11 -2
  119. package/dist/mcp-server/types.d.ts +4 -0
  120. package/dist/mcp-server/types.d.ts.map +1 -1
  121. package/dist/observability/redaction.d.ts.map +1 -1
  122. package/dist/observability/redaction.js +6 -2
  123. package/dist/observability/types.d.ts +1 -1
  124. package/dist/observability/types.d.ts.map +1 -1
  125. package/dist/openai/index.d.ts +2 -0
  126. package/dist/openai/index.d.ts.map +1 -1
  127. package/dist/openai/index.js +1 -0
  128. package/dist/openai/responses-runner.d.ts +1 -1
  129. package/dist/openai/responses-runner.d.ts.map +1 -1
  130. package/dist/openai/responses-runner.js +134 -7
  131. package/dist/openai/selection-client.d.ts +28 -0
  132. package/dist/openai/selection-client.d.ts.map +1 -0
  133. package/dist/openai/selection-client.js +95 -0
  134. package/dist/openai/tool-loop.js +1 -1
  135. package/dist/openai/types.d.ts +19 -2
  136. package/dist/openai/types.d.ts.map +1 -1
  137. package/dist/replay/discovery-snapshot.d.ts +10 -0
  138. package/dist/replay/discovery-snapshot.d.ts.map +1 -0
  139. package/dist/replay/discovery-snapshot.js +17 -0
  140. package/dist/replay/recorder.d.ts.map +1 -1
  141. package/dist/replay/recorder.js +4 -0
  142. package/dist/replay/redaction.js +5 -1
  143. package/dist/replay/replayer.d.ts.map +1 -1
  144. package/dist/replay/replayer.js +14 -1
  145. package/dist/replay/types.d.ts +3 -0
  146. package/dist/replay/types.d.ts.map +1 -1
  147. package/dist/replay/validation.d.ts.map +1 -1
  148. package/dist/replay/validation.js +6 -0
  149. package/dist/runtime/bounded-json.d.ts +4 -0
  150. package/dist/runtime/bounded-json.d.ts.map +1 -0
  151. package/dist/runtime/bounded-json.js +74 -0
  152. package/dist/runtime/eligibility.d.ts +4 -0
  153. package/dist/runtime/eligibility.d.ts.map +1 -0
  154. package/dist/runtime/eligibility.js +128 -0
  155. package/dist/runtime/index.d.ts +5 -1
  156. package/dist/runtime/index.d.ts.map +1 -1
  157. package/dist/runtime/index.js +2 -0
  158. package/dist/runtime/provider-attempt.d.ts +11 -0
  159. package/dist/runtime/provider-attempt.d.ts.map +1 -0
  160. package/dist/runtime/provider-attempt.js +221 -0
  161. package/dist/runtime/provider-run.d.ts +10 -0
  162. package/dist/runtime/provider-run.d.ts.map +1 -0
  163. package/dist/runtime/provider-run.js +123 -0
  164. package/dist/runtime/provider-stop.d.ts +9 -0
  165. package/dist/runtime/provider-stop.d.ts.map +1 -0
  166. package/dist/runtime/provider-stop.js +28 -0
  167. package/dist/runtime/provider-types.d.ts +189 -0
  168. package/dist/runtime/provider-types.d.ts.map +1 -0
  169. package/dist/runtime/provider-types.js +1 -0
  170. package/dist/runtime/provider-usage.d.ts +9 -0
  171. package/dist/runtime/provider-usage.d.ts.map +1 -0
  172. package/dist/runtime/provider-usage.js +69 -0
  173. package/dist/runtime/router.d.ts.map +1 -1
  174. package/dist/runtime/router.js +3 -118
  175. package/dist/runtime/types.d.ts +9 -0
  176. package/dist/runtime/types.d.ts.map +1 -1
  177. package/dist/types.d.ts +1 -1
  178. package/dist/types.d.ts.map +1 -1
  179. package/dist/validator.d.ts +3 -0
  180. package/dist/validator.d.ts.map +1 -1
  181. package/dist/validator.js +32 -0
  182. package/docs/api/public-api-policy.md +10 -0
  183. package/docs/api/stable-workflow.md +58 -0
  184. package/docs/api.md +7 -0
  185. package/docs/capability-manifests.md +24 -0
  186. package/docs/development.md +22 -0
  187. package/docs/discovery.md +186 -0
  188. package/docs/evals/discovery-live.md +199 -0
  189. package/docs/evals/discovery-qualification.md +158 -0
  190. package/docs/evals/overview.md +9 -0
  191. package/docs/getting-started/installation.md +11 -12
  192. package/docs/getting-started/openai-quickstart.md +16 -5
  193. package/docs/getting-started/provider-neutral-quickstart.md +247 -88
  194. package/docs/getting-started/quickstart.md +8 -30
  195. package/docs/index.md +10 -0
  196. package/docs/release.md +29 -5
  197. package/docs/runtime.md +27 -0
  198. package/docs/start-here.md +23 -134
  199. package/examples/12-capability-discovery-selection/README.md +346 -0
  200. package/examples/12-capability-discovery-selection/customer-cases.mjs +52 -0
  201. package/examples/12-capability-discovery-selection/customer-harness.mjs +91 -0
  202. package/examples/12-capability-discovery-selection/customer-request-example.mjs +320 -0
  203. package/examples/12-capability-discovery-selection/discovery-example.mjs +175 -0
  204. package/examples/12-capability-discovery-selection/discovery-fixtures/three-domains.suite.json +7887 -0
  205. package/examples/12-capability-discovery-selection/discovery-fixtures/three-domains.v2.suite.json +8167 -0
  206. package/examples/12-capability-discovery-selection/discovery-fixtures/three-domains.v3.suite.json +8342 -0
  207. package/examples/12-capability-discovery-selection/evaluation/application.mjs +305 -0
  208. package/examples/12-capability-discovery-selection/evaluation/campaign.mjs +248 -0
  209. package/examples/12-capability-discovery-selection/evaluation/clients.mjs +433 -0
  210. package/examples/12-capability-discovery-selection/evaluation/continuation.mjs +208 -0
  211. package/examples/12-capability-discovery-selection/evaluation/durable-budget.mjs +420 -0
  212. package/examples/12-capability-discovery-selection/evaluation/freeze.mjs +9 -0
  213. package/examples/12-capability-discovery-selection/evaluation/harness.mjs +618 -0
  214. package/examples/12-capability-discovery-selection/evaluation/mock-host.mjs +260 -0
  215. package/examples/12-capability-discovery-selection/evaluation/preflight.mjs +115 -0
  216. package/examples/12-capability-discovery-selection/evaluation/qualification-workflows.mjs +87 -0
  217. package/examples/12-capability-discovery-selection/evaluation/regrade.mjs +281 -0
  218. package/examples/12-capability-discovery-selection/evaluation/report.mjs +517 -0
  219. package/examples/12-capability-discovery-selection/evaluation/runner.mjs +613 -0
  220. package/examples/12-capability-discovery-selection/evaluation/saved-campaign.mjs +385 -0
  221. package/examples/12-capability-discovery-selection/evaluation/wording.mjs +115 -0
  222. package/examples/12-capability-discovery-selection/evaluation/workflow-application.mjs +378 -0
  223. package/examples/12-capability-discovery-selection/evaluation/workflow-cases.mjs +90 -0
  224. package/examples/12-capability-discovery-selection/evaluation-example.mjs +154 -0
  225. package/examples/12-capability-discovery-selection/hybrid-example.mjs +174 -0
  226. package/examples/12-capability-discovery-selection/mock-embeddings.mjs +101 -0
  227. package/examples/12-capability-discovery-selection/mock-selection.mjs +78 -0
  228. package/examples/12-capability-discovery-selection/pipeline-example.mjs +496 -0
  229. package/examples/12-capability-discovery-selection/retrieval-cases.mjs +31 -0
  230. package/examples/12-capability-discovery-selection/run-campaign-mock.mjs +40 -0
  231. package/examples/12-capability-discovery-selection/run-customer-mock.mjs +15 -0
  232. package/examples/12-capability-discovery-selection/run-evaluation-live.mjs +10 -0
  233. package/examples/12-capability-discovery-selection/run-evaluation-mock.mjs +3 -0
  234. package/examples/12-capability-discovery-selection/run-evaluation-regrade.mjs +71 -0
  235. package/examples/12-capability-discovery-selection/run-hybrid-mock.mjs +3 -0
  236. package/examples/12-capability-discovery-selection/run-mock.mjs +3 -0
  237. package/examples/12-capability-discovery-selection/run-pipeline-mock.mjs +2 -0
  238. package/examples/12-capability-discovery-selection/run-selector-mock.mjs +3 -0
  239. package/examples/12-capability-discovery-selection/selection-example.mjs +88 -0
  240. package/package.json +17 -4
  241. package/schemas/discovery/embedding-index.schema.json +71 -0
  242. package/schemas/discovery/eval-observations.schema.json +409 -0
  243. package/schemas/discovery/eval-suite.schema.json +375 -0
  244. package/schemas/discovery/metadata.schema.json +30 -0
  245. package/schemas/discovery/selection-response.schema.json +47 -0
  246. package/schemas/replay/discovery-snapshot.schema.json +335 -0
package/CHANGELOG.md CHANGED
@@ -4,6 +4,48 @@ All notable public changes to AI Capability Framework are documented here.
4
4
 
5
5
  ## Unreleased
6
6
 
7
+ ## 1.1.0 - 2026-10-17
8
+
9
+ - Fixed the installed CLI's POSIX symlink entrypoint so `npx aicf` runs commands instead
10
+ of silently returning. Programmatic CLI imports remain side-effect-free.
11
+
12
+ - Stabilized the recommended lexical/native search-to-tool workflow and its named
13
+ runtime/provider contracts. Advanced APIs retain their documented maturity; hybrid
14
+ remains experimental and dedicated selection optional.
15
+ - Made installed-package onboarding primary, with a complete manifest and mock app
16
+ checked directly from the published documentation in fresh consumers.
17
+ - Corrected obsolete checkout-only guidance and a nonexistent registry-helper import.
18
+ Retrieval behavior, authorization, approval boundaries and model configuration are
19
+ unchanged. Frozen qualification evidence is reused without new live trials.
20
+
21
+ ## 1.1.0-rc.1 - 2026-10-17
22
+
23
+ - Published discovery as release-candidate public, with lexical retrieval and ordinary
24
+ model tool selection as the recommended default. Dedicated selection is optional.
25
+ - Documented the tested synthetic configuration: both lexical modes qualify after a
26
+ separately versioned offline wording correction; hybrid remains experimental and
27
+ opt-in because its incremental-gain gate was not met. See the
28
+ [qualification report](docs/evals/discovery-qualification.md).
29
+ - Tightened registry-error handling and retained tag-only OIDC publication to next. No
30
+ model defaults, retrieval scoring or application deployment changed.
31
+
32
+ - Corrected the synthetic workflow app's planning, terminal dependency states and
33
+ response grading. Added versioned readiness fixtures, fresh qualification families,
34
+ and a remaining-budget continuation protocol. These offline changes preserve
35
+ historical live results and do not qualify a model or change framework defaults.
36
+
37
+ - Added scoped discovery evaluation reports, corrected versioned domain fixtures, and
38
+ opt-in live campaign tooling with durable budgets and independent per-mode gates.
39
+ Default invocation validates offline; synthetic campaign results do not qualify
40
+ models.
41
+
42
+ - Added the optional release-candidate discovery subpath with task search, reusable
43
+ task-bound routers, explicit hybrid retrieval and dedicated selection, shared-run
44
+ accounting, metadata tracing, and bounded replay. Default routing remains unchanged.
45
+ - Added portable no-key customer-request examples, public discovery schemas, and frozen
46
+ synthetic evaluation fixtures. Mock integration and offline metrics do not qualify
47
+ real-model retrieval or selection quality.
48
+
7
49
  ## 1.0.3 - 2026-09-07
8
50
 
9
51
  - Updated the resolved `fast-uri` dependency to `3.1.7` to address the high-severity
package/README.md CHANGED
@@ -110,40 +110,23 @@ In plain terms:
110
110
 
111
111
  ## Try It
112
112
 
113
- Install and validate the public examples:
113
+ Start in a new project:
114
114
 
115
- ```bash
116
- npm install
117
- npm run validate
118
- ```
119
-
120
- Build the CLI and inspect the example registry:
121
-
122
- ```bash
123
- npm run build
124
- node dist/cli.js inspect examples
115
+ ```sh
116
+ npm init -y
117
+ npm install ai-capability-framework
118
+ node node_modules/ai-capability-framework/examples/12-capability-discovery-selection/run-customer-mock.mjs
125
119
  ```
126
120
 
127
- Export OpenAI Responses function tools without calling a model:
128
-
129
- ```bash
130
- node dist/cli.js openai-tools examples --context examples/support/openai/context.support_agent.json
131
- ```
121
+ The mock flow reads a ticket, carries its order ID into refund preparation, and returns
122
+ a preview awaiting approval. It exposes no commit and makes no real provider calls. No
123
+ repository checkout, framework build or optional provider SDK is required.
132
124
 
133
- Run the public mock runtime flow:
134
-
135
- ```bash
136
- node examples/runtime-support-billing/run-mock.mjs
137
- ```
138
-
139
- Run deterministic evals:
140
-
141
- ```bash
142
- node dist/cli.js eval examples --results examples/eval-results/public.results.passing.json
143
- ```
144
-
145
- For expected output excerpts and what each command proves, use
146
- [Start here](docs/start-here.md).
125
+ Follow the
126
+ [complete first-app walkthrough](docs/getting-started/provider-neutral-quickstart.md) to
127
+ author a capability, load a registry, register a handler and use the stable
128
+ lexical/native workflow. [Repository development](docs/development.md) has separate
129
+ build and validation commands.
147
130
 
148
131
  ## Documentation Map
149
132
 
@@ -297,3 +280,28 @@ certification is documented in
297
280
  ## License
298
281
 
299
282
  MIT
283
+
284
+ ## Find capabilities for a task
285
+
286
+ Install the stable framework:
287
+
288
+ ```sh
289
+ npm install ai-capability-framework
290
+ ```
291
+
292
+ Lexical retrieval with the ordinary model/tool loop is the recommended default. The
293
+ [qualification report](docs/evals/discovery-qualification.md) records the tested lexical
294
+ results and the unmet hybrid incremental-gain gate. Hybrid remains experimental and
295
+ opt-in; dedicated selection remains optional.
296
+
297
+ Use the [stable lexical/native workflow](docs/api/stable-workflow.md) and optional
298
+ [discovery API](docs/discovery.md) when your application AI decomposes a customer
299
+ request into tasks. Search each ready task and pass its result-bound router to the
300
+ ordinary model/tool loop. Lexical search needs only a registry, task IDs/text, and
301
+ existing runtime context. Hybrid retrieval and dedicated selection are optional and
302
+ require caller-supplied model access and budgets.
303
+
304
+ Run the
305
+ [complete customer-request example](examples/12-capability-discovery-selection/README.md)
306
+ with deterministic mocks and no provider key. Retrieval scores never authorize execution
307
+ or guarantee a suitable first candidate.
package/ROADMAP.md CHANGED
@@ -24,3 +24,17 @@ signing implementation.
24
24
  Future work should be driven by real adopter feedback and should preserve the same
25
25
  architecture: AICF owns capability safety contracts and host applications own production
26
26
  systems, credentials, side effects, and deployment.
27
+
28
+ ## Capability Discovery
29
+
30
+ The stable lexical/native workflow supports application-produced tasks, eligible
31
+ shortlists, and ordinary model tool selection. Hybrid retrieval and dedicated selection
32
+ remain explicit. No-key examples, a frozen synthetic dataset, and packed consumer checks
33
+ cover integration. The tested synthetic configuration qualifies both lexical modes after
34
+ an offline wording correction. Lexical/native is recommended; hybrid remains
35
+ experimental because incremental benefit was not qualified. See the
36
+ [qualification report](docs/evals/discovery-qualification.md). Application-specific
37
+ qualification and adoption remain separate from framework publication. Normal npm
38
+ installation includes the stable workflow; advanced features retain their own maturity
39
+ labels. The active framework roadmap is complete when installed-package usability and
40
+ verified stable publication pass; application migrations are outside its scope.
package/dist/cli.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAuGA,MAAM,WAAW,aAAa;IAC5B,MAAM,CAAC,EAAE;QAAE,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,CAAC;IAC7C,MAAM,CAAC,EAAE;QAAE,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,CAAC;CAC9C;AA4BD,wBAAsB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,OAAO,GAAE,aAAkB,GAAG,OAAO,CAAC,MAAM,CAAC,CAsRzF"}
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAwGA,MAAM,WAAW,aAAa;IAC5B,MAAM,CAAC,EAAE;QAAE,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,CAAC;IAC7C,MAAM,CAAC,EAAE;QAAE,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,CAAC;CAC9C;AA4BD,wBAAsB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,OAAO,GAAE,aAAkB,GAAG,OAAO,CAAC,MAAM,CAAC,CA+SzF"}
package/dist/cli.js CHANGED
@@ -1,5 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { mkdir, readFile, writeFile } from "node:fs/promises";
3
+ import { realpathSync } from "node:fs";
3
4
  import path from "node:path";
4
5
  import { fileURLToPath } from "node:url";
5
6
  import YAML from "yaml";
@@ -91,6 +92,31 @@ export async function runCli(argv, options = {}) {
91
92
  const validation = validateManifests(loadResult.manifests);
92
93
  const fixtureValidation = validatePublicFixtures(loadResult.fixtures);
93
94
  const errors = [...loadResult.errors, ...validation.errors, ...fixtureValidation.errors];
95
+ if (!errors.length && loadResult.fixtures.some(fixture => fixture.kind === "discovery_eval_suite" || fixture.kind === "discovery_eval_observations")) {
96
+ const { validateDiscoveryEvaluationSuite, evaluateCapabilityDiscovery } = await import("./discovery/evaluation.js");
97
+ const suites = loadResult.fixtures.filter(fixture => fixture.kind === "discovery_eval_suite");
98
+ for (const fixture of suites) {
99
+ for (const diagnostic of validateDiscoveryEvaluationSuite(fixture.fixture)) {
100
+ errors.push({ code: "invalid_fixture", message: diagnostic.code, path: fixture.path, id: diagnostic.caseId });
101
+ }
102
+ }
103
+ for (const fixture of loadResult.fixtures.filter(fixture => fixture.kind === "discovery_eval_observations")) {
104
+ const observations = fixture.fixture;
105
+ const matches = suites.filter(candidate => candidate.fixture.id === observations.suite_id);
106
+ if (matches.length !== 1) {
107
+ errors.push({ code: "invalid_fixture", message: "discovery_evaluation_suite_required", path: fixture.path });
108
+ continue;
109
+ }
110
+ const suite = matches[0].fixture;
111
+ const registry = buildRegistry(suite.capabilities.map(manifest => ({ kind: "capability", manifest,
112
+ path: `synthetic/${manifest.id}.yaml`, absolutePath: `/synthetic/${manifest.id}.yaml` })));
113
+ const result = evaluateCapabilityDiscovery({ suite, registry, observations });
114
+ if (!result.valid)
115
+ for (const diagnostic of result.diagnostics) {
116
+ errors.push({ code: "invalid_fixture", message: diagnostic.code, path: fixture.path, id: diagnostic.caseId });
117
+ }
118
+ }
119
+ }
94
120
  if (errors.length > 0) {
95
121
  stderr.write(formatDiagnostics(errors));
96
122
  return 1;
@@ -2140,5 +2166,10 @@ function isDirectCliRun() {
2140
2166
  if (!invokedPath) {
2141
2167
  return false;
2142
2168
  }
2143
- return path.resolve(invokedPath) === fileURLToPath(import.meta.url);
2169
+ try {
2170
+ return realpathSync(invokedPath) === realpathSync(fileURLToPath(import.meta.url));
2171
+ }
2172
+ catch {
2173
+ return false;
2174
+ }
2144
2175
  }
@@ -0,0 +1,7 @@
1
+ import type { CapabilityRouteRequest } from "../runtime/types.js";
2
+ export declare function captureEligibility(request: CapabilityRouteRequest): {
3
+ fingerprint: string;
4
+ eligible: import("../types.js").LoadedCapabilityManifest[];
5
+ excluded: import("../runtime/types.js").RuntimeCapabilitySlice["excluded"];
6
+ };
7
+ //# sourceMappingURL=bindings.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bindings.d.ts","sourceRoot":"","sources":["../../src/discovery/bindings.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAIlE,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,sBAAsB;;;;EAoBjE"}
@@ -0,0 +1,24 @@
1
+ import { filterEligibleCapabilities } from "../runtime/eligibility.js";
2
+ import { ordinalCompare } from "./corpus.js";
3
+ import { fingerprintDiscoveryValue } from "./fingerprint.js";
4
+ export function captureEligibility(request) {
5
+ const result = filterEligibleCapabilities(request);
6
+ const sorted = (values) => values === undefined ? null : [...new Set(values)].sort(ordinalCompare);
7
+ return {
8
+ ...result,
9
+ fingerprint: fingerprintDiscoveryValue("eligibility", {
10
+ capabilities: result.eligible.map(({ manifest }) => ({
11
+ capabilityId: manifest.id, capabilityVersion: manifest.version,
12
+ exposedOperations: manifest.lifecycle.prepare ? ["select", "prepare"] : ["select"]
13
+ })).sort((left, right) => ordinalCompare(left.capabilityId, right.capabilityId)),
14
+ policy: {
15
+ allowedCapabilityTypes: sorted(request.allowedCapabilityTypes), allowedDomains: sorted(request.allowedDomains),
16
+ includeCapabilityIds: sorted(request.includeCapabilityIds), excludeCapabilityIds: sorted(request.excludeCapabilityIds),
17
+ maxRiskTier: request.maxRiskTier ?? request.builtContext.runtimeContext.autonomy.maxRiskTier,
18
+ includeRestricted: request.includeRestricted ?? false, includeDraft: request.includeDraft ?? false,
19
+ includeExperimental: request.includeExperimental ?? false, includeDeprecated: request.includeDeprecated ?? false,
20
+ includeDisabledForTests: request.includeDisabledForTests ?? false
21
+ }
22
+ })
23
+ };
24
+ }
@@ -0,0 +1,17 @@
1
+ import type { BudgetPolicy } from "../controls/types.js";
2
+ import type { DiscoveryBudgetLedger } from "./types.js";
3
+ /** A host may supply its own ledger and existing budget policy instead. */
4
+ export interface DiscoveryBudgetScope {
5
+ ledger: DiscoveryBudgetLedger;
6
+ policy: BudgetPolicy;
7
+ }
8
+ export interface InMemoryDiscoveryBudgetOptions {
9
+ runId: string;
10
+ maxProviderCalls: number;
11
+ maxInputTokens: number;
12
+ maxEstimatedCost?: number;
13
+ maxOutputTokens?: number;
14
+ }
15
+ /** Single-process, single-run accounting. Outstanding and unknown consumption retain allowance. */
16
+ export declare function createInMemoryDiscoveryBudget(options: InMemoryDiscoveryBudgetOptions): DiscoveryBudgetScope;
17
+ //# sourceMappingURL=budget.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"budget.d.ts","sourceRoot":"","sources":["../../src/discovery/budget.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAe,MAAM,sBAAsB,CAAC;AAKtE,OAAO,KAAK,EAAE,qBAAqB,EAA6B,MAAM,YAAY,CAAC;AAGnF,2EAA2E;AAC3E,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,qBAAqB,CAAC;IAC9B,MAAM,EAAE,YAAY,CAAC;CACtB;AAED,MAAM,WAAW,8BAA8B;IAC7C,KAAK,EAAE,MAAM,CAAC;IACd,gBAAgB,EAAE,MAAM,CAAC;IACzB,cAAc,EAAE,MAAM,CAAC;IACvB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,mGAAmG;AACnG,wBAAgB,6BAA6B,CAAC,OAAO,EAAE,8BAA8B,GAAG,oBAAoB,CAmE3G"}
@@ -0,0 +1,77 @@
1
+ import { hasOnlyKeys, isRecord, nonblank } from "./configuration.js";
2
+ import { DiscoveryError } from "./diagnostics.js";
3
+ import { nonnegative, positiveInteger } from "./embedding-configuration.js";
4
+ import { stopReason } from "./embeddings.js";
5
+ import { knownUsage } from "./usage.js";
6
+ /** Single-process, single-run accounting. Outstanding and unknown consumption retain allowance. */
7
+ export function createInMemoryDiscoveryBudget(options) {
8
+ if (!isRecord(options) || !hasOnlyKeys(options, ["runId", "maxProviderCalls", "maxInputTokens", "maxOutputTokens", "maxEstimatedCost"])
9
+ || !nonblank(options.runId) || !positiveInteger(options.maxProviderCalls) || !positiveInteger(options.maxInputTokens)
10
+ || options.maxOutputTokens !== undefined && !positiveInteger(options.maxOutputTokens)
11
+ || options.maxEstimatedCost !== undefined && !nonnegative(options.maxEstimatedCost)) {
12
+ throw new DiscoveryError({ code: "invalid_configuration", message: "An in-memory budget requires a run ID and positive finite call and input-token limits." });
13
+ }
14
+ const runId = options.runId;
15
+ const policy = Object.freeze({
16
+ id: "discovery.in-memory.v1", scope: Object.freeze({ type: "global" }), mode: "hard",
17
+ maxProviderCallsPerRun: options.maxProviderCalls, maxInputTokensPerRun: options.maxInputTokens,
18
+ ...(options.maxOutputTokens === undefined ? {} : { maxOutputTokensPerRun: options.maxOutputTokens }),
19
+ ...(options.maxEstimatedCost === undefined ? {} : { maxEstimatedCostPerRun: options.maxEstimatedCost })
20
+ });
21
+ const pending = new Map();
22
+ const charged = { providerCalls: 0, inputTokens: 0, outputTokens: 0, estimatedCost: 0 };
23
+ const held = { providerCalls: 0, inputTokens: 0, outputTokens: 0, estimatedCost: 0 };
24
+ let sequence = 0;
25
+ const ledger = {
26
+ async reserve(input) {
27
+ const denied = () => ({ status: "denied", diagnostic: {
28
+ code: "budget_denied", message: "The in-memory run budget denied this reservation."
29
+ } });
30
+ const usage = input.requestedUsage;
31
+ if (input.runId !== runId || !nonblank(input.requestId) || !Number.isFinite(input.deadlineAt)
32
+ || stopReason(input) || !isRecord(usage) || !positiveInteger(usage.providerCalls)
33
+ || !positiveInteger(usage.inputTokens)
34
+ || usage.outputTokens !== undefined && (typeof usage.outputTokens !== "number" || !Number.isSafeInteger(usage.outputTokens) || usage.outputTokens < 0)
35
+ || policy.maxOutputTokensPerRun !== undefined && !["embedding_build", "query_embedding"].includes(input.stage) && !positiveInteger(usage.outputTokens)
36
+ || usage.estimatedCost !== undefined && !nonnegative(usage.estimatedCost)
37
+ || policy.maxEstimatedCostPerRun !== undefined && usage.estimatedCost === undefined)
38
+ return denied();
39
+ const amounts = { providerCalls: usage.providerCalls, inputTokens: usage.inputTokens, outputTokens: usage.outputTokens ?? 0, estimatedCost: usage.estimatedCost ?? 0 };
40
+ if (charged.providerCalls + held.providerCalls + amounts.providerCalls > policy.maxProviderCallsPerRun
41
+ || charged.inputTokens + held.inputTokens + amounts.inputTokens > policy.maxInputTokensPerRun
42
+ || policy.maxOutputTokensPerRun !== undefined && charged.outputTokens + held.outputTokens + amounts.outputTokens > policy.maxOutputTokensPerRun
43
+ || policy.maxEstimatedCostPerRun !== undefined
44
+ && charged.estimatedCost + held.estimatedCost + amounts.estimatedCost > policy.maxEstimatedCostPerRun)
45
+ return denied();
46
+ // No await between checking capacity and recording the reservation.
47
+ const id = "discovery-reservation-" + ++sequence;
48
+ pending.set(id, amounts);
49
+ for (const key of ["providerCalls", "inputTokens", "outputTokens", "estimatedCost"])
50
+ held[key] += amounts[key];
51
+ return { status: "reserved", reservationId: id };
52
+ },
53
+ async settle(id, result) {
54
+ const reserved = pending.get(id);
55
+ if (!reserved || !isRecord(result) || !Number.isSafeInteger(result.providerAttempts) || result.providerAttempts < 0
56
+ || !Number.isSafeInteger(result.completedResponses) || result.completedResponses < 0
57
+ || !["completed", "failed", "cancelled", "discarded"].includes(result.outcome)) {
58
+ throw new DiscoveryError({ code: "accounting_unavailable", message: "The budget settlement is invalid or its reservation was already settled." });
59
+ }
60
+ const usage = knownUsage(result.usage);
61
+ // A completed response establishes an attempt even if a malformed client reports zero.
62
+ const attempts = Math.max(result.providerAttempts, result.completedResponses);
63
+ const actual = {
64
+ providerCalls: attempts,
65
+ inputTokens: usage.inputTokens ?? (attempts ? reserved.inputTokens : 0),
66
+ outputTokens: usage.outputTokens ?? (attempts ? reserved.outputTokens : 0),
67
+ estimatedCost: usage.estimatedCost ?? (attempts ? reserved.estimatedCost : 0)
68
+ };
69
+ pending.delete(id);
70
+ for (const key of ["providerCalls", "inputTokens", "outputTokens", "estimatedCost"]) {
71
+ held[key] = Math.max(0, held[key] - reserved[key]);
72
+ charged[key] += actual[key];
73
+ }
74
+ }
75
+ };
76
+ return Object.freeze({ ledger: Object.freeze(ledger), policy });
77
+ }
@@ -0,0 +1,10 @@
1
+ import type { DiscoveryConfiguration, ResolvedDiscoveryConfiguration, ResolvedLexicalDiscoveryConfiguration } from "./types.js";
2
+ export declare const HYBRID_WEIGHT_TOLERANCE = 1e-12;
3
+ export declare function resolveDiscoveryConfiguration(value: DiscoveryConfiguration): ResolvedDiscoveryConfiguration;
4
+ export declare function lexicalConfiguration(value: ResolvedDiscoveryConfiguration): ResolvedLexicalDiscoveryConfiguration;
5
+ export declare function isRecord(value: unknown): value is Record<string, unknown>;
6
+ export declare function hasOnlyKeys(value: Record<string, unknown>, keys: readonly string[]): boolean;
7
+ export declare function nonblank(value: unknown): value is string;
8
+ export declare function unitScore(value: unknown): value is number;
9
+ export declare function resolveLexicalConfiguration(value: DiscoveryConfiguration): ResolvedLexicalDiscoveryConfiguration;
10
+ //# sourceMappingURL=configuration.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"configuration.d.ts","sourceRoot":"","sources":["../../src/discovery/configuration.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,sBAAsB,EAAE,8BAA8B,EAAE,qCAAqC,EAAE,MAAM,YAAY,CAAC;AAEhI,eAAO,MAAM,uBAAuB,QAAQ,CAAC;AAE7C,wBAAgB,6BAA6B,CAAC,KAAK,EAAE,sBAAsB,GAAG,8BAA8B,CAgB3G;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,8BAA8B,GAAG,qCAAqC,CAGjH;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAGzE;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAE5F;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAExD;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAEzD;AAED,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,sBAAsB,GAAG,qCAAqC,CAsBhH"}
@@ -0,0 +1,63 @@
1
+ import { DiscoveryError } from "./diagnostics.js";
2
+ import { DISCOVERY_DEFAULT_LIMITS, DISCOVERY_HARD_LIMITS } from "./versions.js";
3
+ export const HYBRID_WEIGHT_TOLERANCE = 1e-12;
4
+ export function resolveDiscoveryConfiguration(value) {
5
+ if (isRecord(value) && value.mode === "hybrid") {
6
+ if (!hasOnlyKeys(value, ["mode", "policyVersion", "limits", "aliasWeight", "minRetrievalScore", "weights", "failurePolicy"])
7
+ || !isRecord(value.weights) || !hasOnlyKeys(value.weights, ["semantic", "lexical"])
8
+ || !unitScore(value.weights.semantic) || !unitScore(value.weights.lexical)
9
+ || Math.abs(value.weights.semantic + value.weights.lexical - 1) > HYBRID_WEIGHT_TOLERANCE
10
+ || value.failurePolicy !== "unavailable" && value.failurePolicy !== "lexical_fallback") {
11
+ throw new DiscoveryError({ code: "invalid_configuration", message: "Hybrid discovery requires explicit unit weights and a failure policy." });
12
+ }
13
+ const lexical = resolveLexicalConfiguration({
14
+ mode: "lexical", policyVersion: value.policyVersion,
15
+ limits: value.limits, aliasWeight: value.aliasWeight, minRetrievalScore: value.minRetrievalScore
16
+ });
17
+ return Object.freeze({ ...lexical, mode: "hybrid", weights: Object.freeze({ ...value.weights }), failurePolicy: value.failurePolicy });
18
+ }
19
+ return resolveLexicalConfiguration(value);
20
+ }
21
+ export function lexicalConfiguration(value) {
22
+ return Object.freeze({ mode: "lexical", policyVersion: value.policyVersion, limits: value.limits,
23
+ aliasWeight: value.aliasWeight, minRetrievalScore: value.minRetrievalScore });
24
+ }
25
+ export function isRecord(value) {
26
+ return value !== null && typeof value === "object" && !Array.isArray(value)
27
+ && (Object.getPrototypeOf(value) === Object.prototype || Object.getPrototypeOf(value) === null);
28
+ }
29
+ export function hasOnlyKeys(value, keys) {
30
+ return Reflect.ownKeys(value).every((key) => typeof key === "string" && keys.includes(key));
31
+ }
32
+ export function nonblank(value) {
33
+ return typeof value === "string" && value.trim().length > 0;
34
+ }
35
+ export function unitScore(value) {
36
+ return typeof value === "number" && Number.isFinite(value) && value >= 0 && value <= 1;
37
+ }
38
+ export function resolveLexicalConfiguration(value) {
39
+ const invalid = () => new DiscoveryError({
40
+ code: "invalid_configuration", message: "Discovery requires a valid, explicit lexical configuration."
41
+ });
42
+ if (!isRecord(value) || !hasOnlyKeys(value, ["mode", "policyVersion", "limits", "aliasWeight", "minRetrievalScore"])
43
+ || value.mode !== "lexical" || !nonblank(value.policyVersion))
44
+ throw invalid();
45
+ if (value.limits !== undefined && (!isRecord(value.limits)
46
+ || !hasOnlyKeys(value.limits, Object.keys(DISCOVERY_DEFAULT_LIMITS))))
47
+ throw invalid();
48
+ const limits = { ...DISCOVERY_DEFAULT_LIMITS, ...value.limits };
49
+ for (const key of Object.keys(limits)) {
50
+ const minimum = key === "aliasDiversitySlots" ? 0 : 1;
51
+ if (!Number.isInteger(limits[key]) || limits[key] < minimum || limits[key] > DISCOVERY_HARD_LIMITS[key]) {
52
+ throw invalid();
53
+ }
54
+ }
55
+ if (limits.aliasDiversitySlots >= limits.maxCandidates
56
+ || (value.aliasWeight !== undefined && !unitScore(value.aliasWeight))
57
+ || (value.minRetrievalScore !== undefined && !unitScore(value.minRetrievalScore)))
58
+ throw invalid();
59
+ return Object.freeze({
60
+ mode: "lexical", policyVersion: value.policyVersion, limits: Object.freeze(limits),
61
+ aliasWeight: value.aliasWeight ?? 0, minRetrievalScore: value.minRetrievalScore ?? 0
62
+ });
63
+ }
@@ -0,0 +1,8 @@
1
+ import type { ManifestRegistry } from "../types.js";
2
+ import type { CapabilitySearchCorpus } from "./types.js";
3
+ export declare const CAPABILITY_CORPUS_PROJECTION_VERSION = "approved-retrieval-fields.v1";
4
+ /** Rechecks definitions and map/list consistency without projecting another corpus. */
5
+ export declare function registrySourceFingerprint(registry: ManifestRegistry): string;
6
+ export declare function buildCapabilitySearchCorpus(registry: ManifestRegistry): CapabilitySearchCorpus;
7
+ export declare function ordinalCompare(left: string, right: string): number;
8
+ //# sourceMappingURL=corpus.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"corpus.d.ts","sourceRoot":"","sources":["../../src/discovery/corpus.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAMpD,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAEzD,eAAO,MAAM,oCAAoC,iCAAiC,CAAC;AAEnF,uFAAuF;AACvF,wBAAgB,yBAAyB,CAAC,QAAQ,EAAE,gBAAgB,GAAG,MAAM,CAmB5E;AAED,wBAAgB,2BAA2B,CAAC,QAAQ,EAAE,gBAAgB,GAAG,sBAAsB,CA0B9F;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAElE"}
@@ -0,0 +1,64 @@
1
+ import { validateManifests } from "../validator.js";
2
+ import { DiscoveryError } from "./diagnostics.js";
3
+ import { fingerprintDiscoveryValue, hashDiscoveryContent } from "./fingerprint.js";
4
+ import { tokenizeDiscoveryText, LEXICAL_TOKENIZER_VERSION } from "./lexical.js";
5
+ import { resolveDiscoveryMetadata } from "./metadata.js";
6
+ export const CAPABILITY_CORPUS_PROJECTION_VERSION = "approved-retrieval-fields.v1";
7
+ /** Rechecks definitions and map/list consistency without projecting another corpus. */
8
+ export function registrySourceFingerprint(registry) {
9
+ try {
10
+ const ids = new Set();
11
+ for (const entry of registry.capabilities) {
12
+ const id = entry.manifest.id;
13
+ if (entry.kind !== "capability" || ids.has(id) || registry.capabilityById.get(id) !== entry)
14
+ throw invalidRegistry();
15
+ ids.add(id);
16
+ }
17
+ if (registry.capabilityById.size !== ids.size)
18
+ throw invalidRegistry();
19
+ const validation = validateManifests([...registry.capabilities, ...registry.entities, ...registry.evals]);
20
+ if (!validation.valid)
21
+ throw invalidRegistry();
22
+ return fingerprintDiscoveryValue("registry_source", {
23
+ capabilities: registry.capabilities.map(({ manifest }) => ({
24
+ capabilityId: manifest.id, capabilityVersion: manifest.version, sourceContentHash: hashDiscoveryContent(manifest)
25
+ })).sort((left, right) => ordinalCompare(left.capabilityId, right.capabilityId))
26
+ });
27
+ }
28
+ catch {
29
+ throw invalidRegistry();
30
+ }
31
+ }
32
+ export function buildCapabilitySearchCorpus(registry) {
33
+ const source = registrySourceFingerprint(registry);
34
+ const documents = registry.capabilities.map(({ manifest }) => {
35
+ const metadata = resolveDiscoveryMetadata(manifest);
36
+ const content = {
37
+ capabilityId: manifest.id, capabilityVersion: manifest.version, riskTier: manifest.risk_tier,
38
+ name: manifest.name, summary: metadata.summary, aliases: [...metadata.aliases]
39
+ };
40
+ const fields = [content.capabilityId, content.name, content.summary, ...content.aliases];
41
+ return Object.freeze({
42
+ ...content, aliases: Object.freeze(content.aliases), text: fields.join("\n"),
43
+ tokens: Object.freeze([...new Set(fields.flatMap(tokenizeDiscoveryText))]),
44
+ documentHash: hashDiscoveryContent(content)
45
+ });
46
+ }).sort((left, right) => ordinalCompare(left.capabilityId, right.capabilityId));
47
+ return Object.freeze({
48
+ schemaVersion: "1.0", projectionVersion: CAPABILITY_CORPUS_PROJECTION_VERSION,
49
+ registrySourceFingerprint: source, documents: Object.freeze(documents),
50
+ corpusFingerprint: fingerprintDiscoveryValue("corpus", {
51
+ registrySourceFingerprint: source, projectionVersion: CAPABILITY_CORPUS_PROJECTION_VERSION,
52
+ projectionConfiguration: { tokenizerVersion: LEXICAL_TOKENIZER_VERSION },
53
+ documents: documents.map(({ capabilityId, capabilityVersion, documentHash }) => ({
54
+ capabilityId, capabilityVersion, documentHash
55
+ }))
56
+ })
57
+ });
58
+ }
59
+ export function ordinalCompare(left, right) {
60
+ return left < right ? -1 : left > right ? 1 : 0;
61
+ }
62
+ function invalidRegistry() {
63
+ return new DiscoveryError({ code: "invalid_input", message: "Discovery requires a valid, consistent capability registry." });
64
+ }
@@ -0,0 +1,15 @@
1
+ export type DiscoveryDiagnosticCode = "invalid_configuration" | "invalid_metadata" | "invalid_input" | "input_limit_exceeded" | "empty_query" | "no_eligible_capabilities" | "no_matching_candidates" | "invalid_ranker_output" | "invalid_index" | "embedding_configuration_mismatch" | "invalid_embedding" | "provider_unavailable" | "invalid_selection_output" | "invalid_selection_input" | "selection_configuration_mismatch" | "stale_binding" | "budget_denied" | "control_denied" | "accounting_unavailable" | "deadline_exceeded" | "cancelled" | "lexical_fallback" | "invalid_fingerprint_payload" | "replay_inputs_unavailable";
2
+ export interface DiscoveryDiagnostic {
3
+ code: DiscoveryDiagnosticCode;
4
+ message: string;
5
+ queryId?: string;
6
+ capabilityId?: string;
7
+ path?: string;
8
+ }
9
+ /** Configuration/contract errors only; operational outcomes use result statuses. */
10
+ export declare class DiscoveryError extends Error {
11
+ readonly code: DiscoveryDiagnosticCode;
12
+ readonly diagnostic: Readonly<DiscoveryDiagnostic>;
13
+ constructor(diagnostic: DiscoveryDiagnostic);
14
+ }
15
+ //# sourceMappingURL=diagnostics.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diagnostics.d.ts","sourceRoot":"","sources":["../../src/discovery/diagnostics.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,uBAAuB,GAC/B,uBAAuB,GACvB,kBAAkB,GAClB,eAAe,GACf,sBAAsB,GACtB,aAAa,GACb,0BAA0B,GAC1B,wBAAwB,GACxB,uBAAuB,GACvB,eAAe,GACf,kCAAkC,GAClC,mBAAmB,GACnB,sBAAsB,GACtB,0BAA0B,GAC1B,yBAAyB,GACzB,kCAAkC,GAClC,eAAe,GACf,eAAe,GACf,gBAAgB,GAChB,wBAAwB,GACxB,mBAAmB,GACnB,WAAW,GACX,kBAAkB,GAClB,6BAA6B,GAC7B,2BAA2B,CAAC;AAEhC,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,uBAAuB,CAAC;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,oFAAoF;AACpF,qBAAa,cAAe,SAAQ,KAAK;IACvC,QAAQ,CAAC,IAAI,EAAE,uBAAuB,CAAC;IACvC,QAAQ,CAAC,UAAU,EAAE,QAAQ,CAAC,mBAAmB,CAAC,CAAC;gBAEvC,UAAU,EAAE,mBAAmB;CAM5C"}
@@ -0,0 +1,11 @@
1
+ /** Configuration/contract errors only; operational outcomes use result statuses. */
2
+ export class DiscoveryError extends Error {
3
+ code;
4
+ diagnostic;
5
+ constructor(diagnostic) {
6
+ super(diagnostic.message);
7
+ this.name = "DiscoveryError";
8
+ this.code = diagnostic.code;
9
+ this.diagnostic = Object.freeze({ ...diagnostic });
10
+ }
11
+ }
@@ -0,0 +1,23 @@
1
+ import { type DiscoveryDiagnosticCode } from "./diagnostics.js";
2
+ import type { HybridDiscoveryDependencies } from "./embedding-types.js";
3
+ import type { CapabilityDiscoveryRequest, CapabilityDiscoveryResult, CapabilityLexicalRanker, DiscoveryConfiguration, DiscoveryQuery, DiscoveryUsage, ResolvedDiscoveryConfiguration } from "./types.js";
4
+ export { HYBRID_RANKER_VERSION, QUERY_EMBEDDING_PROJECTION_VERSION } from "./retrieval-policy.js";
5
+ export interface CapabilityDiscovererOptions {
6
+ ranker?: CapabilityLexicalRanker;
7
+ embedding?: HybridDiscoveryDependencies;
8
+ }
9
+ export declare class CapabilityDiscoverer {
10
+ readonly configuration: ResolvedDiscoveryConfiguration;
11
+ private readonly ranker?;
12
+ private readonly embedding?;
13
+ constructor(configuration: DiscoveryConfiguration, options?: CapabilityDiscovererOptions);
14
+ discover(request: CapabilityDiscoveryRequest): Promise<readonly CapabilityDiscoveryResult[]>;
15
+ private invocationConfiguration;
16
+ }
17
+ export declare function validateQueries(request: Pick<CapabilityDiscoveryRequest, "queries">, configuration: ResolvedDiscoveryConfiguration): readonly DiscoveryQuery[];
18
+ export declare function discoveryStopReason(request: {
19
+ signal?: AbortSignal;
20
+ deadlineAt?: number;
21
+ }): DiscoveryDiagnosticCode | undefined;
22
+ export declare function zeroDiscoveryUsage(elapsedMs: number): DiscoveryUsage;
23
+ //# sourceMappingURL=discoverer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discoverer.d.ts","sourceRoot":"","sources":["../../src/discovery/discoverer.ts"],"names":[],"mappings":"AAMA,OAAO,EAAkB,KAAK,uBAAuB,EAAE,MAAM,kBAAkB,CAAC;AAIhF,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,sBAAsB,CAAC;AAMxE,OAAO,KAAK,EACV,0BAA0B,EAAE,yBAAyB,EAAE,uBAAuB,EAAE,sBAAsB,EACtG,cAAc,EAAE,cAAc,EAAE,8BAA8B,EAC/D,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,qBAAqB,EAAE,kCAAkC,EAAE,MAAM,uBAAuB,CAAC;AAClG,MAAM,WAAW,2BAA2B;IAC1C,MAAM,CAAC,EAAE,uBAAuB,CAAC;IACjC,SAAS,CAAC,EAAE,2BAA2B,CAAC;CACzC;AAED,qBAAa,oBAAoB;IAC/B,QAAQ,CAAC,aAAa,EAAE,8BAA8B,CAAC;IACvD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,CAA0B;IAClD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,CAEzB;gBAEU,aAAa,EAAE,sBAAsB,EAAE,OAAO,GAAE,2BAAgC;IA0BtF,QAAQ,CAAC,OAAO,EAAE,0BAA0B,GAAG,OAAO,CAAC,SAAS,yBAAyB,EAAE,CAAC;IAsHlG,OAAO,CAAC,uBAAuB;CAchC;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,IAAI,CAAC,0BAA0B,EAAE,SAAS,CAAC,EAAE,aAAa,EAAE,8BAA8B,GAAG,SAAS,cAAc,EAAE,CAqB9J;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE;IAAE,MAAM,CAAC,EAAE,WAAW,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,uBAAuB,GAAG,SAAS,CAE/H;AAED,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,cAAc,CAEpE"}