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,173 @@
1
+ /**
2
+ * FederationExtension — Phase 14r MCP Federation (schema v2, 2026-07-07).
3
+ *
4
+ * Declares the `MCPFederation` Kind: an external MCP server whose tools
5
+ * DNA agents consume via `Agent.spec.mcp_servers` (primary,
6
+ * s-mcp-servers-on-agent) or via the DNA-as-MCP-server proxy
7
+ * (legacy Phase 14r direction). Transports: stdio | streamable_http.
8
+ * Auth carries env-var NAMES only — never secret values.
9
+ *
10
+ * Schema v2 is fully backward-compatible with v1 docs: `transport`
11
+ * defaults to `stdio` and every new field is optional.
12
+ *
13
+ * 1:1 parity with python/dna/extensions/federation/__init__.py.
14
+ * The TS SDK ships schema/Kind parity only — the agent runtime (and the
15
+ * MCP client) is Python-only by design (spec §3).
16
+ */
17
+ import { KindBase } from "../kernel/kind_base.js";
18
+ import { SD } from "../kernel/protocols.js";
19
+ const API_VERSION = "github.com/ruinosus/dna/federation/v1";
20
+ class MCPFederationKind extends KindBase {
21
+ apiVersion = API_VERSION;
22
+ kind = "MCPFederation";
23
+ alias = "federation-mcp";
24
+ origin = "github.com/ruinosus/dna/federation";
25
+ isPromptTarget = false;
26
+ promptTargetPriority = 0;
27
+ flattenInContext = false;
28
+ storage = SD.yaml("federations");
29
+ graphStyle = { fill: "#F97316", stroke: "#EA580C", textColor: "#fff" };
30
+ asciiIcon = "🛰️";
31
+ displayLabel = "MCP Federations";
32
+ docs = "An MCPFederation declares an external MCP server whose tools DNA " +
33
+ "agents consume: a Agent lists the doc's name in " +
34
+ "spec.mcp_servers and the harness loads the remote tools as " +
35
+ "first-class agent tools (zero code, zero deploy). Transports: " +
36
+ "stdio (command/args/env/cwd) or streamable_http (url). Auth " +
37
+ "carries env-var NAMES only — never secret values. allowed_tools " +
38
+ "bounds what any agent can get; enabled: false is the declarative " +
39
+ "kill-switch. Docs in _lib/federations/ are inherited by every " +
40
+ "scope. Also consumed by the DNA-as-MCP-server proxy (Phase 14r).";
41
+ dependencies() { return null; }
42
+ schema() {
43
+ // v2 (spec 2026-07-07-mcp-first-tools-design.md §5.1). Back-compat:
44
+ // every v1 doc (required command, stdio implied) stays valid —
45
+ // transport defaults to stdio and command is enforced for stdio
46
+ // (resp. url for streamable_http) via allOf/if-then instead of a
47
+ // top-level required: [command].
48
+ return {
49
+ type: "object",
50
+ additionalProperties: true,
51
+ properties: {
52
+ transport: {
53
+ type: "string",
54
+ enum: ["stdio", "streamable_http"],
55
+ default: "stdio",
56
+ description: "How to reach the server: stdio subprocess (default, v1) or Streamable HTTP.",
57
+ },
58
+ url: {
59
+ type: "string",
60
+ description: "Server endpoint. Required when transport=streamable_http.",
61
+ },
62
+ command: {
63
+ type: "string",
64
+ description: "Executable to run (resolved via PATH). Required when transport=stdio.",
65
+ },
66
+ args: { type: "array", items: { type: "string" }, default: [] },
67
+ env: {
68
+ type: "object",
69
+ additionalProperties: { type: "string" },
70
+ default: {},
71
+ description: "Extra env vars merged onto os.environ for the subprocess.",
72
+ },
73
+ cwd: {
74
+ type: ["string", "null"],
75
+ description: "Working directory; null = scope dir.",
76
+ },
77
+ tool_prefix: {
78
+ type: "string",
79
+ description: "Prepended to every proxied tool name (e.g. 'graphify_').",
80
+ default: "",
81
+ },
82
+ enabled: {
83
+ type: "boolean",
84
+ default: true,
85
+ description: "Disable without deleting the doc — declarative kill-switch, no deploy.",
86
+ },
87
+ allowed_tools: {
88
+ type: "array",
89
+ items: { type: "string" },
90
+ default: [],
91
+ description: "Server-level allowlist of remote tool names (pre-prefix). Empty = all.",
92
+ },
93
+ timeout_s: {
94
+ type: "integer",
95
+ default: 30,
96
+ description: "Per-call timeout default (seconds). Per-agent entry may override.",
97
+ },
98
+ auth: {
99
+ type: "object",
100
+ additionalProperties: false,
101
+ description: "Auth by env-var NAME — the value is read from the process env at connect time and never stored in docs, logs, or events.",
102
+ properties: {
103
+ kind: {
104
+ type: "string",
105
+ enum: ["none", "bearer_env", "header_env"],
106
+ default: "none",
107
+ },
108
+ env: {
109
+ type: "string",
110
+ description: "Name of the env var holding the secret value.",
111
+ },
112
+ header: {
113
+ type: "string",
114
+ description: "Header to carry the value (header_env only; bearer_env implies Authorization: Bearer).",
115
+ },
116
+ },
117
+ },
118
+ propagate_tenant: {
119
+ type: "boolean",
120
+ default: true,
121
+ description: "HTTP transport: stamp X-DNA-Tenant-Effective / X-DNA-Scope / X-DNA-Agent headers.",
122
+ },
123
+ health_check: {
124
+ type: "object",
125
+ additionalProperties: true,
126
+ properties: {
127
+ interval_s: { type: "integer", default: 30 },
128
+ timeout_s: { type: "integer", default: 5 },
129
+ },
130
+ },
131
+ tags: { type: "array", items: { type: "string" }, default: [] },
132
+ },
133
+ allOf: [
134
+ {
135
+ // NOTE: required: [transport] inside the `if` is load-bearing —
136
+ // without it an absent `transport` matches the const vacuously
137
+ // and v1 docs would be forced to carry `url`.
138
+ if: {
139
+ properties: { transport: { const: "streamable_http" } },
140
+ required: ["transport"],
141
+ },
142
+ then: { required: ["url"] },
143
+ else: { required: ["command"] },
144
+ },
145
+ ],
146
+ };
147
+ }
148
+ describe(doc) {
149
+ const spec = (doc.spec ?? {});
150
+ const transport = spec.transport || "stdio";
151
+ const target = (transport === "streamable_http" ? spec.url : spec.command) ?? "?";
152
+ const prefix = spec.tool_prefix ?? "";
153
+ return `${target || "?"} (${prefix || "no-prefix"})`;
154
+ }
155
+ summary(doc) {
156
+ const spec = (doc.spec ?? {});
157
+ return {
158
+ transport: spec.transport || "stdio",
159
+ url: spec.url ?? "",
160
+ command: spec.command ?? "",
161
+ tool_prefix: spec.tool_prefix ?? "",
162
+ enabled: spec.enabled ?? true,
163
+ tags: spec.tags ?? [],
164
+ };
165
+ }
166
+ }
167
+ export class FederationExtension {
168
+ name = "federation";
169
+ version = "1.0.0";
170
+ register(kernel) {
171
+ kernel.kind(new MCPFederationKind());
172
+ }
173
+ }
@@ -0,0 +1,20 @@
1
+ # Guardrail
2
+
3
+ A Guardrail declares a hard safety, compliance, or policy rule that must be
4
+ enforced on every turn of an agent's conversation. It is stored as a bundle
5
+ rooted on a `GUARDRAIL.md` marker file.
6
+
7
+ Unlike Skills (which are on-demand procedural know-how), Guardrails are
8
+ flattened directly into the agent's system prompt so the rules are always in
9
+ view. Each Guardrail carries a `severity` (`low`, `medium`, `high`, `critical`)
10
+ and a list of `rules` that the Agent template renders inline.
11
+
12
+ **Helix-native kind — not guardrails.ai.** This is not a binding for the
13
+ `guardrails.ai` runtime validator library. It is inspired by the tripwire /
14
+ input-output guardrail pattern from the OpenAI Agents SDK
15
+ (https://openai.github.io/openai-agents-python/guardrails/) but implemented
16
+ natively as a composable document kind. No external runtime is required;
17
+ enforcement is purely prompt-level.
18
+
19
+ **Composition:** referenced by Agents via `dep_filters.guardrails`
20
+ (alias `guardrails-guardrail`).
@@ -0,0 +1,31 @@
1
+ /**
2
+ * GuardrailExtension — Guardrail kind + GuardrailReader + GuardrailWriter.
3
+ *
4
+ * 1:1 parity with Python dna.v3.extensions.guardrails.
5
+ */
6
+ import type { BundleHandle } from "../kernel/bundle-handle.js";
7
+ import type { FSLike } from "../kernel/fs.js";
8
+ import type { ExtensionHost, Extension, ReaderPort, SerializedFile, WriterPort } from "../kernel/protocols.js";
9
+ export declare class GuardrailReader implements ReaderPort {
10
+ private fs;
11
+ constructor(fs?: FSLike);
12
+ detect(bundle: BundleHandle): boolean;
13
+ read(bundle: BundleHandle): Record<string, unknown>;
14
+ }
15
+ export declare class GuardrailWriter implements WriterPort {
16
+ private fs;
17
+ constructor(fs?: FSLike);
18
+ canWrite(raw: Record<string, unknown>): boolean;
19
+ /** Shared by write()/serialize() so the two surfaces cannot drift
20
+ * (s-dna-rw-roundtrip-suite). */
21
+ private entries;
22
+ serialize(raw: Record<string, unknown>): SerializedFile[];
23
+ write(bundle: BundleHandle, raw: Record<string, unknown>): void;
24
+ }
25
+ export declare class GuardrailExtension implements Extension {
26
+ private fs;
27
+ readonly name = "guardrails";
28
+ readonly version = "1.0.0";
29
+ constructor(fs?: FSLike);
30
+ register(kernel: ExtensionHost): void;
31
+ }
@@ -0,0 +1,228 @@
1
+ /**
2
+ * GuardrailExtension — Guardrail kind + GuardrailReader + GuardrailWriter.
3
+ *
4
+ * 1:1 parity with Python dna.v3.extensions.guardrails.
5
+ */
6
+ import yaml from "js-yaml";
7
+ import { nodeFS } from "../kernel/fs.js";
8
+ import { KindBase } from "../kernel/kind_base.js";
9
+ import { GuardrailSchema, GuardrailSpecSchema, zodSpecToJsonSchema } from "../kernel/models.js";
10
+ import { SD } from "../kernel/protocols.js";
11
+ // ---------------------------------------------------------------------------
12
+ // GuardrailKind
13
+ // ---------------------------------------------------------------------------
14
+ class GuardrailKind extends KindBase {
15
+ apiVersion = "github.com/ruinosus/dna/v1";
16
+ kind = "Guardrail";
17
+ alias = "guardrails-guardrail";
18
+ isSchemaAffecting = true;
19
+ origin = "github.com/ruinosus/dna/guardrails";
20
+ isPromptTarget = false;
21
+ promptTargetPriority = 0;
22
+ flattenInContext = false;
23
+ descriptionFallbackField = "instruction";
24
+ storage = SD.bundle("guardrails", "GUARDRAIL.md", "list", "rules");
25
+ graphStyle = { fill: "#EF4444", stroke: "#DC2626", textColor: "#fff" };
26
+ asciiIcon = "🛡️";
27
+ displayLabel = "Guardrails";
28
+ _sourceUrl = import.meta.url;
29
+ docs = "A Guardrail declares a hard safety, compliance, or policy rule " +
30
+ "enforced on every agent turn. Stored as a bundle rooted on " +
31
+ "GUARDRAIL.md. Flattened directly into the system prompt — helix- " +
32
+ "native, inspired by OpenAI Agents SDK tripwires, not guardrails.ai.";
33
+ uiSchema = {
34
+ instruction: {
35
+ widget: "markdown",
36
+ label: "GUARDRAIL.md",
37
+ help: "Prose body explaining the intent behind the rule set.",
38
+ height: 280,
39
+ order: 10,
40
+ },
41
+ rules: {
42
+ widget: "list-markdown",
43
+ label: "Rules",
44
+ help: "Individual directives the agent must follow every turn.",
45
+ order: 20,
46
+ },
47
+ severity: {
48
+ widget: "select",
49
+ label: "Severity",
50
+ help: "warn lets the turn continue; error fails the turn; hard refuses to answer.",
51
+ order: 30,
52
+ },
53
+ scope: {
54
+ widget: "select",
55
+ label: "Scope",
56
+ help: "input guards the user prompt; output guards the agent response; both runs on each side.",
57
+ order: 40,
58
+ },
59
+ };
60
+ schema() { return zodSpecToJsonSchema(GuardrailSpecSchema); }
61
+ parse(raw) {
62
+ return GuardrailSchema.parse(raw);
63
+ }
64
+ summary(doc) {
65
+ const spec = (doc.spec ?? {});
66
+ return {
67
+ severity: typeof spec.severity === "string" ? spec.severity : "warn",
68
+ scope: typeof spec.scope === "string" ? spec.scope : "both",
69
+ rules: Array.isArray(spec.rules) ? spec.rules.length : 0,
70
+ };
71
+ }
72
+ preview(doc) {
73
+ const spec = (doc.spec ?? {});
74
+ const blocks = [];
75
+ const instruction = typeof spec.instruction === "string" ? spec.instruction : "";
76
+ if (instruction) {
77
+ blocks.push({ kind: "markdown", title: "GUARDRAIL.md", body: instruction });
78
+ }
79
+ const rules = spec.rules;
80
+ if (Array.isArray(rules) && rules.length > 0) {
81
+ blocks.push({
82
+ kind: "markdown",
83
+ title: "Rules",
84
+ body: rules
85
+ .map((r) => `- ${typeof r === "string" ? r : JSON.stringify(r)}`)
86
+ .join("\n"),
87
+ });
88
+ }
89
+ const meta = [];
90
+ if (typeof spec.severity === "string")
91
+ meta.push({ label: "severity", value: spec.severity });
92
+ if (typeof spec.scope === "string")
93
+ meta.push({ label: "scope", value: spec.scope });
94
+ if (meta.length > 0) {
95
+ blocks.push({ kind: "fields", title: "Policy", fields: meta });
96
+ }
97
+ if (blocks.length === 0) {
98
+ return [{ kind: "empty", title: "Guardrail (empty)" }];
99
+ }
100
+ return blocks;
101
+ }
102
+ }
103
+ // ---------------------------------------------------------------------------
104
+ // GuardrailReader
105
+ // ---------------------------------------------------------------------------
106
+ function parseFrontmatter(text) {
107
+ const match = text.match(/^---\n([\s\S]*?)---\n?/);
108
+ if (!match)
109
+ return {};
110
+ try {
111
+ const parsed = yaml.load(match[1]);
112
+ return typeof parsed === "object" && parsed !== null ? parsed : {};
113
+ }
114
+ catch {
115
+ return {};
116
+ }
117
+ }
118
+ export class GuardrailReader {
119
+ fs;
120
+ constructor(fs = nodeFS) {
121
+ this.fs = fs;
122
+ }
123
+ detect(bundle) {
124
+ const path = bundle.path ?? "";
125
+ return this.fs.exists(`${path}/GUARDRAIL.md`);
126
+ }
127
+ read(bundle) {
128
+ const path = bundle.path ?? "";
129
+ const guardrailMd = this.fs.readFile(`${path}/GUARDRAIL.md`);
130
+ const metadata = parseFrontmatter(guardrailMd);
131
+ const name = String(metadata.name || "") || path.split("/").pop() || "";
132
+ const description = String(metadata.desc || metadata.description || "");
133
+ const severity = String(metadata.severity || "warn");
134
+ const scope = String(metadata.scope || "both");
135
+ // Extract body (after frontmatter)
136
+ const body = guardrailMd.replace(/^---\n[\s\S]*?---\n?/, "").trim();
137
+ // Parse rules from body: lines starting with "- "
138
+ const bodyRules = [];
139
+ for (const line of body.split("\n")) {
140
+ const trimmed = line.trimStart();
141
+ if (trimmed.startsWith("- ")) {
142
+ bodyRules.push(trimmed.slice(2).trim());
143
+ }
144
+ }
145
+ // Rules can come from frontmatter (YAML list) or body (markdown list)
146
+ const frontmatterRules = metadata.rules;
147
+ let rules;
148
+ if (Array.isArray(frontmatterRules) && frontmatterRules.length > 0) {
149
+ rules = frontmatterRules.map(String);
150
+ }
151
+ else {
152
+ rules = bodyRules;
153
+ }
154
+ return {
155
+ apiVersion: "github.com/ruinosus/dna/v1",
156
+ kind: "Guardrail",
157
+ metadata: { name, description },
158
+ spec: { rules, severity, scope },
159
+ };
160
+ }
161
+ }
162
+ // ---------------------------------------------------------------------------
163
+ // GuardrailWriter
164
+ // ---------------------------------------------------------------------------
165
+ export class GuardrailWriter {
166
+ fs;
167
+ constructor(fs = nodeFS) {
168
+ this.fs = fs;
169
+ }
170
+ canWrite(raw) {
171
+ return raw.kind === "Guardrail";
172
+ }
173
+ /** Shared by write()/serialize() so the two surfaces cannot drift
174
+ * (s-dna-rw-roundtrip-suite). */
175
+ entries(raw, defaultName) {
176
+ const spec = raw.spec ?? {};
177
+ const meta = raw.metadata ?? {};
178
+ const name = meta.name || defaultName;
179
+ const description = meta.description ?? "";
180
+ const severity = spec.severity ?? "warn";
181
+ const scope = spec.scope ?? "both";
182
+ const rules = spec.rules ?? [];
183
+ // Build frontmatter lines
184
+ const fmLines = [];
185
+ fmLines.push(`name: ${name}`);
186
+ if (description)
187
+ fmLines.push(`desc: ${description}`);
188
+ // Only write severity/scope if non-default
189
+ if (severity !== "warn")
190
+ fmLines.push(`severity: ${severity}`);
191
+ if (scope !== "both")
192
+ fmLines.push(`scope: ${scope}`);
193
+ const frontmatter = fmLines.join("\n");
194
+ // Build body: rules as "- " lines
195
+ const bodyLines = rules.map((r) => `- ${r}`);
196
+ const body = bodyLines.join("\n");
197
+ const content = body
198
+ ? `---\n${frontmatter}\n---\n\n${body}\n`
199
+ : `---\n${frontmatter}\n---\n`;
200
+ return [{ relativePath: "GUARDRAIL.md", content }];
201
+ }
202
+ serialize(raw) {
203
+ return this.entries(raw, "");
204
+ }
205
+ write(bundle, raw) {
206
+ const path = bundle.path ?? "";
207
+ this.fs.mkdir(path);
208
+ for (const f of this.entries(raw, path.split("/").pop() || "")) {
209
+ this.fs.writeFile(`${path}/${f.relativePath}`, f.content ?? "");
210
+ }
211
+ }
212
+ }
213
+ // ---------------------------------------------------------------------------
214
+ // Extension
215
+ // ---------------------------------------------------------------------------
216
+ export class GuardrailExtension {
217
+ fs;
218
+ name = "guardrails";
219
+ version = "1.0.0";
220
+ constructor(fs = nodeFS) {
221
+ this.fs = fs;
222
+ }
223
+ register(kernel) {
224
+ kernel.kind(new GuardrailKind());
225
+ kernel.reader(new GuardrailReader(this.fs));
226
+ kernel.writer(new GuardrailWriter(this.fs));
227
+ }
228
+ }
@@ -0,0 +1,20 @@
1
+ # Actor
2
+
3
+ An Actor is a UML-canonical participant in the system — a human user, an
4
+ external system, or a time/schedule trigger. Actors describe WHO or WHAT
5
+ initiates or collaborates with agents, separating role identity from the
6
+ agents that fulfill that role. Canonical api version:
7
+ `github.com/ruinosus/dna/v1`.
8
+
9
+ **Actor types.** The `actorType` field disambiguates:
10
+ - `human` — a person or role (e.g. "support specialist", "admin")
11
+ - `system` — an upstream service or external system triggering behavior
12
+ - `time` — a scheduled or cron-like trigger
13
+
14
+ **Composition.** Actors are referenced by UseCases (as `primary_actor` and
15
+ `supporting_actors`) and by Agents through `dep_filters.actors`.
16
+ Actors are NOT prompt targets on their own — they are structural metadata
17
+ that lets manifests document and wire the cast of characters around an
18
+ agent without embedding role descriptions in prompts.
19
+
20
+ **Storage.** Flat YAML file at `actors/<name>.yaml`.
@@ -0,0 +1,20 @@
1
+ # Agent
2
+
3
+ A Agent is the primary prompt target in a helix manifest — it is
4
+ what actually runs when a user (or another agent) talks to the system. It
5
+ carries an `instruction` (the agent's main prompt, usually a bundled
6
+ `AGENT.md`), a `model` to call, and `dep_filters` that declare which Soul,
7
+ Skills, Guardrails, and Actors it composes with.
8
+
9
+ **Prompt assembly.** Every turn the kernel builds the agent's system prompt
10
+ by rendering the `prompt_template`: the instruction body comes first, then
11
+ the Soul content (flattened in full), then each Guardrail (name, severity,
12
+ and rules). Skills are deliberately NOT flattened — they are exposed via
13
+ Agent Skills progressive disclosure so the context window stays lean.
14
+
15
+ **Priority.** `prompt_target_priority = 10` means Agent wins over
16
+ other prompt-target kinds when the harness has to pick one to run.
17
+
18
+ **Storage.** Bundle-based: `agents/<name>/AGENT.md` with optional
19
+ `scripts/`, `references/`, and `assets/` subdirectories. Canonical api
20
+ version: `github.com/ruinosus/dna/v1`.
@@ -0,0 +1,20 @@
1
+ # UseCase
2
+
3
+ A UseCase is a UML-canonical use case document: a goal-oriented interaction
4
+ between one or more Actors and the system. It composes a primary actor,
5
+ supporting actors, and the agent(s) that fulfill the goal, then carries the
6
+ classical UML fields: `preconditions`, `main_flow`, `alternate_flows`,
7
+ `postconditions`, and `success_criteria`. Canonical api version:
8
+ `github.com/ruinosus/dna/v1`.
9
+
10
+ **Not a prompt target.** A UseCase is purely declarative — it documents how
11
+ the manifest's agents and actors are meant to work together to achieve a
12
+ business goal. It is structural composition metadata, consumed by tooling
13
+ (navigators, doc generators, validators) rather than by the LLM directly.
14
+
15
+ **When to use.** Reach for UseCases when a helix manifest is complex
16
+ enough that the relationship between actors and agents is non-obvious, or
17
+ when you need machine-readable traceability from requirements to the agents
18
+ that implement them.
19
+
20
+ **Storage.** Flat YAML file at `use_cases/<name>.yaml`.
@@ -0,0 +1,12 @@
1
+ /**
2
+ * DEPRECATED shim — DefaultLayerResolver moved into the kernel.
3
+ *
4
+ * Layer resolution is a core kernel responsibility
5
+ * (s-invert-layer-resolver-dep, 2026-07-07): the kernel must work with
6
+ * zero extensions loaded, so the resolver now lives at
7
+ * `src/kernel/layer-resolver.ts`. This module reexports the old public
8
+ * names for external importers and emits a DeprecationWarning on import.
9
+ *
10
+ * @deprecated Import from `dna-sdk/kernel/layer-resolver` instead.
11
+ */
12
+ export { DefaultLayerResolver, deepMerge, mergeTimelineArrays, type LayerSource, } from "../../kernel/layer-resolver.js";
@@ -0,0 +1,18 @@
1
+ /**
2
+ * DEPRECATED shim — DefaultLayerResolver moved into the kernel.
3
+ *
4
+ * Layer resolution is a core kernel responsibility
5
+ * (s-invert-layer-resolver-dep, 2026-07-07): the kernel must work with
6
+ * zero extensions loaded, so the resolver now lives at
7
+ * `src/kernel/layer-resolver.ts`. This module reexports the old public
8
+ * names for external importers and emits a DeprecationWarning on import.
9
+ *
10
+ * @deprecated Import from `dna-sdk/kernel/layer-resolver` instead.
11
+ */
12
+ export { DefaultLayerResolver, deepMerge, mergeTimelineArrays, } from "../../kernel/layer-resolver.js";
13
+ // Node/Bun idiomatic import-time deprecation (parity with the Python
14
+ // shim's warnings.warn(DeprecationWarning)).
15
+ if (typeof process !== "undefined" && typeof process.emitWarning === "function") {
16
+ process.emitWarning("extensions/helix/layers is deprecated — import DefaultLayerResolver/" +
17
+ "deepMerge from kernel/layer-resolver instead (s-invert-layer-resolver-dep).", "DeprecationWarning");
18
+ }
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Helix-owned write-path guards (s-write-path-despecialize).
3
+ *
4
+ * These rules used to live inline in `Kernel.writeDocument` as
5
+ * `kind === "Agent"` special-cases — extension domain knowledge
6
+ * leaked into the microkernel. They are now `pre_save` VETO hooks
7
+ * registered by `HelixExtension.register` (the Agent owner):
8
+ *
9
+ * - platform-agent fork guard (priority 10) — no per-tenant overlay of a
10
+ * `_lib` Agent (JARVIS 16384 outage, 2026-05-29).
11
+ * - prompt-budget enforcement (priority 20) — an Agent whose instruction
12
+ * exceeds its model's `instruction_token_cap` (read from the
13
+ * ModelProfile registry — never hardcode token caps) is blocked when
14
+ * the model is strict (voice persona / `realtime: true` profile) and
15
+ * warned when it is a chat model (fail-open on unknown model / missing
16
+ * cap / instruction_file).
17
+ * - Kind-Writer contract (priority 30) — a Agent declaring
18
+ * `writes_kind` must satisfy the slot↔schema contract at write time.
19
+ *
20
+ * A throw from a guard vetoes the write (nothing is persisted). The hooks
21
+ * fire for EVERY `kernel.writeDocument` regardless of `skipHooks` — they
22
+ * are integrity gates, not notifications.
23
+ *
24
+ * 1:1 parity with Python dna.extensions.helix.write_guards.
25
+ */
26
+ import type { PreSaveContext } from "../../kernel/hooks.js";
27
+ import type { ExtensionHost } from "../../kernel/protocols.js";
28
+ export declare const PRIORITY_FORK_GUARD = 10;
29
+ export declare const PRIORITY_PROMPT_BUDGET = 20;
30
+ export declare const PRIORITY_KIND_WRITER = 30;
31
+ /**
32
+ * Block per-tenant overlays of `_lib` Agents.
33
+ *
34
+ * The `_lib` scope is the shared baseline (jarvis + the 12 transversais);
35
+ * its Agents are edited in git + `dna doc apply --scope _lib` (base
36
+ * only). A per-tenant overlay silently FORKS the persona and shadows the
37
+ * base for that tenant's reads — the root cause of the JARVIS 16384 outage
38
+ * (2026-05-29) and the stale-persona bug (2026-06-14). Veto it loudly.
39
+ */
40
+ export declare function platformAgentForkGuard(ctx: PreSaveContext): void;
41
+ /**
42
+ * Enforce the Agent instruction budget against the ModelProfile registry.
43
+ *
44
+ * CONTRACT — never hardcode token caps: the cap ALWAYS comes from the
45
+ * ModelProfile registry (`kernel.modelProfile(idOrAlias)` → the
46
+ * `modelreg-model-profile` Kind in `_lib`), never from a literal in code.
47
+ *
48
+ * Three paths (s-tier-a-modelprofile):
49
+ * - VETO — strict model (voice persona, or `realtime: true` profile) and
50
+ * the instruction estimate exceeds `instruction_token_cap`.
51
+ * - WARN — a chat Agent (`spec.model` declared, non-realtime profile)
52
+ * exceeds the cap: tolerated but logged loud.
53
+ * - PASS — no model declared, no profile found, no cap, or within budget.
54
+ * Enforcement is opt-in by DATA: writing a profile with a cap arms it.
55
+ *
56
+ * Fail-open on uncounted text (instruction_file / non-string body).
57
+ * `DNA_PROMPT_BUDGET_ENFORCE=0` downgrades the veto to a warn.
58
+ *
59
+ * 1:1 parity with Python `prompt_budget_guard`.
60
+ */
61
+ export declare function promptBudgetGuard(ctx: PreSaveContext): Promise<void>;
62
+ export declare function kindWriterContractGuard(ctx: PreSaveContext): void;
63
+ /**
64
+ * Wire the Helix write guards as `pre_save` veto hooks. Keys make the
65
+ * registration idempotent (re-loading the extension onto a shared
66
+ * HookRegistry replaces instead of stacking duplicates). Takes the
67
+ * `ExtensionHost` slice (s-dna-extension-host-contract) — registration
68
+ * goes through `kernel.hooks.onVeto` for the `key` idempotency.
69
+ */
70
+ export declare function registerWriteGuards(kernel: ExtensionHost): void;