agentboot 0.2.0 → 0.3.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.
@@ -12,7 +12,12 @@ import path from "node:path";
12
12
  export interface AgentBootConfig {
13
13
  org: string;
14
14
  orgDisplayName?: string;
15
+
16
+ // AB-88: N-tier scope model — nodes replace flat groups/teams
17
+ // Legacy groups/teams still supported for backward compat; converted to nodes internally.
15
18
  groups?: Record<string, GroupConfig>;
19
+ nodes?: Record<string, ScopeNode>;
20
+
16
21
  personas?: {
17
22
  enabled?: string[];
18
23
  customDir?: string;
@@ -24,6 +29,10 @@ export interface AgentBootConfig {
24
29
  instructions?: {
25
30
  enabled?: string[];
26
31
  };
32
+
33
+ // AB-53: Domain layers
34
+ domains?: DomainReference[];
35
+
27
36
  output?: {
28
37
  distPath?: string;
29
38
  provenanceHeaders?: boolean;
@@ -46,6 +55,16 @@ export interface AgentBootConfig {
46
55
  permissions?: { allow?: string[]; deny?: string[] };
47
56
  mcpServers?: Record<string, unknown>;
48
57
  };
58
+
59
+ // AB-62: Three-tier privacy model
60
+ privacy?: PrivacyConfig;
61
+
62
+ // AB-65: Telemetry configuration
63
+ telemetry?: TelemetryConfig;
64
+
65
+ // AB-61: Managed settings (HARD guardrails for MDM)
66
+ managed?: ManagedConfig;
67
+
49
68
  validation?: {
50
69
  secretPatterns?: string[];
51
70
  strictMode?: boolean;
@@ -56,15 +75,238 @@ export interface GroupConfig {
56
75
  teams?: string[];
57
76
  }
58
77
 
78
+ // ---------------------------------------------------------------------------
79
+ // AB-88: N-tier scope model
80
+ // ---------------------------------------------------------------------------
81
+
82
+ /** A node in the scope tree. Replaces flat groups/teams with arbitrary depth. */
83
+ export interface ScopeNode {
84
+ /** Display name for this scope level */
85
+ displayName?: string;
86
+ /** Child nodes (arbitrary depth) */
87
+ children?: Record<string, ScopeNode>;
88
+ /** Personas enabled at this scope (additive to parent) */
89
+ personas?: string[];
90
+ /** Additional traits enabled at this scope */
91
+ traits?: string[];
92
+ /** Override config values at this scope */
93
+ config?: Record<string, unknown>;
94
+ }
95
+
96
+ /**
97
+ * Flatten a nodes tree into scope paths for compilation.
98
+ * Returns array of { path: "platform/api", node } tuples.
99
+ */
100
+ export function flattenNodes(
101
+ nodes: Record<string, ScopeNode>,
102
+ prefix = ""
103
+ ): Array<{ path: string; node: ScopeNode }> {
104
+ const result: Array<{ path: string; node: ScopeNode }> = [];
105
+ for (const [name, node] of Object.entries(nodes)) {
106
+ const nodePath = prefix ? `${prefix}/${name}` : name;
107
+ result.push({ path: nodePath, node });
108
+ if (node.children) {
109
+ result.push(...flattenNodes(node.children, nodePath));
110
+ }
111
+ }
112
+ return result;
113
+ }
114
+
115
+ /**
116
+ * Convert legacy groups/teams config to N-tier nodes.
117
+ * Groups become depth-1 nodes; teams become depth-2 children.
118
+ */
119
+ export function groupsToNodes(groups: Record<string, GroupConfig>): Record<string, ScopeNode> {
120
+ const nodes: Record<string, ScopeNode> = {};
121
+ for (const [groupName, group] of Object.entries(groups)) {
122
+ const children: Record<string, ScopeNode> = {};
123
+ for (const team of group.teams ?? []) {
124
+ children[team] = {};
125
+ }
126
+ const node: ScopeNode = {};
127
+ if (Object.keys(children).length > 0) {
128
+ node.children = children;
129
+ }
130
+ nodes[groupName] = node;
131
+ }
132
+ return nodes;
133
+ }
134
+
135
+ // ---------------------------------------------------------------------------
136
+ // AB-53: Domain layer references
137
+ // ---------------------------------------------------------------------------
138
+
139
+ export type DomainReference = string | { name: string; version?: string; path?: string };
140
+
141
+ export interface DomainManifest {
142
+ name: string;
143
+ version: string;
144
+ description?: string;
145
+ traits?: string[];
146
+ personas?: string[];
147
+ instructions?: string[];
148
+ requires_core_version?: string;
149
+ }
150
+
151
+ // ---------------------------------------------------------------------------
152
+ // AB-62: Privacy model
153
+ // ---------------------------------------------------------------------------
154
+
155
+ export interface PrivacyConfig {
156
+ /** Three-tier model: private (raw prompts never leave machine),
157
+ * privileged (LLM analysis via API, developer approves),
158
+ * organizational (anonymized metrics only). */
159
+ tier?: "private" | "privileged" | "organizational";
160
+ /** Raw prompts are NEVER collected. This is a design invariant. */
161
+ rawPrompts?: false;
162
+ /** Escalation exception for genuinely harmful content (category flag only). */
163
+ escalationEnabled?: boolean;
164
+ }
165
+
166
+ // ---------------------------------------------------------------------------
167
+ // AB-65: Telemetry config
168
+ // ---------------------------------------------------------------------------
169
+
170
+ export interface TelemetryConfig {
171
+ enabled?: boolean;
172
+ /** How to identify developers in telemetry.
173
+ * false = no developer ID, "hashed" = SHA-256 of email, "email" = raw email. */
174
+ includeDevId?: false | "hashed" | "email";
175
+ /** Path to NDJSON log file. Default: ~/.agentboot/telemetry.ndjson */
176
+ logPath?: string;
177
+ /** Never include raw prompt content in telemetry. Design invariant. */
178
+ includeContent?: false;
179
+ }
180
+
181
+ // ---------------------------------------------------------------------------
182
+ // AB-61: Managed settings (MDM distribution)
183
+ // ---------------------------------------------------------------------------
184
+
185
+ export interface ManagedConfig {
186
+ /** Enable managed settings artifact generation */
187
+ enabled?: boolean;
188
+ /** MDM platform target */
189
+ platform?: "jamf" | "intune" | "jumpcloud" | "kandji" | "other";
190
+ /** Custom output path for managed settings */
191
+ outputPath?: string;
192
+ /** HARD guardrails to enforce via managed settings */
193
+ guardrails?: {
194
+ /** Force-install specific plugins */
195
+ forcePlugins?: string[];
196
+ /** Deny these tool patterns */
197
+ denyTools?: string[];
198
+ /** Require audit logging */
199
+ requireAuditLog?: boolean;
200
+ };
201
+ }
202
+
59
203
  export interface PersonaConfig {
60
204
  name: string;
61
205
  description: string;
62
206
  invocation?: string;
63
207
  model?: string;
64
208
  permissionMode?: string;
209
+ maxTurns?: number;
210
+ disallowedTools?: string[];
211
+ tools?: string[];
212
+ effort?: "low" | "medium" | "high" | "max";
213
+ autonomy?: "advisory" | "auto-approve" | "autonomous";
214
+ skills?: string[];
215
+ memory?: "user" | "project" | "local" | null;
216
+ background?: boolean;
217
+ isolation?: "none" | "worktree";
218
+ tokenBudget?: number;
65
219
  traits?: string[];
66
220
  groups?: Record<string, { traits?: string[] }>;
67
221
  teams?: Record<string, { traits?: string[] }>;
222
+ /** Per-persona hook configuration */
223
+ hooks?: Record<string, unknown>;
224
+ /** Per-persona MCP servers */
225
+ mcpServers?: Record<string, unknown>;
226
+ }
227
+
228
+ // ---------------------------------------------------------------------------
229
+ // AB-64: Telemetry event schema
230
+ // ---------------------------------------------------------------------------
231
+
232
+ export interface TelemetryEvent {
233
+ event: "persona_invocation" | "persona_error" | "hook_execution" | "session_summary";
234
+ persona_id: string;
235
+ persona_version?: string;
236
+ model?: string;
237
+ scope?: string;
238
+ input_tokens?: number;
239
+ output_tokens?: number;
240
+ thinking_tokens?: number;
241
+ tool_calls?: number;
242
+ duration_ms?: number;
243
+ cost_usd?: number;
244
+ findings_count?: {
245
+ CRITICAL?: number;
246
+ ERROR?: number;
247
+ WARN?: number;
248
+ INFO?: number;
249
+ };
250
+ suggestions?: number;
251
+ timestamp: string;
252
+ session_id?: string;
253
+ dev_id?: string;
254
+ }
255
+
256
+ // ---------------------------------------------------------------------------
257
+ // AB-57: Plugin manifest
258
+ // ---------------------------------------------------------------------------
259
+
260
+ export interface PluginManifest {
261
+ name: string;
262
+ version: string;
263
+ description: string;
264
+ author: string;
265
+ license: string;
266
+ agentboot_version: string;
267
+ personas: Array<{
268
+ id: string;
269
+ name: string;
270
+ description: string;
271
+ model?: string | undefined;
272
+ agent_path: string;
273
+ skill_path: string;
274
+ }>;
275
+ traits: Array<{
276
+ id: string;
277
+ path: string;
278
+ }>;
279
+ hooks?: Array<{
280
+ event: string;
281
+ path: string;
282
+ }> | undefined;
283
+ rules?: Array<{
284
+ path: string;
285
+ description?: string | undefined;
286
+ }> | undefined;
287
+ }
288
+
289
+ // ---------------------------------------------------------------------------
290
+ // AB-58: Marketplace manifest
291
+ // ---------------------------------------------------------------------------
292
+
293
+ export interface MarketplaceManifest {
294
+ $schema?: string;
295
+ name: string;
296
+ description: string;
297
+ maintainer: string;
298
+ url?: string;
299
+ entries: MarketplaceEntry[];
300
+ }
301
+
302
+ export interface MarketplaceEntry {
303
+ type: "plugin" | "trait" | "domain" | "persona";
304
+ name: string;
305
+ version: string;
306
+ description: string;
307
+ published_at: string;
308
+ sha256?: string;
309
+ path: string;
68
310
  }
69
311
 
70
312
  // ---------------------------------------------------------------------------
@@ -136,7 +378,7 @@ export function loadConfig(configPath: string): AgentBootConfig {
136
378
  const parsed = JSON.parse(stripped);
137
379
 
138
380
  // Minimal runtime validation for critical fields
139
- if (typeof parsed !== "object" || parsed === null) {
381
+ if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
140
382
  throw new Error("Config must be a JSON object");
141
383
  }
142
384
  if (typeof parsed.org !== "string" || parsed.org.length === 0) {
@@ -8,7 +8,9 @@
8
8
  // Frontmatter parsing
9
9
  // ---------------------------------------------------------------------------
10
10
 
11
- const FRONTMATTER_RE = /^---\n([\s\S]+?)\n---/;
11
+ // Matches YAML frontmatter blocks. Uses [\s\S]*? (zero or more) so that
12
+ // empty frontmatter (---\n---) returns an empty Map rather than null.
13
+ const FRONTMATTER_RE = /^---\n([\s\S]*?)\n---/;
12
14
 
13
15
  export function parseFrontmatter(content: string): Map<string, string> | null {
14
16
  const match = FRONTMATTER_RE.exec(content);
@@ -0,0 +1,117 @@
1
+ import {themes as prismThemes} from 'prism-react-renderer';
2
+ import type {Config} from '@docusaurus/types';
3
+ import type * as Preset from '@docusaurus/preset-classic';
4
+
5
+ const config: Config = {
6
+ title: 'AgentBoot',
7
+ tagline: 'Convention over configuration for agentic development teams',
8
+ favicon: 'img/favicon.ico',
9
+
10
+ future: {
11
+ v4: true,
12
+ },
13
+
14
+ url: 'https://agentboot.dev',
15
+ baseUrl: '/',
16
+
17
+ organizationName: 'agentboot-dev',
18
+ projectName: 'agentboot',
19
+ deploymentBranch: 'gh-pages',
20
+ trailingSlash: false,
21
+
22
+ onBrokenLinks: 'warn',
23
+
24
+ i18n: {
25
+ defaultLocale: 'en',
26
+ locales: ['en'],
27
+ },
28
+
29
+ presets: [
30
+ [
31
+ 'classic',
32
+ {
33
+ docs: {
34
+ path: '../docs',
35
+ sidebarPath: './sidebars.ts',
36
+ editUrl: 'https://github.com/agentboot-dev/agentboot/tree/main/',
37
+ // Exclude internal docs from the public site
38
+ exclude: ['internal/**'],
39
+ },
40
+ blog: false, // Disable blog for now
41
+ theme: {
42
+ customCss: './src/css/custom.css',
43
+ },
44
+ } satisfies Preset.Options,
45
+ ],
46
+ ],
47
+
48
+ themeConfig: {
49
+ colorMode: {
50
+ defaultMode: 'light',
51
+ respectPrefersColorScheme: true,
52
+ },
53
+ navbar: {
54
+ title: 'AgentBoot',
55
+ items: [
56
+ {
57
+ type: 'docSidebar',
58
+ sidebarId: 'docsSidebar',
59
+ position: 'left',
60
+ label: 'Docs',
61
+ },
62
+ {
63
+ to: '/docs/roadmap',
64
+ label: 'Roadmap',
65
+ position: 'left',
66
+ },
67
+ {
68
+ href: 'https://github.com/agentboot-dev/agentboot',
69
+ label: 'GitHub',
70
+ position: 'right',
71
+ },
72
+ ],
73
+ },
74
+ footer: {
75
+ style: 'dark',
76
+ links: [
77
+ {
78
+ title: 'Documentation',
79
+ items: [
80
+ { label: 'Getting Started', to: '/docs/getting-started' },
81
+ { label: 'Core Concepts', to: '/docs/concepts' },
82
+ { label: 'CLI Reference', to: '/docs/cli-reference' },
83
+ ],
84
+ },
85
+ {
86
+ title: 'Guides',
87
+ items: [
88
+ { label: 'Extending AgentBoot', to: '/docs/extending' },
89
+ { label: 'Prompt Authoring', to: '/docs/prompt-guide' },
90
+ { label: 'Privacy & Safety', to: '/docs/privacy' },
91
+ ],
92
+ },
93
+ {
94
+ title: 'Community',
95
+ items: [
96
+ {
97
+ label: 'GitHub',
98
+ href: 'https://github.com/agentboot-dev/agentboot',
99
+ },
100
+ {
101
+ label: 'Issues',
102
+ href: 'https://github.com/agentboot-dev/agentboot/issues',
103
+ },
104
+ ],
105
+ },
106
+ ],
107
+ copyright: `Copyright ${new Date().getFullYear()} AgentBoot Contributors. Apache-2.0 License.`,
108
+ },
109
+ prism: {
110
+ theme: prismThemes.github,
111
+ darkTheme: prismThemes.dracula,
112
+ additionalLanguages: ['bash', 'json', 'yaml', 'toml'],
113
+ },
114
+ } satisfies Preset.ThemeConfig,
115
+ };
116
+
117
+ export default config;