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.
- package/LICENSE +21 -0
- package/README.md +58 -0
- package/dist/adapters/embedding/onnx.d.ts +32 -0
- package/dist/adapters/embedding/onnx.js +51 -0
- package/dist/adapters/filesystem/cache.d.ts +16 -0
- package/dist/adapters/filesystem/cache.js +113 -0
- package/dist/adapters/filesystem/index.d.ts +2 -0
- package/dist/adapters/filesystem/index.js +2 -0
- package/dist/adapters/filesystem/source.d.ts +82 -0
- package/dist/adapters/filesystem/source.js +357 -0
- package/dist/adapters/postgres/index.d.ts +2 -0
- package/dist/adapters/postgres/index.js +2 -0
- package/dist/adapters/postgres/migrations.d.ts +14 -0
- package/dist/adapters/postgres/migrations.js +88 -0
- package/dist/adapters/postgres/source.d.ts +172 -0
- package/dist/adapters/postgres/source.js +569 -0
- package/dist/adapters/resolvers/github.d.ts +12 -0
- package/dist/adapters/resolvers/github.js +47 -0
- package/dist/adapters/resolvers/http.d.ts +22 -0
- package/dist/adapters/resolvers/http.js +145 -0
- package/dist/adapters/resolvers/index.d.ts +3 -0
- package/dist/adapters/resolvers/index.js +3 -0
- package/dist/adapters/resolvers/local.d.ts +24 -0
- package/dist/adapters/resolvers/local.js +132 -0
- package/dist/adapters/search/driver.d.ts +45 -0
- package/dist/adapters/search/driver.js +138 -0
- package/dist/adapters/search/migrations.d.ts +26 -0
- package/dist/adapters/search/migrations.js +58 -0
- package/dist/adapters/search/rrf.d.ts +23 -0
- package/dist/adapters/search/rrf.js +42 -0
- package/dist/adapters/search/sqlite-vec.d.ts +66 -0
- package/dist/adapters/search/sqlite-vec.js +294 -0
- package/dist/bootstrap.d.ts +45 -0
- package/dist/bootstrap.js +134 -0
- package/dist/extensions/agentskills/DOCS.md +18 -0
- package/dist/extensions/agentskills.d.ts +28 -0
- package/dist/extensions/agentskills.js +252 -0
- package/dist/extensions/agentsmd/DOCS.md +18 -0
- package/dist/extensions/agentsmd.d.ts +22 -0
- package/dist/extensions/agentsmd.js +170 -0
- package/dist/extensions/audit/kinds/audit-log.kind.yaml +148 -0
- package/dist/extensions/audit.d.ts +25 -0
- package/dist/extensions/audit.js +62 -0
- package/dist/extensions/automation/kinds/automation.kind.yaml +296 -0
- package/dist/extensions/automation/query.d.ts +49 -0
- package/dist/extensions/automation/query.js +77 -0
- package/dist/extensions/automation/write-guards.d.ts +59 -0
- package/dist/extensions/automation/write-guards.js +153 -0
- package/dist/extensions/automation.d.ts +41 -0
- package/dist/extensions/automation.js +54 -0
- package/dist/extensions/collab.d.ts +16 -0
- package/dist/extensions/collab.js +79 -0
- package/dist/extensions/doc/kinds/doc.kind.yaml +118 -0
- package/dist/extensions/doc.d.ts +25 -0
- package/dist/extensions/doc.js +10 -0
- package/dist/extensions/eval/kinds/eval-baseline.kind.yaml +65 -0
- package/dist/extensions/eval/kinds/eval-case.kind.yaml +140 -0
- package/dist/extensions/eval/kinds/eval-run.kind.yaml +134 -0
- package/dist/extensions/eval/kinds/eval-suite.kind.yaml +87 -0
- package/dist/extensions/eval.d.ts +24 -0
- package/dist/extensions/eval.js +31 -0
- package/dist/extensions/evidence/kinds/evidence.kind.yaml +92 -0
- package/dist/extensions/evidence.d.ts +17 -0
- package/dist/extensions/evidence.js +94 -0
- package/dist/extensions/federation.d.ts +22 -0
- package/dist/extensions/federation.js +173 -0
- package/dist/extensions/guardrails/DOCS.md +20 -0
- package/dist/extensions/guardrails.d.ts +31 -0
- package/dist/extensions/guardrails.js +228 -0
- package/dist/extensions/helix/DOCS-Actor.md +20 -0
- package/dist/extensions/helix/DOCS-Agent.md +20 -0
- package/dist/extensions/helix/DOCS-UseCase.md +20 -0
- package/dist/extensions/helix/layers.d.ts +12 -0
- package/dist/extensions/helix/layers.js +18 -0
- package/dist/extensions/helix/write-guards.d.ts +70 -0
- package/dist/extensions/helix/write-guards.js +172 -0
- package/dist/extensions/helix.d.ts +29 -0
- package/dist/extensions/helix.js +963 -0
- package/dist/extensions/helix_extras.d.ts +124 -0
- package/dist/extensions/helix_extras.js +328 -0
- package/dist/extensions/hooks.d.ts +31 -0
- package/dist/extensions/hooks.js +247 -0
- package/dist/extensions/kinddef/DOCS.md +24 -0
- package/dist/extensions/kinddef.d.ts +40 -0
- package/dist/extensions/kinddef.js +171 -0
- package/dist/extensions/lesson.d.ts +6 -0
- package/dist/extensions/lesson.js +194 -0
- package/dist/extensions/modelreg/kinds/model-profile.kind.yaml +155 -0
- package/dist/extensions/modelreg.d.ts +30 -0
- package/dist/extensions/modelreg.js +38 -0
- package/dist/extensions/recognizer.d.ts +34 -0
- package/dist/extensions/recognizer.js +272 -0
- package/dist/extensions/research.d.ts +32 -0
- package/dist/extensions/research.js +292 -0
- package/dist/extensions/safety.d.ts +33 -0
- package/dist/extensions/safety.js +230 -0
- package/dist/extensions/sdlc/kinds/adr.kind.yaml +136 -0
- package/dist/extensions/sdlc/kinds/archive-proposal.kind.yaml +107 -0
- package/dist/extensions/sdlc/kinds/changelog.kind.yaml +108 -0
- package/dist/extensions/sdlc/kinds/cognitive-policy.kind.yaml +470 -0
- package/dist/extensions/sdlc/kinds/forecast.kind.yaml +125 -0
- package/dist/extensions/sdlc/kinds/insight.kind.yaml +87 -0
- package/dist/extensions/sdlc/kinds/kaizen.kind.yaml +106 -0
- package/dist/extensions/sdlc/kinds/lesson-learned.kind.yaml +270 -0
- package/dist/extensions/sdlc/kinds/narrative.kind.yaml +189 -0
- package/dist/extensions/sdlc/kinds/pattern-insight.kind.yaml +204 -0
- package/dist/extensions/sdlc/kinds/postmortem.kind.yaml +168 -0
- package/dist/extensions/sdlc/kinds/pre-mortem.kind.yaml +145 -0
- package/dist/extensions/sdlc/kinds/prompt-template.kind.yaml +109 -0
- package/dist/extensions/sdlc/kinds/retrospective.kind.yaml +186 -0
- package/dist/extensions/sdlc/kinds/risk-register.kind.yaml +178 -0
- package/dist/extensions/sdlc/kinds/saved-view.kind.yaml +127 -0
- package/dist/extensions/sdlc/kinds/status-report.kind.yaml +129 -0
- package/dist/extensions/sdlc/kinds/synthesis-run.kind.yaml +279 -0
- package/dist/extensions/sdlc/kinds/synthesizer-state.kind.yaml +196 -0
- package/dist/extensions/sdlc/kinds/workflow-event.kind.yaml +195 -0
- package/dist/extensions/sdlc.d.ts +32 -0
- package/dist/extensions/sdlc.js +1318 -0
- package/dist/extensions/soulspec/DOCS.md +19 -0
- package/dist/extensions/soulspec.d.ts +22 -0
- package/dist/extensions/soulspec.js +287 -0
- package/dist/extensions/tenant.d.ts +6 -0
- package/dist/extensions/tenant.js +291 -0
- package/dist/extensions/testkit.d.ts +24 -0
- package/dist/extensions/testkit.js +211 -0
- package/dist/index.d.ts +80 -0
- package/dist/index.js +102 -0
- package/dist/kernel/_text.d.ts +28 -0
- package/dist/kernel/_text.js +42 -0
- package/dist/kernel/bundle-handle.d.ts +83 -0
- package/dist/kernel/bundle-handle.js +184 -0
- package/dist/kernel/capabilities.d.ts +157 -0
- package/dist/kernel/capabilities.js +109 -0
- package/dist/kernel/collaborator-ports.d.ts +91 -0
- package/dist/kernel/collaborator-ports.js +1 -0
- package/dist/kernel/composition-resolver.d.ts +215 -0
- package/dist/kernel/composition-resolver.js +558 -0
- package/dist/kernel/composition.d.ts +10 -0
- package/dist/kernel/composition.js +1 -0
- package/dist/kernel/descriptor-loader.d.ts +13 -0
- package/dist/kernel/descriptor-loader.js +48 -0
- package/dist/kernel/document.d.ts +43 -0
- package/dist/kernel/document.js +71 -0
- package/dist/kernel/embedding.d.ts +28 -0
- package/dist/kernel/embedding.js +78 -0
- package/dist/kernel/errors.d.ts +62 -0
- package/dist/kernel/errors.js +82 -0
- package/dist/kernel/events.d.ts +6 -0
- package/dist/kernel/events.js +21 -0
- package/dist/kernel/evidence-capture.d.ts +69 -0
- package/dist/kernel/evidence-capture.js +138 -0
- package/dist/kernel/fs.d.ts +20 -0
- package/dist/kernel/fs.js +128 -0
- package/dist/kernel/generic-rw.d.ts +33 -0
- package/dist/kernel/generic-rw.js +235 -0
- package/dist/kernel/hooks.d.ts +172 -0
- package/dist/kernel/hooks.js +256 -0
- package/dist/kernel/index.d.ts +624 -0
- package/dist/kernel/index.js +1638 -0
- package/dist/kernel/instance.d.ts +211 -0
- package/dist/kernel/instance.js +487 -0
- package/dist/kernel/kind-registry.d.ts +183 -0
- package/dist/kernel/kind-registry.js +710 -0
- package/dist/kernel/kind_base.d.ts +106 -0
- package/dist/kernel/kind_base.js +244 -0
- package/dist/kernel/layer-resolver.d.ts +48 -0
- package/dist/kernel/layer-resolver.js +284 -0
- package/dist/kernel/lock-manager.d.ts +21 -0
- package/dist/kernel/lock-manager.js +43 -0
- package/dist/kernel/lock.d.ts +38 -0
- package/dist/kernel/lock.js +115 -0
- package/dist/kernel/meta.d.ts +135 -0
- package/dist/kernel/meta.js +817 -0
- package/dist/kernel/models.d.ts +3089 -0
- package/dist/kernel/models.js +764 -0
- package/dist/kernel/navigator.d.ts +36 -0
- package/dist/kernel/navigator.js +132 -0
- package/dist/kernel/port-surface.d.ts +33 -0
- package/dist/kernel/port-surface.js +180 -0
- package/dist/kernel/preview.d.ts +60 -0
- package/dist/kernel/preview.js +54 -0
- package/dist/kernel/prompt-budget.d.ts +39 -0
- package/dist/kernel/prompt-budget.js +43 -0
- package/dist/kernel/prompt-builder.d.ts +25 -0
- package/dist/kernel/prompt-builder.js +237 -0
- package/dist/kernel/protocols.d.ts +751 -0
- package/dist/kernel/protocols.js +493 -0
- package/dist/kernel/reports.d.ts +26 -0
- package/dist/kernel/reports.js +215 -0
- package/dist/kernel/resolver.d.ts +146 -0
- package/dist/kernel/resolver.js +232 -0
- package/dist/kernel/resource.d.ts +57 -0
- package/dist/kernel/resource.js +97 -0
- package/dist/kernel/runtime.d.ts +16 -0
- package/dist/kernel/runtime.js +18 -0
- package/dist/kernel/safety-scanner.d.ts +38 -0
- package/dist/kernel/safety-scanner.js +228 -0
- package/dist/kernel/serialize-to-files.d.ts +29 -0
- package/dist/kernel/serialize-to-files.js +23 -0
- package/dist/kernel/spec-access.d.ts +23 -0
- package/dist/kernel/spec-access.js +40 -0
- package/dist/kernel/studio_ui.d.ts +88 -0
- package/dist/kernel/studio_ui.js +135 -0
- package/dist/kernel/templates.d.ts +77 -0
- package/dist/kernel/templates.js +116 -0
- package/dist/kernel/tool-registry.d.ts +52 -0
- package/dist/kernel/tool-registry.js +89 -0
- package/dist/kernel/write-pipeline.d.ts +65 -0
- package/dist/kernel/write-pipeline.js +271 -0
- package/dist/kernel/writer-helpers.d.ts +24 -0
- package/dist/kernel/writer-helpers.js +42 -0
- package/dist/memory/decay.d.ts +31 -0
- package/dist/memory/decay.js +97 -0
- package/dist/memory/ecphory.d.ts +25 -0
- package/dist/memory/ecphory.js +178 -0
- package/dist/memory/encodingContext.d.ts +21 -0
- package/dist/memory/encodingContext.js +62 -0
- package/dist/memory/index.d.ts +23 -0
- package/dist/memory/index.js +23 -0
- package/dist/memory/memoryType.d.ts +7 -0
- package/dist/memory/memoryType.js +24 -0
- package/dist/memory/policy.d.ts +35 -0
- package/dist/memory/policy.js +35 -0
- package/dist/memory/retrieval.d.ts +21 -0
- package/dist/memory/retrieval.js +145 -0
- package/dist/testing/index.d.ts +8 -0
- package/dist/testing/index.js +8 -0
- package/dist/testing/recordSearchConformance.d.ts +43 -0
- package/dist/testing/recordSearchConformance.js +147 -0
- package/dist/viz/ascii.d.ts +7 -0
- package/dist/viz/ascii.js +60 -0
- package/dist/viz/health.d.ts +8 -0
- package/dist/viz/health.js +161 -0
- package/dist/viz/index.d.ts +10 -0
- package/dist/viz/index.js +10 -0
- package/dist/viz/matrix.d.ts +8 -0
- package/dist/viz/matrix.js +84 -0
- package/dist/viz/mermaid.d.ts +38 -0
- package/dist/viz/mermaid.js +706 -0
- package/package.json +82 -0
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AgentSkillsExtension — Skill kind + SkillReader.
|
|
3
|
+
*
|
|
4
|
+
* 1:1 parity with Python dna.v3.extensions.agentskills.
|
|
5
|
+
*/
|
|
6
|
+
import yaml from "js-yaml";
|
|
7
|
+
import { deriveFirstLine } from "../kernel/_text.js";
|
|
8
|
+
import { SkillSchema, SkillSpecSchema, zodSpecToJsonSchema } from "../kernel/models.js";
|
|
9
|
+
import { KindBase } from "../kernel/kind_base.js";
|
|
10
|
+
import { SD } from "../kernel/protocols.js";
|
|
11
|
+
import { nodeFS, readTextSafe, collectDir } from "../kernel/fs.js";
|
|
12
|
+
// ---------------------------------------------------------------------------
|
|
13
|
+
// SkillKind
|
|
14
|
+
// ---------------------------------------------------------------------------
|
|
15
|
+
class SkillKind extends KindBase {
|
|
16
|
+
apiVersion = "agentskills.io/v1";
|
|
17
|
+
kind = "Skill";
|
|
18
|
+
alias = "agentskills-skill";
|
|
19
|
+
isSchemaAffecting = true;
|
|
20
|
+
origin = "agentskills.io";
|
|
21
|
+
isPromptTarget = false;
|
|
22
|
+
promptTargetPriority = 0;
|
|
23
|
+
flattenInContext = false;
|
|
24
|
+
descriptionFallbackField = "instruction";
|
|
25
|
+
storage = SD.bundle("skills", "SKILL.md");
|
|
26
|
+
graphStyle = { fill: "#10B981", stroke: "#059669", textColor: "#fff" };
|
|
27
|
+
asciiIcon = "📖";
|
|
28
|
+
displayLabel = "Skills";
|
|
29
|
+
_sourceUrl = import.meta.url;
|
|
30
|
+
docs = "A Skill is a modular, progressively-disclosed unit of know-how stored " +
|
|
31
|
+
"as a bundle rooted on SKILL.md with optional scripts/, references/, " +
|
|
32
|
+
"assets/. Skills are NOT flattened into prompts; the harness exposes a " +
|
|
33
|
+
"catalogue and agents read full SKILL.md on demand.";
|
|
34
|
+
uiSchema = {
|
|
35
|
+
instruction: {
|
|
36
|
+
widget: "markdown-toc",
|
|
37
|
+
label: "SKILL.md",
|
|
38
|
+
help: "The skill's instruction body (progressive disclosure, ≤500 lines).",
|
|
39
|
+
height: 520,
|
|
40
|
+
order: 10,
|
|
41
|
+
},
|
|
42
|
+
scripts: { widget: "readonly", label: "scripts/", help: "Bundled scripts directory. Edit on disk.", order: 20 },
|
|
43
|
+
references: { widget: "readonly", label: "references/", help: "Bundled reference files. Edit on disk.", order: 30 },
|
|
44
|
+
assets: { widget: "readonly", label: "assets/", help: "Binary/static assets. Edit on disk.", order: 40 },
|
|
45
|
+
};
|
|
46
|
+
schema() { return zodSpecToJsonSchema(SkillSpecSchema); }
|
|
47
|
+
parse(raw) {
|
|
48
|
+
return SkillSchema.parse(raw);
|
|
49
|
+
}
|
|
50
|
+
summary() { return null; }
|
|
51
|
+
preview(doc) {
|
|
52
|
+
const spec = (doc.spec ?? {});
|
|
53
|
+
const instruction = typeof spec.instruction === "string" ? spec.instruction : "";
|
|
54
|
+
if (!instruction) {
|
|
55
|
+
return [{ kind: "empty", title: "Skill (empty)" }];
|
|
56
|
+
}
|
|
57
|
+
return [
|
|
58
|
+
{
|
|
59
|
+
kind: "markdown",
|
|
60
|
+
title: "SKILL.md",
|
|
61
|
+
body: instruction,
|
|
62
|
+
},
|
|
63
|
+
];
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
// ---------------------------------------------------------------------------
|
|
67
|
+
// SkillReader
|
|
68
|
+
// ---------------------------------------------------------------------------
|
|
69
|
+
const KNOWN_DIRS = new Set(["scripts", "references", "assets"]);
|
|
70
|
+
export class SkillReader {
|
|
71
|
+
fs;
|
|
72
|
+
constructor(fs) {
|
|
73
|
+
this.fs = fs;
|
|
74
|
+
}
|
|
75
|
+
detect(bundle) {
|
|
76
|
+
const path = bundle.path ?? "";
|
|
77
|
+
return this.fs.exists(`${path}/SKILL.md`);
|
|
78
|
+
}
|
|
79
|
+
read(bundle) {
|
|
80
|
+
const path = bundle.path ?? "";
|
|
81
|
+
const skillMd = this.fs.readFile(`${path}/SKILL.md`);
|
|
82
|
+
const metadata = parseFrontmatter(skillMd);
|
|
83
|
+
const name = (typeof metadata.name === "string" && metadata.name) ||
|
|
84
|
+
path.split("/").pop() ||
|
|
85
|
+
"";
|
|
86
|
+
const description = typeof metadata.description === "string" ? metadata.description : "";
|
|
87
|
+
// Extract body (after frontmatter) — F3 market fidelity: keep the
|
|
88
|
+
// tail byte-exact except the ONE leading newline the writer
|
|
89
|
+
// canonically re-emits ("---\\n\\n"). Trailing newlines and extra
|
|
90
|
+
// blank lines are part of the artifact.
|
|
91
|
+
const fmMatch = skillMd.match(/^---\n[\s\S]*?---(?:\n|$)/);
|
|
92
|
+
const tail = fmMatch ? skillMd.slice(fmMatch[0].length) : skillMd;
|
|
93
|
+
const body = tail.startsWith("\n") ? tail.slice(1) : tail;
|
|
94
|
+
const spec = { instruction: body };
|
|
95
|
+
// Collect known subdirectories (scripts/, references/, assets/)
|
|
96
|
+
for (const dirName of KNOWN_DIRS) {
|
|
97
|
+
const sub = `${path}/${dirName}`;
|
|
98
|
+
if (this.fs.isDirectory(sub)) {
|
|
99
|
+
const files = collectDir(this.fs, sub, sub);
|
|
100
|
+
if (Object.keys(files).length > 0) {
|
|
101
|
+
spec[dirName] = files;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
// Single readDir call, reused for extras + root files
|
|
106
|
+
const entries = this.fs.readDir(path);
|
|
107
|
+
// Collect ALL other subdirectories as extra bundles
|
|
108
|
+
const extras = {};
|
|
109
|
+
for (const entry of entries) {
|
|
110
|
+
const full = `${path}/${entry}`;
|
|
111
|
+
if (!this.fs.isDirectory(full) || KNOWN_DIRS.has(entry))
|
|
112
|
+
continue;
|
|
113
|
+
const files = collectDir(this.fs, full, full);
|
|
114
|
+
if (Object.keys(files).length > 0) {
|
|
115
|
+
extras[entry] = files;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
if (Object.keys(extras).length > 0) {
|
|
119
|
+
spec.extras = extras;
|
|
120
|
+
}
|
|
121
|
+
// Collect root-level extra files (not SKILL.md)
|
|
122
|
+
const rootFiles = {};
|
|
123
|
+
for (const entry of entries) {
|
|
124
|
+
const full = `${path}/${entry}`;
|
|
125
|
+
if (!this.fs.isFile(full) || entry === "SKILL.md")
|
|
126
|
+
continue;
|
|
127
|
+
const text = readTextSafe(this.fs, full);
|
|
128
|
+
if (text !== null) {
|
|
129
|
+
rootFiles[entry] = text;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
if (Object.keys(rootFiles).length > 0) {
|
|
133
|
+
spec.root_files = rootFiles;
|
|
134
|
+
}
|
|
135
|
+
// Preserve all frontmatter keys (tags, owner, priority, …). SkillWriter
|
|
136
|
+
// already round-trips extras; spreading metadata first then overriding
|
|
137
|
+
// name/description defaults closes the asymmetry on the reader side.
|
|
138
|
+
return {
|
|
139
|
+
apiVersion: "agentskills.io/v1",
|
|
140
|
+
kind: "Skill",
|
|
141
|
+
metadata: { ...metadata, name, description },
|
|
142
|
+
spec,
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
function parseFrontmatter(text) {
|
|
147
|
+
const match = text.match(/^---\n([\s\S]*?)---\n?/);
|
|
148
|
+
if (!match)
|
|
149
|
+
return {};
|
|
150
|
+
try {
|
|
151
|
+
const parsed = yaml.load(match[1]);
|
|
152
|
+
if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)) {
|
|
153
|
+
return parsed;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
catch { }
|
|
157
|
+
return {};
|
|
158
|
+
}
|
|
159
|
+
// ---------------------------------------------------------------------------
|
|
160
|
+
// SkillWriter
|
|
161
|
+
// ---------------------------------------------------------------------------
|
|
162
|
+
export class SkillWriter {
|
|
163
|
+
fs;
|
|
164
|
+
constructor(fs) {
|
|
165
|
+
this.fs = fs;
|
|
166
|
+
}
|
|
167
|
+
canWrite(raw) {
|
|
168
|
+
return raw.kind === "Skill";
|
|
169
|
+
}
|
|
170
|
+
write(bundle, raw) {
|
|
171
|
+
const path = bundle.path ?? "";
|
|
172
|
+
this.fs.mkdir(path);
|
|
173
|
+
for (const f of this.serialize(raw)) {
|
|
174
|
+
this.fs.writeFile(`${path}/${f.relativePath}`, f.content ?? "");
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
serialize(raw) {
|
|
178
|
+
const files = [];
|
|
179
|
+
const meta = (raw.metadata ?? {});
|
|
180
|
+
const spec = (raw.spec ?? {});
|
|
181
|
+
// SKILL.md with frontmatter + instruction body
|
|
182
|
+
const fm = {};
|
|
183
|
+
if (meta.name)
|
|
184
|
+
fm.name = meta.name;
|
|
185
|
+
if (meta.description)
|
|
186
|
+
fm.description = meta.description;
|
|
187
|
+
// Preserve extra metadata (e.g. tenant for RLS) — frontmatter is the
|
|
188
|
+
// authoritative metadata block for bundle kinds.
|
|
189
|
+
for (const [key, value] of Object.entries(meta)) {
|
|
190
|
+
if (key === "name" || key === "description")
|
|
191
|
+
continue;
|
|
192
|
+
if (value == null)
|
|
193
|
+
continue;
|
|
194
|
+
fm[key] = value;
|
|
195
|
+
}
|
|
196
|
+
// F3 market fidelity: metadata.description may have been ENRICHED at
|
|
197
|
+
// parse time (deriveFirstLine of the body). Persisting it would emit
|
|
198
|
+
// frontmatter the source bundle never had — elide when derivable.
|
|
199
|
+
if (typeof fm.description === "string" && fm.description === deriveFirstLine(spec.instruction ?? "")) {
|
|
200
|
+
delete fm.description;
|
|
201
|
+
}
|
|
202
|
+
// lineWidth: real marketplace skills author description as ONE long
|
|
203
|
+
// line — the default width 80 would wrap it (not byte-faithful).
|
|
204
|
+
const frontmatter = yaml.dump(fm, { flowLevel: -1, sortKeys: false, lineWidth: -1 });
|
|
205
|
+
const instruction = spec.instruction ?? "";
|
|
206
|
+
files.push({ relativePath: "SKILL.md", content: `---\n${frontmatter}---\n\n${instruction}` });
|
|
207
|
+
// Sub-directories: scripts, references, assets
|
|
208
|
+
for (const dirName of ["scripts", "references", "assets"]) {
|
|
209
|
+
const dirFiles = spec[dirName];
|
|
210
|
+
if (dirFiles != null && typeof dirFiles === "object") {
|
|
211
|
+
for (const [fname, fcontent] of Object.entries(dirFiles)) {
|
|
212
|
+
files.push({ relativePath: `${dirName}/${fname}`, content: fcontent });
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
// Extras
|
|
217
|
+
const extras = spec.extras;
|
|
218
|
+
if (extras != null && typeof extras === "object") {
|
|
219
|
+
for (const [dirName, dirFiles] of Object.entries(extras)) {
|
|
220
|
+
if (typeof dirFiles === "object") {
|
|
221
|
+
for (const [fname, fcontent] of Object.entries(dirFiles)) {
|
|
222
|
+
files.push({ relativePath: `${dirName}/${fname}`, content: fcontent });
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
// Root files
|
|
228
|
+
const rootFiles = spec.root_files;
|
|
229
|
+
if (rootFiles != null && typeof rootFiles === "object") {
|
|
230
|
+
for (const [fname, fcontent] of Object.entries(rootFiles)) {
|
|
231
|
+
files.push({ relativePath: fname, content: fcontent });
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
return files;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
// ---------------------------------------------------------------------------
|
|
238
|
+
// Extension
|
|
239
|
+
// ---------------------------------------------------------------------------
|
|
240
|
+
export class AgentSkillsExtension {
|
|
241
|
+
fs;
|
|
242
|
+
name = "agentskills";
|
|
243
|
+
version = "1.0.0";
|
|
244
|
+
constructor(fs = nodeFS) {
|
|
245
|
+
this.fs = fs;
|
|
246
|
+
}
|
|
247
|
+
register(kernel) {
|
|
248
|
+
kernel.kind(new SkillKind());
|
|
249
|
+
kernel.reader(new SkillReader(this.fs));
|
|
250
|
+
kernel.writer(new SkillWriter(this.fs));
|
|
251
|
+
}
|
|
252
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# AgentDefinition (AGENTS.md)
|
|
2
|
+
|
|
3
|
+
AgentDefinition wraps a standalone `AGENTS.md` file as a first-class document
|
|
4
|
+
kind. `AGENTS.md` is an emerging community convention
|
|
5
|
+
(https://agents.md) for giving coding agents repo-level instructions —
|
|
6
|
+
similar in spirit to `README.md` but targeted at autonomous agents rather than
|
|
7
|
+
human readers.
|
|
8
|
+
|
|
9
|
+
The AgentsMdExtension scans for a top-level `AGENTS.md` in the manifest scope
|
|
10
|
+
and exposes its content as a document. It is NOT a prompt target on its own;
|
|
11
|
+
it is context material that agents and tooling can surface when operating in
|
|
12
|
+
that repository.
|
|
13
|
+
|
|
14
|
+
**When to use:** drop an `AGENTS.md` alongside your module manifest to record
|
|
15
|
+
repo-wide conventions, coding style, test commands, or operational notes that
|
|
16
|
+
any agent working in the scope should respect. Unlike Souls (which describe
|
|
17
|
+
voice) and Skills (which describe procedures), AgentContext describes the
|
|
18
|
+
environment the agent is working in.
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AgentsMdExtension — AgentDefinition kind + AgentDefinitionReader + Writer.
|
|
3
|
+
*
|
|
4
|
+
* 1:1 parity with Python dna.v3.extensions.agentsmd.
|
|
5
|
+
*/
|
|
6
|
+
import type { BundleHandle } from "../kernel/bundle-handle.js";
|
|
7
|
+
import type { FSLike } from "../kernel/fs.js";
|
|
8
|
+
import type { ExtensionHost, Extension, SerializedFile, WriterPort } from "../kernel/protocols.js";
|
|
9
|
+
export declare class AgentDefinitionWriter implements WriterPort {
|
|
10
|
+
private fs;
|
|
11
|
+
constructor(fs?: FSLike);
|
|
12
|
+
canWrite(raw: Record<string, unknown>): boolean;
|
|
13
|
+
write(bundle: BundleHandle, raw: Record<string, unknown>): void;
|
|
14
|
+
serialize(raw: Record<string, unknown>): SerializedFile[];
|
|
15
|
+
}
|
|
16
|
+
export declare class AgentsMdExtension implements Extension {
|
|
17
|
+
private fs;
|
|
18
|
+
readonly name = "agentsmd";
|
|
19
|
+
readonly version = "1.0.0";
|
|
20
|
+
constructor(fs?: FSLike);
|
|
21
|
+
register(kernel: ExtensionHost): void;
|
|
22
|
+
}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AgentsMdExtension — AgentDefinition kind + AgentDefinitionReader + Writer.
|
|
3
|
+
*
|
|
4
|
+
* 1:1 parity with Python dna.v3.extensions.agentsmd.
|
|
5
|
+
*/
|
|
6
|
+
import yaml from "js-yaml";
|
|
7
|
+
import { deriveFirstLine } from "../kernel/_text.js";
|
|
8
|
+
import { nodeFS } from "../kernel/fs.js";
|
|
9
|
+
import { KindBase } from "../kernel/kind_base.js";
|
|
10
|
+
import { AgentDefinitionSchema, AgentDefinitionSpecSchema, zodSpecToJsonSchema } from "../kernel/models.js";
|
|
11
|
+
import { SD } from "../kernel/protocols.js";
|
|
12
|
+
// ---------------------------------------------------------------------------
|
|
13
|
+
// Frontmatter helpers
|
|
14
|
+
// ---------------------------------------------------------------------------
|
|
15
|
+
function parseAgentsFrontmatter(text) {
|
|
16
|
+
const match = text.match(/^---\n([\s\S]*?)---\n?([\s\S]*)$/);
|
|
17
|
+
if (!match)
|
|
18
|
+
return { metadata: {}, body: text };
|
|
19
|
+
try {
|
|
20
|
+
const parsed = yaml.load(match[1]);
|
|
21
|
+
if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)) {
|
|
22
|
+
return {
|
|
23
|
+
metadata: parsed,
|
|
24
|
+
body: match[2].replace(/^\n+/, ""),
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
catch { }
|
|
29
|
+
return { metadata: {}, body: text };
|
|
30
|
+
}
|
|
31
|
+
// ---------------------------------------------------------------------------
|
|
32
|
+
// AgentDefinitionKind
|
|
33
|
+
// ---------------------------------------------------------------------------
|
|
34
|
+
class AgentDefinitionKind extends KindBase {
|
|
35
|
+
apiVersion = "agents.md/v1";
|
|
36
|
+
kind = "AgentDefinition";
|
|
37
|
+
alias = "agentsmd-agent";
|
|
38
|
+
origin = "agents.md";
|
|
39
|
+
isPromptTarget = true;
|
|
40
|
+
promptTargetPriority = 1;
|
|
41
|
+
flattenInContext = true;
|
|
42
|
+
descriptionFallbackField = "content";
|
|
43
|
+
storage = SD.standalone("AGENTS.md");
|
|
44
|
+
graphStyle = { fill: "#6366F1", stroke: "#4F46E5", textColor: "#fff" };
|
|
45
|
+
asciiIcon = "📝";
|
|
46
|
+
displayLabel = "AGENTS.md";
|
|
47
|
+
_sourceUrl = import.meta.url;
|
|
48
|
+
docs = "AgentDefinition wraps a standalone AGENTS.md file — the emerging " +
|
|
49
|
+
"community convention (https://agents.md) for repo-level coding-agent " +
|
|
50
|
+
"instructions. Flattened into context for agents working in the scope.";
|
|
51
|
+
schema() { return zodSpecToJsonSchema(AgentDefinitionSpecSchema); }
|
|
52
|
+
parse(raw) {
|
|
53
|
+
return AgentDefinitionSchema.parse(raw);
|
|
54
|
+
}
|
|
55
|
+
summary() { return null; }
|
|
56
|
+
promptTemplate() {
|
|
57
|
+
return "{{{content}}}";
|
|
58
|
+
}
|
|
59
|
+
preview(doc) {
|
|
60
|
+
const spec = (doc.spec ?? {});
|
|
61
|
+
const content = typeof spec.content === "string" ? spec.content : "";
|
|
62
|
+
if (!content) {
|
|
63
|
+
return [{ kind: "empty", title: "AGENTS.md (empty)" }];
|
|
64
|
+
}
|
|
65
|
+
return [{ kind: "markdown", title: "AGENTS.md", body: content }];
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
// ---------------------------------------------------------------------------
|
|
69
|
+
// AgentDefinitionReader
|
|
70
|
+
// ---------------------------------------------------------------------------
|
|
71
|
+
class AgentDefinitionReader {
|
|
72
|
+
fs;
|
|
73
|
+
constructor(fs) {
|
|
74
|
+
this.fs = fs;
|
|
75
|
+
}
|
|
76
|
+
detect(bundle) {
|
|
77
|
+
const path = bundle.path ?? "";
|
|
78
|
+
if (!this.fs.exists(`${path}/AGENTS.md`))
|
|
79
|
+
return false;
|
|
80
|
+
// Skip if inside a soul bundle
|
|
81
|
+
if (this.fs.exists(`${path}/SOUL.md`) || this.fs.exists(`${path}/soul.json`)) {
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
84
|
+
return true;
|
|
85
|
+
}
|
|
86
|
+
read(bundle) {
|
|
87
|
+
const path = bundle.path ?? "";
|
|
88
|
+
const text = this.fs.readFile(`${path}/AGENTS.md`);
|
|
89
|
+
const name = path.split("/").pop() || "";
|
|
90
|
+
const { metadata: fm, body } = parseAgentsFrontmatter(text);
|
|
91
|
+
const metadata = { ...fm };
|
|
92
|
+
if (metadata.name == null)
|
|
93
|
+
metadata.name = name;
|
|
94
|
+
// When no frontmatter was present, preserve the full original text
|
|
95
|
+
// (byte-compat). When frontmatter IS present, spec.content is the body
|
|
96
|
+
// after it.
|
|
97
|
+
const hasFm = Object.keys(fm).length > 0;
|
|
98
|
+
const content = hasFm ? body : text;
|
|
99
|
+
return {
|
|
100
|
+
apiVersion: "agents.md/v1",
|
|
101
|
+
kind: "AgentDefinition",
|
|
102
|
+
metadata,
|
|
103
|
+
spec: { content },
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
// ---------------------------------------------------------------------------
|
|
108
|
+
// AgentDefinitionWriter
|
|
109
|
+
// ---------------------------------------------------------------------------
|
|
110
|
+
export class AgentDefinitionWriter {
|
|
111
|
+
fs;
|
|
112
|
+
constructor(fs = nodeFS) {
|
|
113
|
+
this.fs = fs;
|
|
114
|
+
}
|
|
115
|
+
canWrite(raw) {
|
|
116
|
+
return raw.kind === "AgentDefinition";
|
|
117
|
+
}
|
|
118
|
+
write(bundle, raw) {
|
|
119
|
+
const path = bundle.path ?? "";
|
|
120
|
+
this.fs.mkdir(path);
|
|
121
|
+
for (const f of this.serialize(raw)) {
|
|
122
|
+
this.fs.writeFile(`${path}/${f.relativePath}`, f.content ?? "");
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
serialize(raw) {
|
|
126
|
+
const spec = (raw.spec ?? {});
|
|
127
|
+
const meta = (raw.metadata ?? {});
|
|
128
|
+
const body = (spec.content ?? "") || "";
|
|
129
|
+
// Drop null/undefined before deciding whether to emit frontmatter.
|
|
130
|
+
const fm = {};
|
|
131
|
+
for (const [k, v] of Object.entries(meta)) {
|
|
132
|
+
if (v == null)
|
|
133
|
+
continue;
|
|
134
|
+
fm[k] = v;
|
|
135
|
+
}
|
|
136
|
+
// F3 market fidelity: metadata.description may have been ENRICHED at
|
|
137
|
+
// parse time (deriveFirstLine of the body). Persisting it would emit
|
|
138
|
+
// frontmatter the source bundle never had — elide when derivable.
|
|
139
|
+
if (typeof fm.description === "string" && fm.description === deriveFirstLine(body)) {
|
|
140
|
+
delete fm.description;
|
|
141
|
+
}
|
|
142
|
+
const bodyHasFm = body.trimStart().startsWith("---");
|
|
143
|
+
const fmKeys = Object.keys(fm);
|
|
144
|
+
// Byte-compat for the simple "only name" case — previous writer emitted
|
|
145
|
+
// just the body. Keeps existing fixture AGENTS.md files from diffing.
|
|
146
|
+
const onlyName = fmKeys.length === 0 || (fmKeys.length === 1 && fmKeys[0] === "name");
|
|
147
|
+
const needsFm = fmKeys.length > 0 && !bodyHasFm && !onlyName;
|
|
148
|
+
if (needsFm) {
|
|
149
|
+
const fmBody = yaml.dump(fm, { flowLevel: -1, sortKeys: false, lineWidth: -1 }).replace(/\n+$/, "");
|
|
150
|
+
return [{ relativePath: "AGENTS.md", content: `---\n${fmBody}\n---\n${body}` }];
|
|
151
|
+
}
|
|
152
|
+
return [{ relativePath: "AGENTS.md", content: body }];
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
// ---------------------------------------------------------------------------
|
|
156
|
+
// Extension
|
|
157
|
+
// ---------------------------------------------------------------------------
|
|
158
|
+
export class AgentsMdExtension {
|
|
159
|
+
fs;
|
|
160
|
+
name = "agentsmd";
|
|
161
|
+
version = "1.0.0";
|
|
162
|
+
constructor(fs = nodeFS) {
|
|
163
|
+
this.fs = fs;
|
|
164
|
+
}
|
|
165
|
+
register(kernel) {
|
|
166
|
+
kernel.kind(new AgentDefinitionKind());
|
|
167
|
+
kernel.reader(new AgentDefinitionReader(this.fs));
|
|
168
|
+
kernel.writer(new AgentDefinitionWriter(this.fs));
|
|
169
|
+
}
|
|
170
|
+
}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
# AuditLog — immutable record of a role-gated HTTP endpoint invocation
|
|
2
|
+
# (record plane, runtime artifact; written by emit_audit() from gated handlers).
|
|
3
|
+
#
|
|
4
|
+
# expr batch A (plan 2026-06-11-descriptor-expressiveness, Chunk 3): the
|
|
5
|
+
# twin AuditLogKind classes (Py+TS) were DELETED — this descriptor is the
|
|
6
|
+
# single source. First builtin Kind to carry the new D2 `ui:` descriptor
|
|
7
|
+
# field (StudioUIMetadata reconstructed by DeclarativeKindPort and served
|
|
8
|
+
# by kinds-api's /kinds/manifest verbatim — the class's `ui` block).
|
|
9
|
+
# PARITY-CRITICAL package data: the byte-identical mirror lives at
|
|
10
|
+
# packages/sdk-{py,ts}/{dna/extensions,src/extensions}/audit/kinds/
|
|
11
|
+
# audit-log.kind.yaml (tests/test_descriptor_hash_parity.py enforces).
|
|
12
|
+
# Equivalence with the extinct class frozen in
|
|
13
|
+
# tests/test_expr_batch_a_equivalence.py.
|
|
14
|
+
#
|
|
15
|
+
# tenant_scope: tenanted is DECLARED — the class set scope=TenantScope.TENANTED
|
|
16
|
+
# explicitly (each tenant sees only their own audit trail; platform admins
|
|
17
|
+
# query cross-tenant). This is NOT the permissive-undeclared case.
|
|
18
|
+
apiVersion: github.com/ruinosus/dna/core/v1
|
|
19
|
+
kind: KindDefinition
|
|
20
|
+
metadata:
|
|
21
|
+
name: audit-log
|
|
22
|
+
spec:
|
|
23
|
+
target_api_version: github.com/ruinosus/dna/audit/v1
|
|
24
|
+
target_kind: AuditLog
|
|
25
|
+
alias: audit-auditlog
|
|
26
|
+
origin: github.com/ruinosus/dna/audit
|
|
27
|
+
tenant_scope: tenanted
|
|
28
|
+
plane: record
|
|
29
|
+
prompt_target: false
|
|
30
|
+
flatten_in_context: false
|
|
31
|
+
prompt_target_priority: 0
|
|
32
|
+
is_runtime_artifact: true
|
|
33
|
+
storage:
|
|
34
|
+
type: yaml
|
|
35
|
+
container: audit-log
|
|
36
|
+
schema:
|
|
37
|
+
type: object
|
|
38
|
+
required:
|
|
39
|
+
- actor
|
|
40
|
+
- roles
|
|
41
|
+
- operation
|
|
42
|
+
- outcome
|
|
43
|
+
- captured_at
|
|
44
|
+
additionalProperties: true
|
|
45
|
+
properties:
|
|
46
|
+
actor:
|
|
47
|
+
type: string
|
|
48
|
+
description: Identity that made the request. From claims.email > claims.sub.
|
|
49
|
+
'dev-user' in dev-bypass, 'test-user' in test-header mode.
|
|
50
|
+
roles:
|
|
51
|
+
type: array
|
|
52
|
+
items:
|
|
53
|
+
type: string
|
|
54
|
+
description: Roles claimed at request time (from JWT or DNA_DEV_ROLES). Snapshot
|
|
55
|
+
— does NOT reflect later role revocations.
|
|
56
|
+
operation:
|
|
57
|
+
type: string
|
|
58
|
+
description: HTTP method + path template, e.g. 'PUT /scopes/{scope}/docs/Agent/{name}'
|
|
59
|
+
or 'POST /assessments/{name}/run'.
|
|
60
|
+
target_kind:
|
|
61
|
+
type: string
|
|
62
|
+
description: Kind of doc affected (when applicable). Null for non-doc ops like
|
|
63
|
+
POST /sync/replicate.
|
|
64
|
+
target_name:
|
|
65
|
+
type: string
|
|
66
|
+
description: Name of doc affected, when applicable.
|
|
67
|
+
target_scope:
|
|
68
|
+
type: string
|
|
69
|
+
description: Scope of doc affected, when applicable.
|
|
70
|
+
target_tenant:
|
|
71
|
+
type:
|
|
72
|
+
- string
|
|
73
|
+
- 'null'
|
|
74
|
+
description: Tenant the operation routed to (claims.tenant + overrides resolved).
|
|
75
|
+
Null = base layer write.
|
|
76
|
+
outcome:
|
|
77
|
+
type: string
|
|
78
|
+
enum:
|
|
79
|
+
- success
|
|
80
|
+
- denied
|
|
81
|
+
- error
|
|
82
|
+
description: 'success = decorator + handler ran clean. denied = 403 from require_role.
|
|
83
|
+
error = handler raised (500/422/...).'
|
|
84
|
+
captured_at:
|
|
85
|
+
type: string
|
|
86
|
+
format: date-time
|
|
87
|
+
description: UTC ISO-8601 timestamp.
|
|
88
|
+
request_id:
|
|
89
|
+
type: string
|
|
90
|
+
description: Correlation ID (UUIDv4) — joins logs.
|
|
91
|
+
remote_ip:
|
|
92
|
+
type: string
|
|
93
|
+
description: Best-effort client IP (X-Forwarded-For aware).
|
|
94
|
+
user_agent:
|
|
95
|
+
type: string
|
|
96
|
+
description: HTTP User-Agent header.
|
|
97
|
+
detail:
|
|
98
|
+
type: object
|
|
99
|
+
description: 'Free-form context: which required roles failed, body size, durations,
|
|
100
|
+
errors. Defensive about PII — don''t include request bodies verbatim.'
|
|
101
|
+
# Curated list-endpoint projection. The extinct Py class declared NO
|
|
102
|
+
# summary() (KindBase whole-spec echo); the TS class returned null. Both
|
|
103
|
+
# are replaced by this curated projection (intentional delta — precedent
|
|
104
|
+
# VoiceEpisode/SynthesizerState in F3 lote-3). The manifest does NOT carry
|
|
105
|
+
# summary, so this choice is manifest-neutral.
|
|
106
|
+
summary:
|
|
107
|
+
actor: ''
|
|
108
|
+
operation: ''
|
|
109
|
+
outcome: ''
|
|
110
|
+
target_kind: ''
|
|
111
|
+
captured_at: ''
|
|
112
|
+
# P2L2 — AuditLog is Govern-mode (compliance + tenant-admin only). Sidebar
|
|
113
|
+
# entry visible to those roles. Read-only — no create/edit exposed in UI
|
|
114
|
+
# (writes happen via emit_audit() from gated handlers).
|
|
115
|
+
ui:
|
|
116
|
+
mode: govern
|
|
117
|
+
label:
|
|
118
|
+
en: Audit Log
|
|
119
|
+
pt-BR: Trilha de Auditoria
|
|
120
|
+
icon: 🔒
|
|
121
|
+
description:
|
|
122
|
+
en: Forensic trail of every role-gated mutation.
|
|
123
|
+
pt-BR: Trilha forense de toda mutação com role.
|
|
124
|
+
breadcrumb:
|
|
125
|
+
- Govern
|
|
126
|
+
- Audit Log
|
|
127
|
+
routes:
|
|
128
|
+
list: docs/AuditLog
|
|
129
|
+
detail: docs/AuditLog/:name
|
|
130
|
+
permissions:
|
|
131
|
+
list:
|
|
132
|
+
- compliance
|
|
133
|
+
- tenant-admin
|
|
134
|
+
detail:
|
|
135
|
+
- compliance
|
|
136
|
+
- tenant-admin
|
|
137
|
+
in_sidebar: true
|
|
138
|
+
display_order: 40
|
|
139
|
+
graph_style:
|
|
140
|
+
fill: '#475569'
|
|
141
|
+
stroke: '#334155'
|
|
142
|
+
text_color: '#fff'
|
|
143
|
+
ascii_icon: 🔍
|
|
144
|
+
display_label: Audit Log
|
|
145
|
+
docs: Immutable record of a role-gated HTTP endpoint invocation. Captures actor,
|
|
146
|
+
roles claimed, operation, target Kind/name, scope/tenant, request_id, outcome,
|
|
147
|
+
and timestamp. Used by compliance auditors + admins to answer 'who did what when'
|
|
148
|
+
without parsing application logs.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AuditExtension — RBAC audit-trail Kinds.
|
|
3
|
+
*
|
|
4
|
+
* 1:1 parity with Python dna.extensions.audit
|
|
5
|
+
* (s-port-missing-ts-extensions). Registers:
|
|
6
|
+
* - AuditLog (audit-auditlog) — immutable record of a role-gated endpoint
|
|
7
|
+
* call. MIGRATED to a descriptor in expr batch A (plan
|
|
8
|
+
* 2026-06-11-descriptor-expressiveness): the twin AuditLogKind classes
|
|
9
|
+
* (Py+TS) were DELETED — kinds/audit-log.kind.yaml is the single source,
|
|
10
|
+
* registered via the loadDescriptors loop in register(). The descriptor
|
|
11
|
+
* carries the D2 `ui:` block (now expressible Py↔TS), which the old TS
|
|
12
|
+
* class intentionally omitted — so the TS runtime now exposes the same
|
|
13
|
+
* Studio sidebar metadata the Python side always had.
|
|
14
|
+
* - UserRoleAssignment (audit-userroleassignment) — user→roles within a
|
|
15
|
+
* tenant (still a class).
|
|
16
|
+
*
|
|
17
|
+
* UserRoleAssignment is TENANTED (the KindBase default) with no reader/writer
|
|
18
|
+
* (plain YAML).
|
|
19
|
+
*/
|
|
20
|
+
import type { ExtensionHost, Extension } from "../kernel/protocols.js";
|
|
21
|
+
export declare class AuditExtension implements Extension {
|
|
22
|
+
readonly name = "audit";
|
|
23
|
+
readonly version = "1.0.0";
|
|
24
|
+
register(kernel: ExtensionHost): void;
|
|
25
|
+
}
|