dna-sdk 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (240) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +58 -0
  3. package/dist/adapters/embedding/onnx.d.ts +32 -0
  4. package/dist/adapters/embedding/onnx.js +51 -0
  5. package/dist/adapters/filesystem/cache.d.ts +16 -0
  6. package/dist/adapters/filesystem/cache.js +113 -0
  7. package/dist/adapters/filesystem/index.d.ts +2 -0
  8. package/dist/adapters/filesystem/index.js +2 -0
  9. package/dist/adapters/filesystem/source.d.ts +82 -0
  10. package/dist/adapters/filesystem/source.js +357 -0
  11. package/dist/adapters/postgres/index.d.ts +2 -0
  12. package/dist/adapters/postgres/index.js +2 -0
  13. package/dist/adapters/postgres/migrations.d.ts +14 -0
  14. package/dist/adapters/postgres/migrations.js +88 -0
  15. package/dist/adapters/postgres/source.d.ts +172 -0
  16. package/dist/adapters/postgres/source.js +569 -0
  17. package/dist/adapters/resolvers/github.d.ts +12 -0
  18. package/dist/adapters/resolvers/github.js +47 -0
  19. package/dist/adapters/resolvers/http.d.ts +22 -0
  20. package/dist/adapters/resolvers/http.js +145 -0
  21. package/dist/adapters/resolvers/index.d.ts +3 -0
  22. package/dist/adapters/resolvers/index.js +3 -0
  23. package/dist/adapters/resolvers/local.d.ts +24 -0
  24. package/dist/adapters/resolvers/local.js +132 -0
  25. package/dist/adapters/search/driver.d.ts +45 -0
  26. package/dist/adapters/search/driver.js +138 -0
  27. package/dist/adapters/search/migrations.d.ts +26 -0
  28. package/dist/adapters/search/migrations.js +58 -0
  29. package/dist/adapters/search/rrf.d.ts +23 -0
  30. package/dist/adapters/search/rrf.js +42 -0
  31. package/dist/adapters/search/sqlite-vec.d.ts +66 -0
  32. package/dist/adapters/search/sqlite-vec.js +294 -0
  33. package/dist/bootstrap.d.ts +45 -0
  34. package/dist/bootstrap.js +134 -0
  35. package/dist/extensions/agentskills/DOCS.md +18 -0
  36. package/dist/extensions/agentskills.d.ts +28 -0
  37. package/dist/extensions/agentskills.js +252 -0
  38. package/dist/extensions/agentsmd/DOCS.md +18 -0
  39. package/dist/extensions/agentsmd.d.ts +22 -0
  40. package/dist/extensions/agentsmd.js +170 -0
  41. package/dist/extensions/audit/kinds/audit-log.kind.yaml +148 -0
  42. package/dist/extensions/audit.d.ts +25 -0
  43. package/dist/extensions/audit.js +62 -0
  44. package/dist/extensions/automation/kinds/automation.kind.yaml +296 -0
  45. package/dist/extensions/automation/query.d.ts +49 -0
  46. package/dist/extensions/automation/query.js +77 -0
  47. package/dist/extensions/automation/write-guards.d.ts +59 -0
  48. package/dist/extensions/automation/write-guards.js +153 -0
  49. package/dist/extensions/automation.d.ts +41 -0
  50. package/dist/extensions/automation.js +54 -0
  51. package/dist/extensions/collab.d.ts +16 -0
  52. package/dist/extensions/collab.js +79 -0
  53. package/dist/extensions/doc/kinds/doc.kind.yaml +118 -0
  54. package/dist/extensions/doc.d.ts +25 -0
  55. package/dist/extensions/doc.js +10 -0
  56. package/dist/extensions/eval/kinds/eval-baseline.kind.yaml +65 -0
  57. package/dist/extensions/eval/kinds/eval-case.kind.yaml +140 -0
  58. package/dist/extensions/eval/kinds/eval-run.kind.yaml +134 -0
  59. package/dist/extensions/eval/kinds/eval-suite.kind.yaml +87 -0
  60. package/dist/extensions/eval.d.ts +24 -0
  61. package/dist/extensions/eval.js +31 -0
  62. package/dist/extensions/evidence/kinds/evidence.kind.yaml +92 -0
  63. package/dist/extensions/evidence.d.ts +17 -0
  64. package/dist/extensions/evidence.js +94 -0
  65. package/dist/extensions/federation.d.ts +22 -0
  66. package/dist/extensions/federation.js +173 -0
  67. package/dist/extensions/guardrails/DOCS.md +20 -0
  68. package/dist/extensions/guardrails.d.ts +31 -0
  69. package/dist/extensions/guardrails.js +228 -0
  70. package/dist/extensions/helix/DOCS-Actor.md +20 -0
  71. package/dist/extensions/helix/DOCS-Agent.md +20 -0
  72. package/dist/extensions/helix/DOCS-UseCase.md +20 -0
  73. package/dist/extensions/helix/layers.d.ts +12 -0
  74. package/dist/extensions/helix/layers.js +18 -0
  75. package/dist/extensions/helix/write-guards.d.ts +70 -0
  76. package/dist/extensions/helix/write-guards.js +172 -0
  77. package/dist/extensions/helix.d.ts +29 -0
  78. package/dist/extensions/helix.js +963 -0
  79. package/dist/extensions/helix_extras.d.ts +124 -0
  80. package/dist/extensions/helix_extras.js +328 -0
  81. package/dist/extensions/hooks.d.ts +31 -0
  82. package/dist/extensions/hooks.js +247 -0
  83. package/dist/extensions/kinddef/DOCS.md +24 -0
  84. package/dist/extensions/kinddef.d.ts +40 -0
  85. package/dist/extensions/kinddef.js +171 -0
  86. package/dist/extensions/lesson.d.ts +6 -0
  87. package/dist/extensions/lesson.js +194 -0
  88. package/dist/extensions/modelreg/kinds/model-profile.kind.yaml +155 -0
  89. package/dist/extensions/modelreg.d.ts +30 -0
  90. package/dist/extensions/modelreg.js +38 -0
  91. package/dist/extensions/recognizer.d.ts +34 -0
  92. package/dist/extensions/recognizer.js +272 -0
  93. package/dist/extensions/research.d.ts +32 -0
  94. package/dist/extensions/research.js +292 -0
  95. package/dist/extensions/safety.d.ts +33 -0
  96. package/dist/extensions/safety.js +230 -0
  97. package/dist/extensions/sdlc/kinds/adr.kind.yaml +136 -0
  98. package/dist/extensions/sdlc/kinds/archive-proposal.kind.yaml +107 -0
  99. package/dist/extensions/sdlc/kinds/changelog.kind.yaml +108 -0
  100. package/dist/extensions/sdlc/kinds/cognitive-policy.kind.yaml +470 -0
  101. package/dist/extensions/sdlc/kinds/forecast.kind.yaml +125 -0
  102. package/dist/extensions/sdlc/kinds/insight.kind.yaml +87 -0
  103. package/dist/extensions/sdlc/kinds/kaizen.kind.yaml +106 -0
  104. package/dist/extensions/sdlc/kinds/lesson-learned.kind.yaml +270 -0
  105. package/dist/extensions/sdlc/kinds/narrative.kind.yaml +189 -0
  106. package/dist/extensions/sdlc/kinds/pattern-insight.kind.yaml +204 -0
  107. package/dist/extensions/sdlc/kinds/postmortem.kind.yaml +168 -0
  108. package/dist/extensions/sdlc/kinds/pre-mortem.kind.yaml +145 -0
  109. package/dist/extensions/sdlc/kinds/prompt-template.kind.yaml +109 -0
  110. package/dist/extensions/sdlc/kinds/retrospective.kind.yaml +186 -0
  111. package/dist/extensions/sdlc/kinds/risk-register.kind.yaml +178 -0
  112. package/dist/extensions/sdlc/kinds/saved-view.kind.yaml +127 -0
  113. package/dist/extensions/sdlc/kinds/status-report.kind.yaml +129 -0
  114. package/dist/extensions/sdlc/kinds/synthesis-run.kind.yaml +279 -0
  115. package/dist/extensions/sdlc/kinds/synthesizer-state.kind.yaml +196 -0
  116. package/dist/extensions/sdlc/kinds/workflow-event.kind.yaml +195 -0
  117. package/dist/extensions/sdlc.d.ts +32 -0
  118. package/dist/extensions/sdlc.js +1318 -0
  119. package/dist/extensions/soulspec/DOCS.md +19 -0
  120. package/dist/extensions/soulspec.d.ts +22 -0
  121. package/dist/extensions/soulspec.js +287 -0
  122. package/dist/extensions/tenant.d.ts +6 -0
  123. package/dist/extensions/tenant.js +291 -0
  124. package/dist/extensions/testkit.d.ts +24 -0
  125. package/dist/extensions/testkit.js +211 -0
  126. package/dist/index.d.ts +80 -0
  127. package/dist/index.js +102 -0
  128. package/dist/kernel/_text.d.ts +28 -0
  129. package/dist/kernel/_text.js +42 -0
  130. package/dist/kernel/bundle-handle.d.ts +83 -0
  131. package/dist/kernel/bundle-handle.js +184 -0
  132. package/dist/kernel/capabilities.d.ts +157 -0
  133. package/dist/kernel/capabilities.js +109 -0
  134. package/dist/kernel/collaborator-ports.d.ts +91 -0
  135. package/dist/kernel/collaborator-ports.js +1 -0
  136. package/dist/kernel/composition-resolver.d.ts +215 -0
  137. package/dist/kernel/composition-resolver.js +558 -0
  138. package/dist/kernel/composition.d.ts +10 -0
  139. package/dist/kernel/composition.js +1 -0
  140. package/dist/kernel/descriptor-loader.d.ts +13 -0
  141. package/dist/kernel/descriptor-loader.js +48 -0
  142. package/dist/kernel/document.d.ts +43 -0
  143. package/dist/kernel/document.js +71 -0
  144. package/dist/kernel/embedding.d.ts +28 -0
  145. package/dist/kernel/embedding.js +78 -0
  146. package/dist/kernel/errors.d.ts +62 -0
  147. package/dist/kernel/errors.js +82 -0
  148. package/dist/kernel/events.d.ts +6 -0
  149. package/dist/kernel/events.js +21 -0
  150. package/dist/kernel/evidence-capture.d.ts +69 -0
  151. package/dist/kernel/evidence-capture.js +138 -0
  152. package/dist/kernel/fs.d.ts +20 -0
  153. package/dist/kernel/fs.js +128 -0
  154. package/dist/kernel/generic-rw.d.ts +33 -0
  155. package/dist/kernel/generic-rw.js +235 -0
  156. package/dist/kernel/hooks.d.ts +172 -0
  157. package/dist/kernel/hooks.js +256 -0
  158. package/dist/kernel/index.d.ts +624 -0
  159. package/dist/kernel/index.js +1638 -0
  160. package/dist/kernel/instance.d.ts +211 -0
  161. package/dist/kernel/instance.js +487 -0
  162. package/dist/kernel/kind-registry.d.ts +183 -0
  163. package/dist/kernel/kind-registry.js +710 -0
  164. package/dist/kernel/kind_base.d.ts +106 -0
  165. package/dist/kernel/kind_base.js +244 -0
  166. package/dist/kernel/layer-resolver.d.ts +48 -0
  167. package/dist/kernel/layer-resolver.js +284 -0
  168. package/dist/kernel/lock-manager.d.ts +21 -0
  169. package/dist/kernel/lock-manager.js +43 -0
  170. package/dist/kernel/lock.d.ts +38 -0
  171. package/dist/kernel/lock.js +115 -0
  172. package/dist/kernel/meta.d.ts +135 -0
  173. package/dist/kernel/meta.js +817 -0
  174. package/dist/kernel/models.d.ts +3089 -0
  175. package/dist/kernel/models.js +764 -0
  176. package/dist/kernel/navigator.d.ts +36 -0
  177. package/dist/kernel/navigator.js +132 -0
  178. package/dist/kernel/port-surface.d.ts +33 -0
  179. package/dist/kernel/port-surface.js +180 -0
  180. package/dist/kernel/preview.d.ts +60 -0
  181. package/dist/kernel/preview.js +54 -0
  182. package/dist/kernel/prompt-budget.d.ts +39 -0
  183. package/dist/kernel/prompt-budget.js +43 -0
  184. package/dist/kernel/prompt-builder.d.ts +25 -0
  185. package/dist/kernel/prompt-builder.js +237 -0
  186. package/dist/kernel/protocols.d.ts +751 -0
  187. package/dist/kernel/protocols.js +493 -0
  188. package/dist/kernel/reports.d.ts +26 -0
  189. package/dist/kernel/reports.js +215 -0
  190. package/dist/kernel/resolver.d.ts +146 -0
  191. package/dist/kernel/resolver.js +232 -0
  192. package/dist/kernel/resource.d.ts +57 -0
  193. package/dist/kernel/resource.js +97 -0
  194. package/dist/kernel/runtime.d.ts +16 -0
  195. package/dist/kernel/runtime.js +18 -0
  196. package/dist/kernel/safety-scanner.d.ts +38 -0
  197. package/dist/kernel/safety-scanner.js +228 -0
  198. package/dist/kernel/serialize-to-files.d.ts +29 -0
  199. package/dist/kernel/serialize-to-files.js +23 -0
  200. package/dist/kernel/spec-access.d.ts +23 -0
  201. package/dist/kernel/spec-access.js +40 -0
  202. package/dist/kernel/studio_ui.d.ts +88 -0
  203. package/dist/kernel/studio_ui.js +135 -0
  204. package/dist/kernel/templates.d.ts +77 -0
  205. package/dist/kernel/templates.js +116 -0
  206. package/dist/kernel/tool-registry.d.ts +52 -0
  207. package/dist/kernel/tool-registry.js +89 -0
  208. package/dist/kernel/write-pipeline.d.ts +65 -0
  209. package/dist/kernel/write-pipeline.js +271 -0
  210. package/dist/kernel/writer-helpers.d.ts +24 -0
  211. package/dist/kernel/writer-helpers.js +42 -0
  212. package/dist/memory/decay.d.ts +31 -0
  213. package/dist/memory/decay.js +97 -0
  214. package/dist/memory/ecphory.d.ts +25 -0
  215. package/dist/memory/ecphory.js +178 -0
  216. package/dist/memory/encodingContext.d.ts +21 -0
  217. package/dist/memory/encodingContext.js +62 -0
  218. package/dist/memory/index.d.ts +23 -0
  219. package/dist/memory/index.js +23 -0
  220. package/dist/memory/memoryType.d.ts +7 -0
  221. package/dist/memory/memoryType.js +24 -0
  222. package/dist/memory/policy.d.ts +35 -0
  223. package/dist/memory/policy.js +35 -0
  224. package/dist/memory/retrieval.d.ts +21 -0
  225. package/dist/memory/retrieval.js +145 -0
  226. package/dist/testing/index.d.ts +8 -0
  227. package/dist/testing/index.js +8 -0
  228. package/dist/testing/recordSearchConformance.d.ts +43 -0
  229. package/dist/testing/recordSearchConformance.js +147 -0
  230. package/dist/viz/ascii.d.ts +7 -0
  231. package/dist/viz/ascii.js +60 -0
  232. package/dist/viz/health.d.ts +8 -0
  233. package/dist/viz/health.js +161 -0
  234. package/dist/viz/index.d.ts +10 -0
  235. package/dist/viz/index.js +10 -0
  236. package/dist/viz/matrix.d.ts +8 -0
  237. package/dist/viz/matrix.js +84 -0
  238. package/dist/viz/mermaid.d.ts +38 -0
  239. package/dist/viz/mermaid.js +706 -0
  240. package/package.json +82 -0
@@ -0,0 +1,155 @@
1
+ # ModelProfile — per-LLM-model capability/limit registry (record plane).
2
+ # One doc per model: hard limits (instruction_token_cap, context_window,
3
+ # tools_cap, max_output_tokens) + modalities + cost, as first-class GLOBAL
4
+ # data so limits are project data, not implicit knowledge. Ported from the
5
+ # internal SDK's model registry, motivated by a real outage: a 17269-token
6
+ # voice persona silently exceeded the realtime model's 16384-token
7
+ # session-instructions cap because the cap lived in nobody's code.
8
+ #
9
+ # CONTRACT — never hardcode token caps: the prompt-budget write guard
10
+ # (dna/extensions/helix/write_guards.py :: prompt_budget_guard and its TS
11
+ # twin) reads instruction_token_cap from THIS registry via
12
+ # kernel.model_profile(id_or_alias); a cap literal in code is a bug.
13
+ #
14
+ # Profiles live in the `_lib` scope (`model-profiles/<model_id>.yaml`) —
15
+ # ModelProfile is GLOBAL (base only, no per-tenant override) and NOT
16
+ # inheritable; kernel.model_profile() queries `_lib` directly regardless
17
+ # of the caller's scope.
18
+ #
19
+ # PARITY-CRITICAL package data: the byte-identical mirror lives at
20
+ # packages/sdk-{py,ts}/{dna/extensions,src/extensions}/modelreg/kinds/
21
+ # model-profile.kind.yaml (tests/test_descriptor_hash_parity.py enforces).
22
+ apiVersion: github.com/ruinosus/dna/core/v1
23
+ kind: KindDefinition
24
+ metadata:
25
+ name: model-profile
26
+ spec:
27
+ target_api_version: github.com/ruinosus/dna/modelreg/v1
28
+ target_kind: ModelProfile
29
+ alias: modelreg-model-profile
30
+ origin: github.com/ruinosus/dna/modelreg
31
+ tenant_scope: global
32
+ plane: record
33
+ prompt_target: false
34
+ flatten_in_context: false
35
+ prompt_target_priority: 0
36
+ storage:
37
+ type: yaml
38
+ container: model-profiles
39
+ schema:
40
+ type: object
41
+ required:
42
+ - model_id
43
+ - provider
44
+ properties:
45
+ model_id:
46
+ type: string
47
+ description: Canonical model identifier, e.g. 'gpt-realtime-2'. The doc
48
+ name SHOULD equal the model_id; kernel.model_profile() matches on this
49
+ field first.
50
+ provider:
51
+ type: string
52
+ description: Who serves the model — 'openai', 'anthropic', 'azure', a
53
+ proxy alias, etc.
54
+ family:
55
+ type:
56
+ - string
57
+ - 'null'
58
+ description: Model family/lineage for grouping, e.g. 'gpt-realtime'.
59
+ realtime:
60
+ type: boolean
61
+ default: false
62
+ description: 'True for realtime voice models. STRICT marker: the
63
+ prompt-budget guard VETOES an over-cap write against a realtime
64
+ profile (voice sessions silently degrade past the cap); chat profiles
65
+ only warn.'
66
+ context_window:
67
+ type: integer
68
+ description: Total context window in tokens.
69
+ instruction_token_cap:
70
+ type:
71
+ - integer
72
+ - 'null'
73
+ description: Hard cap for the system-instruction/persona in tokens.
74
+ Null = no cap known (the guard fails open). THE value the
75
+ prompt-budget guard enforces — never hardcode it in code.
76
+ max_output_tokens:
77
+ type:
78
+ - integer
79
+ - 'null'
80
+ description: Max completion/output tokens per response.
81
+ tools_cap:
82
+ type:
83
+ - integer
84
+ - 'null'
85
+ description: Max number of tools the model accepts per session.
86
+ modalities:
87
+ type: array
88
+ items:
89
+ type: string
90
+ description: Supported modalities, e.g. [text], [text, audio],
91
+ [text, image].
92
+ cost_per_1m_input_usd:
93
+ type:
94
+ - number
95
+ - 'null'
96
+ description: USD per 1M input tokens (informational).
97
+ cost_per_1m_output_usd:
98
+ type:
99
+ - number
100
+ - 'null'
101
+ description: USD per 1M output tokens (informational).
102
+ aliases:
103
+ type: array
104
+ items:
105
+ type: string
106
+ description: Alternate ids that resolve to this profile (deployment
107
+ names, dated snapshots). kernel.model_profile() matches these on
108
+ pass 2.
109
+ deprecated:
110
+ type: boolean
111
+ default: false
112
+ description: True when the model is scheduled for removal.
113
+ deprecated_message:
114
+ type:
115
+ - string
116
+ - 'null'
117
+ description: Human guidance shown when a deprecated model is used.
118
+ notes:
119
+ type:
120
+ - string
121
+ - 'null'
122
+ description: Free-form operator notes.
123
+ describe: '{provider}/{model_id}'
124
+ summary:
125
+ model_id: ''
126
+ provider: ''
127
+ family: null
128
+ realtime: false
129
+ context_window: null
130
+ instruction_token_cap: null
131
+ deprecated: false
132
+ ui:
133
+ mode: govern
134
+ label:
135
+ en: Model Profiles
136
+ pt-BR: Perfis de Modelo
137
+ icon: 🧬
138
+ description:
139
+ en: Per-LLM-model limits/capabilities.
140
+ pt-BR: Limites/capacidades por modelo LLM.
141
+ routes:
142
+ list: docs/ModelProfile
143
+ detail: docs/ModelProfile/:name
144
+ permissions:
145
+ list: any
146
+ detail: any
147
+ in_sidebar: true
148
+ display_order: 52
149
+ ascii_icon: 🧬
150
+ display_label: Model Profiles
151
+ docs: A ModelProfile records one LLM model's hard limits and capabilities
152
+ (instruction_token_cap, context_window, tools_cap, modalities, cost). It is
153
+ the single source of truth the prompt-budget write guard reads — never
154
+ hardcode token caps in code; read them from the ModelProfile registry via
155
+ kernel.model_profile().
@@ -0,0 +1,30 @@
1
+ /**
2
+ * ModelRegExtension — per-model capability/limit registry.
3
+ *
4
+ * 1:1 parity with Python `dna.extensions.modelreg`.
5
+ *
6
+ * Registers 1 Kind, from a descriptor (F3 — record Kinds are data, not
7
+ * classes):
8
+ *
9
+ * - ModelProfile (`modelreg-model-profile`) — hard limits
10
+ * (`instruction_token_cap`, `context_window`, `tools_cap`) +
11
+ * modalities + cost of one LLM model, as a first-class GLOBAL Kind so
12
+ * limits are project data, not implicit knowledge. Ported from the
13
+ * internal SDK's model registry, motivated by a real outage: a
14
+ * 17269-token voice persona silently exceeded the realtime model's
15
+ * 16384-token session-instructions cap because the cap lived in
16
+ * nobody's code.
17
+ *
18
+ * CONTRACT — never hardcode token caps. The single source of truth for a
19
+ * model's limits is its ModelProfile doc (`_lib` scope,
20
+ * `model-profiles/<model_id>.yaml`), resolved via
21
+ * `kernel.modelProfile(idOrAlias)`. The prompt-budget write guard
22
+ * (`src/extensions/helix/write-guards.ts` + Python twin) reads the cap
23
+ * from there — a token-cap literal in code is a bug.
24
+ */
25
+ import type { ExtensionHost, Extension } from "../kernel/protocols.js";
26
+ export declare class ModelRegExtension implements Extension {
27
+ name: string;
28
+ version: string;
29
+ register(kernel: ExtensionHost): void;
30
+ }
@@ -0,0 +1,38 @@
1
+ /**
2
+ * ModelRegExtension — per-model capability/limit registry.
3
+ *
4
+ * 1:1 parity with Python `dna.extensions.modelreg`.
5
+ *
6
+ * Registers 1 Kind, from a descriptor (F3 — record Kinds are data, not
7
+ * classes):
8
+ *
9
+ * - ModelProfile (`modelreg-model-profile`) — hard limits
10
+ * (`instruction_token_cap`, `context_window`, `tools_cap`) +
11
+ * modalities + cost of one LLM model, as a first-class GLOBAL Kind so
12
+ * limits are project data, not implicit knowledge. Ported from the
13
+ * internal SDK's model registry, motivated by a real outage: a
14
+ * 17269-token voice persona silently exceeded the realtime model's
15
+ * 16384-token session-instructions cap because the cap lived in
16
+ * nobody's code.
17
+ *
18
+ * CONTRACT — never hardcode token caps. The single source of truth for a
19
+ * model's limits is its ModelProfile doc (`_lib` scope,
20
+ * `model-profiles/<model_id>.yaml`), resolved via
21
+ * `kernel.modelProfile(idOrAlias)`. The prompt-budget write guard
22
+ * (`src/extensions/helix/write-guards.ts` + Python twin) reads the cap
23
+ * from there — a token-cap literal in code is a bug.
24
+ */
25
+ import { loadDescriptors } from "../kernel/descriptor-loader.js";
26
+ export class ModelRegExtension {
27
+ name = "modelreg";
28
+ version = "1.0.0";
29
+ register(kernel) {
30
+ // F3: ModelProfile ships as kinds/model-profile.kind.yaml package data
31
+ // (byte-identical Py↔TS mirror), registered through the SAME funnel as
32
+ // per-scope KindDefinitions (plane lint + digest idempotency + builtin
33
+ // conflict marker).
34
+ for (const raw of loadDescriptors(import.meta.url, "modelreg/kinds")) {
35
+ kernel.kindFromDescriptor(raw);
36
+ }
37
+ }
38
+ }
@@ -0,0 +1,34 @@
1
+ /**
2
+ * RecognizerExtension — Recognizer kind (Presidio ad-hoc recognizer).
3
+ *
4
+ * Declares PII detection patterns as manifest documents. Recognizers are
5
+ * referenced by SafetyPolicy documents via dep_filters and exported to
6
+ * LiteLLM/Presidio at runtime.
7
+ *
8
+ * 1:1 parity with Python dna.extensions.recognizer.
9
+ */
10
+ import type { BundleHandle } from "../kernel/bundle-handle.js";
11
+ import type { FSLike } from "../kernel/fs.js";
12
+ import type { ExtensionHost, Extension, ReaderPort, SerializedFile, WriterPort } from "../kernel/protocols.js";
13
+ export declare class RecognizerReader implements ReaderPort {
14
+ private fs;
15
+ readonly _marker = "RECOGNIZER.md";
16
+ constructor(fs?: FSLike);
17
+ detect(bundle: BundleHandle): boolean;
18
+ read(bundle: BundleHandle): Record<string, unknown>;
19
+ }
20
+ export declare class RecognizerWriter implements WriterPort {
21
+ private fs;
22
+ readonly _kind = "Recognizer";
23
+ constructor(fs?: FSLike);
24
+ canWrite(raw: Record<string, unknown>): boolean;
25
+ write(bundle: BundleHandle, raw: Record<string, unknown>): void;
26
+ serialize(raw: Record<string, unknown>): SerializedFile[];
27
+ }
28
+ export declare class RecognizerExtension implements Extension {
29
+ private fs;
30
+ readonly name = "recognizer";
31
+ readonly version = "1.0.0";
32
+ constructor(fs?: FSLike);
33
+ register(kernel: ExtensionHost): void;
34
+ }
@@ -0,0 +1,272 @@
1
+ /**
2
+ * RecognizerExtension — Recognizer kind (Presidio ad-hoc recognizer).
3
+ *
4
+ * Declares PII detection patterns as manifest documents. Recognizers are
5
+ * referenced by SafetyPolicy documents via dep_filters and exported to
6
+ * LiteLLM/Presidio at runtime.
7
+ *
8
+ * 1:1 parity with Python dna.extensions.recognizer.
9
+ */
10
+ import yaml from "js-yaml";
11
+ import { nodeFS } from "../kernel/fs.js";
12
+ import { KindBase } from "../kernel/kind_base.js";
13
+ import { RecognizerSchema, RecognizerSpecSchema, zodSpecToJsonSchema } from "../kernel/models.js";
14
+ import { SD } from "../kernel/protocols.js";
15
+ // ---------------------------------------------------------------------------
16
+ // RecognizerKind
17
+ // ---------------------------------------------------------------------------
18
+ class RecognizerKind extends KindBase {
19
+ apiVersion = "presidio/v1";
20
+ kind = "Recognizer";
21
+ alias = "presidio-recognizer";
22
+ isSchemaAffecting = true;
23
+ origin = "microsoft.github.io/presidio";
24
+ isPromptTarget = false;
25
+ promptTargetPriority = 0;
26
+ flattenInContext = false;
27
+ descriptionFallbackField = "entity_type";
28
+ storage = SD.bundle("recognizers", "RECOGNIZER.md", "text", "patterns");
29
+ graphStyle = { fill: "#6366F1", stroke: "#4F46E5", textColor: "#fff" };
30
+ asciiIcon = "\uD83D\uDD0D";
31
+ displayLabel = "Recognizers";
32
+ _sourceUrl = import.meta.url;
33
+ docs = "A Recognizer is a Presidio ad-hoc recognizer that detects PII entities " +
34
+ "using regex patterns or deny lists. Recognizers are referenced by " +
35
+ "SafetyPolicy documents and exported to LiteLLM/Presidio at runtime.";
36
+ uiSchema = {
37
+ entity_type: {
38
+ widget: "input",
39
+ label: "Entity Type",
40
+ help: "Presidio entity name, e.g. BR_CPF, BR_CNPJ",
41
+ order: 1,
42
+ },
43
+ language: {
44
+ widget: "select",
45
+ options: ["en", "pt", "es", "de", "fr"],
46
+ label: "Language",
47
+ order: 2,
48
+ },
49
+ patterns: {
50
+ widget: "code",
51
+ language: "yaml",
52
+ label: "Patterns",
53
+ help: "List of {name, regex, score} objects",
54
+ height: 200,
55
+ order: 3,
56
+ },
57
+ deny_list: {
58
+ widget: "tags",
59
+ label: "Deny List",
60
+ help: "Words that always match this entity",
61
+ order: 4,
62
+ },
63
+ context: {
64
+ widget: "tags",
65
+ label: "Context Words",
66
+ help: "Words near the entity that boost confidence",
67
+ order: 5,
68
+ },
69
+ };
70
+ schema() { return zodSpecToJsonSchema(RecognizerSpecSchema); }
71
+ parse(raw) {
72
+ // patterns comes as raw text (body_as=text). Parse as YAML to get array of pattern objects.
73
+ const spec = (raw.spec ?? {});
74
+ if (typeof spec.patterns === "string" && spec.patterns.trim()) {
75
+ try {
76
+ const parsed = yaml.load(spec.patterns);
77
+ if (Array.isArray(parsed)) {
78
+ spec.patterns = parsed;
79
+ }
80
+ else {
81
+ spec.patterns = [];
82
+ }
83
+ }
84
+ catch {
85
+ spec.patterns = [];
86
+ }
87
+ }
88
+ return RecognizerSchema.parse(raw);
89
+ }
90
+ describe(doc) {
91
+ const spec = (doc.spec ?? {});
92
+ return `Recognizer: ${doc.name} (entity=${spec.entity_type})`;
93
+ }
94
+ summary(doc) {
95
+ const spec = (doc.spec ?? {});
96
+ return {
97
+ entity_type: typeof spec.entity_type === "string" ? spec.entity_type : "",
98
+ language: typeof spec.language === "string" ? spec.language : "en",
99
+ patterns: Array.isArray(spec.patterns) ? spec.patterns.length : 0,
100
+ deny_list: Array.isArray(spec.deny_list) ? spec.deny_list.length : 0,
101
+ };
102
+ }
103
+ preview(doc) {
104
+ const spec = (doc.spec ?? {});
105
+ const blocks = [];
106
+ const meta = [];
107
+ if (typeof spec.entity_type === "string")
108
+ meta.push({ label: "Entity Type", value: spec.entity_type });
109
+ if (typeof spec.language === "string")
110
+ meta.push({ label: "Language", value: spec.language });
111
+ if (meta.length > 0) {
112
+ blocks.push({ kind: "fields", title: "Recognizer", fields: meta });
113
+ }
114
+ const patterns = spec.patterns;
115
+ if (Array.isArray(patterns) && patterns.length > 0) {
116
+ blocks.push({
117
+ kind: "code",
118
+ title: "Patterns",
119
+ body: yaml.dump(patterns, { flowLevel: 3 }).trim(),
120
+ language: "yaml",
121
+ });
122
+ }
123
+ const denyList = spec.deny_list;
124
+ if (Array.isArray(denyList) && denyList.length > 0) {
125
+ blocks.push({
126
+ kind: "code",
127
+ title: "Deny List",
128
+ body: denyList.join(", "),
129
+ language: "text",
130
+ });
131
+ }
132
+ const context = spec.context;
133
+ if (Array.isArray(context) && context.length > 0) {
134
+ blocks.push({
135
+ kind: "code",
136
+ title: "Context Words",
137
+ body: context.join(", "),
138
+ language: "text",
139
+ });
140
+ }
141
+ if (blocks.length === 0) {
142
+ return [{ kind: "empty", title: "Recognizer (empty)" }];
143
+ }
144
+ return blocks;
145
+ }
146
+ }
147
+ // ---------------------------------------------------------------------------
148
+ // RecognizerReader
149
+ // ---------------------------------------------------------------------------
150
+ function parseFrontmatter(text) {
151
+ const match = text.match(/^---\n([\s\S]*?)---\n?/);
152
+ if (!match)
153
+ return [{}, text];
154
+ let fm = {};
155
+ try {
156
+ const parsed = yaml.load(match[1]);
157
+ if (typeof parsed === "object" && parsed !== null) {
158
+ fm = parsed;
159
+ }
160
+ }
161
+ catch { /* ignore */ }
162
+ const body = text.slice(match[0].length);
163
+ return [fm, body];
164
+ }
165
+ export class RecognizerReader {
166
+ fs;
167
+ _marker = "RECOGNIZER.md";
168
+ constructor(fs = nodeFS) {
169
+ this.fs = fs;
170
+ }
171
+ detect(bundle) {
172
+ const path = bundle.path ?? "";
173
+ return this.fs.exists(`${path}/RECOGNIZER.md`);
174
+ }
175
+ read(bundle) {
176
+ const path = bundle.path ?? "";
177
+ const text = this.fs.readFile(`${path}/RECOGNIZER.md`);
178
+ const [fm, body] = parseFrontmatter(text);
179
+ const name = String(fm.name || "") || path.split("/").pop() || "";
180
+ const description = String(fm.description || "");
181
+ const entity_type = String(fm.entity_type || "");
182
+ const language = String(fm.language || "en");
183
+ // Parse deny_list and context from frontmatter
184
+ const deny_list = Array.isArray(fm.deny_list) ? fm.deny_list.map(String) : [];
185
+ const context = Array.isArray(fm.context) ? fm.context.map(String) : [];
186
+ // Parse body as YAML list of pattern objects
187
+ let patterns = [];
188
+ const trimmedBody = body.trim();
189
+ if (trimmedBody) {
190
+ try {
191
+ const parsed = yaml.load(trimmedBody);
192
+ if (Array.isArray(parsed)) {
193
+ patterns = parsed;
194
+ }
195
+ }
196
+ catch { /* ignore invalid YAML */ }
197
+ }
198
+ return {
199
+ apiVersion: "presidio/v1",
200
+ kind: "Recognizer",
201
+ metadata: { name, description },
202
+ spec: { entity_type, language, patterns, deny_list, context },
203
+ };
204
+ }
205
+ }
206
+ // ---------------------------------------------------------------------------
207
+ // RecognizerWriter
208
+ // ---------------------------------------------------------------------------
209
+ export class RecognizerWriter {
210
+ fs;
211
+ _kind = "Recognizer";
212
+ constructor(fs = nodeFS) {
213
+ this.fs = fs;
214
+ }
215
+ canWrite(raw) {
216
+ return raw.kind === "Recognizer";
217
+ }
218
+ write(bundle, raw) {
219
+ const path = bundle.path ?? "";
220
+ this.fs.mkdir(path);
221
+ for (const f of this.serialize(raw)) {
222
+ this.fs.writeFile(`${path}/${f.relativePath}`, f.content ?? "");
223
+ }
224
+ }
225
+ serialize(raw) {
226
+ const meta = (raw.metadata ?? {});
227
+ const spec = (raw.spec ?? {});
228
+ const fmParts = [];
229
+ if (meta.name)
230
+ fmParts.push(`name: ${meta.name}`);
231
+ if (meta.description)
232
+ fmParts.push(`description: ${meta.description}`);
233
+ if (spec.entity_type)
234
+ fmParts.push(`entity_type: ${spec.entity_type}`);
235
+ fmParts.push(`language: ${spec.language ?? "en"}`);
236
+ const denyList = spec.deny_list;
237
+ if (denyList && denyList.length > 0) {
238
+ fmParts.push(`deny_list:\n${denyList.map(w => ` - ${w}`).join("\n")}`);
239
+ }
240
+ const context = spec.context;
241
+ if (context && context.length > 0) {
242
+ fmParts.push(`context:\n${context.map(w => ` - ${w}`).join("\n")}`);
243
+ }
244
+ const frontmatter = fmParts.join("\n");
245
+ // Serialize patterns as YAML list
246
+ const patterns = spec.patterns ?? [];
247
+ let body = "";
248
+ if (patterns.length > 0) {
249
+ body = yaml.dump(patterns, { flowLevel: 3 }).trim();
250
+ }
251
+ const content = body
252
+ ? `---\n${frontmatter}\n---\n\n${body}\n`
253
+ : `---\n${frontmatter}\n---\n`;
254
+ return [{ relativePath: "RECOGNIZER.md", content }];
255
+ }
256
+ }
257
+ // ---------------------------------------------------------------------------
258
+ // Extension
259
+ // ---------------------------------------------------------------------------
260
+ export class RecognizerExtension {
261
+ fs;
262
+ name = "recognizer";
263
+ version = "1.0.0";
264
+ constructor(fs = nodeFS) {
265
+ this.fs = fs;
266
+ }
267
+ register(kernel) {
268
+ kernel.kind(new RecognizerKind());
269
+ kernel.reader(new RecognizerReader(this.fs));
270
+ kernel.writer(new RecognizerWriter(this.fs));
271
+ }
272
+ }
@@ -0,0 +1,32 @@
1
+ /**
2
+ * ResearchExtension — curated research syntheses with evidence ratings (TS twin).
3
+ *
4
+ * 1:1 parity with python/dna/extensions/research/__init__.py.
5
+ *
6
+ * Storage layout per doc:
7
+ *
8
+ * .dna/<scope>/research/<name>/
9
+ * RESEARCH.md ← marker (frontmatter = spec)
10
+ *
11
+ * A Research synthesizes N Reference docs with objective, methodology,
12
+ * evidence-rated findings, and priority recommendations — agent-facing
13
+ * knowledge WITH provenance (the declarative counter to LLM-generated
14
+ * repo-wiki prose).
15
+ *
16
+ * Tenancy: PERMISSIVE — no `scope` attribute declared, so the write
17
+ * pipeline treats it as permissive (base writes with or without a
18
+ * tenant). Research is repo-authored knowledge, not per-client data.
19
+ *
20
+ * The Reference companion Kind is provided by the sdlc extension
21
+ * (alias sdlc-reference); it is NOT registered here.
22
+ */
23
+ import type { ExtensionHost, Extension } from "../kernel/protocols.js";
24
+ export declare const METHODOLOGIES: readonly ["web-search-curated", "literature-review", "interview", "field-study", "experiment", "synthesis", "other"];
25
+ export declare const EVIDENCE_RATINGS: readonly ["evidence-based", "opinion-practice", "anecdotal"];
26
+ export declare const STATUSES: readonly ["brief", "ready", "draft", "published", "superseded", "retracted"];
27
+ export declare const VISIBILITY: readonly ["scope-private", "shared"];
28
+ export declare class ResearchExtension implements Extension {
29
+ name: string;
30
+ version: string;
31
+ register(kernel: ExtensionHost): void;
32
+ }