agentboot 0.1.0 → 0.2.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/README.md +8 -7
- package/agentboot.config.json +4 -1
- package/package.json +2 -2
- package/scripts/cli.ts +42 -14
- package/scripts/compile.ts +30 -7
- package/scripts/dev-sync.ts +1 -1
- package/scripts/lib/config.ts +17 -1
- package/scripts/validate.ts +12 -7
- package/.github/ISSUE_TEMPLATE/persona-request.md +0 -62
- package/.github/ISSUE_TEMPLATE/quality-feedback.md +0 -67
- package/.github/workflows/cla.yml +0 -25
- package/.github/workflows/validate.yml +0 -49
- package/.idea/agentboot.iml +0 -9
- package/.idea/misc.xml +0 -6
- package/.idea/modules.xml +0 -8
- package/.idea/vcs.xml +0 -6
- package/CLAUDE.md +0 -230
- package/CONTRIBUTING.md +0 -168
- package/PERSONAS.md +0 -156
- package/core/instructions/baseline.instructions.md +0 -133
- package/core/instructions/security.instructions.md +0 -186
- package/core/personas/code-reviewer/SKILL.md +0 -175
- package/core/personas/security-reviewer/SKILL.md +0 -233
- package/core/personas/test-data-expert/SKILL.md +0 -234
- package/core/personas/test-generator/SKILL.md +0 -262
- package/core/traits/audit-trail.md +0 -182
- package/core/traits/confidence-signaling.md +0 -172
- package/core/traits/critical-thinking.md +0 -129
- package/core/traits/schema-awareness.md +0 -132
- package/core/traits/source-citation.md +0 -174
- package/core/traits/structured-output.md +0 -199
- package/docs/ci-cd-automation.md +0 -548
- package/docs/claude-code-reference/README.md +0 -21
- package/docs/claude-code-reference/agentboot-coverage.md +0 -484
- package/docs/claude-code-reference/feature-inventory.md +0 -906
- package/docs/cli-commands-audit.md +0 -112
- package/docs/cli-design.md +0 -924
- package/docs/concepts.md +0 -1117
- package/docs/config-schema-audit.md +0 -121
- package/docs/configuration.md +0 -645
- package/docs/delivery-methods.md +0 -758
- package/docs/developer-onboarding.md +0 -342
- package/docs/extending.md +0 -448
- package/docs/getting-started.md +0 -298
- package/docs/knowledge-layer.md +0 -464
- package/docs/marketplace.md +0 -822
- package/docs/org-connection.md +0 -570
- package/docs/plans/architecture.md +0 -2429
- package/docs/plans/design.md +0 -2018
- package/docs/plans/prd.md +0 -1862
- package/docs/plans/stack-rank.md +0 -261
- package/docs/plans/technical-spec.md +0 -2755
- package/docs/privacy-and-safety.md +0 -807
- package/docs/prompt-optimization.md +0 -1071
- package/docs/test-plan.md +0 -972
- package/docs/third-party-ecosystem.md +0 -496
- package/domains/compliance-template/README.md +0 -173
- package/domains/compliance-template/traits/compliance-aware.md +0 -228
- package/examples/enterprise/agentboot.config.json +0 -184
- package/examples/minimal/agentboot.config.json +0 -46
- package/tests/REGRESSION-PLAN.md +0 -705
- package/tests/TEST-PLAN.md +0 -111
- package/tests/cli.test.ts +0 -705
- package/tests/pipeline.test.ts +0 -608
- package/tests/validate.test.ts +0 -278
- package/tsconfig.json +0 -62
package/README.md
CHANGED
|
@@ -29,19 +29,20 @@ The output works without AgentBoot installed. Any platform that reads Markdown c
|
|
|
29
29
|
## Quickstart
|
|
30
30
|
|
|
31
31
|
```bash
|
|
32
|
-
# Install
|
|
33
|
-
|
|
32
|
+
# Install (pick one)
|
|
33
|
+
brew tap agentboot-dev/agentboot && brew install agentboot
|
|
34
|
+
npm install -g agentboot
|
|
34
35
|
|
|
35
36
|
# Set up a new personas repo
|
|
36
|
-
|
|
37
|
+
agentboot setup
|
|
37
38
|
|
|
38
39
|
# Configure your org
|
|
39
40
|
# Edit agentboot.config.json with your org name, groups, and teams
|
|
40
41
|
|
|
41
42
|
# Build and sync
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
43
|
+
agentboot build
|
|
44
|
+
agentboot sync --dry-run # preview first
|
|
45
|
+
agentboot sync # deploy to repos
|
|
45
46
|
```
|
|
46
47
|
|
|
47
48
|
Your repos now have:
|
|
@@ -123,7 +124,7 @@ Everything is driven by `agentboot.config.json`:
|
|
|
123
124
|
agentboot build # Compile personas from traits
|
|
124
125
|
agentboot validate # Pre-build validation checks
|
|
125
126
|
agentboot sync # Distribute to target repos
|
|
126
|
-
agentboot
|
|
127
|
+
agentboot dev-build # clean → validate → build → dev-sync pipeline
|
|
127
128
|
agentboot setup # Scaffold a new personas repo
|
|
128
129
|
agentboot add <type> # Create a new persona, trait, or gotcha
|
|
129
130
|
agentboot doctor # Diagnose configuration issues
|
package/agentboot.config.json
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
// Convention over configuration: every field has a sensible default.
|
|
6
6
|
// You only need to specify what's different about your organization.
|
|
7
7
|
//
|
|
8
|
-
// Run `npm run
|
|
8
|
+
// Run `npm run dev-build` after editing to validate, compile, and sync.
|
|
9
9
|
|
|
10
10
|
// ---------------------------------------------------------------------------
|
|
11
11
|
// Organization identity
|
|
@@ -184,6 +184,9 @@
|
|
|
184
184
|
// Claude Code-specific output configuration (only applies to "claude" platform).
|
|
185
185
|
// ---------------------------------------------------------------------------
|
|
186
186
|
|
|
187
|
+
// Claude Code-specific output (experimental — Phase 2).
|
|
188
|
+
// Generates settings.json and .mcp.json when uncommented.
|
|
189
|
+
// Requires Claude Code to support these features.
|
|
187
190
|
// "claude": {
|
|
188
191
|
// "hooks": {},
|
|
189
192
|
// "permissions": { "allow": [], "deny": [] },
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agentboot",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Convention over configuration for agentic development teams. The Spring Boot of Claude Code governance.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "Mike Saavedra <mike@agentboot.dev>",
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
"build": "tsx scripts/compile.ts",
|
|
45
45
|
"validate": "tsx scripts/validate.ts",
|
|
46
46
|
"sync": "tsx scripts/sync.ts",
|
|
47
|
-
"
|
|
47
|
+
"dev-build": "npm run clean && npm run validate && npm run build && npm run dev-sync",
|
|
48
48
|
"test": "vitest run",
|
|
49
49
|
"test:watch": "vitest",
|
|
50
50
|
"typecheck": "tsc --noEmit",
|
package/scripts/cli.ts
CHANGED
|
@@ -140,7 +140,7 @@ program
|
|
|
140
140
|
program
|
|
141
141
|
.command("validate")
|
|
142
142
|
.description("Run pre-build validation checks")
|
|
143
|
-
.option("--strict", "treat warnings as errors")
|
|
143
|
+
.option("-s, --strict", "treat warnings as errors")
|
|
144
144
|
.action((opts, cmd) => {
|
|
145
145
|
const globalOpts = cmd.optsWithGlobals();
|
|
146
146
|
const args = collectGlobalArgs({ config: globalOpts.config });
|
|
@@ -163,7 +163,7 @@ program
|
|
|
163
163
|
.command("sync")
|
|
164
164
|
.description("Distribute compiled output to target repositories")
|
|
165
165
|
.option("--repos-file <path>", "path to repos.json")
|
|
166
|
-
.option("--dry-run", "preview changes without writing")
|
|
166
|
+
.option("-d, --dry-run", "preview changes without writing")
|
|
167
167
|
.action((opts, cmd) => {
|
|
168
168
|
const globalOpts = cmd.optsWithGlobals();
|
|
169
169
|
const args = collectGlobalArgs({ config: globalOpts.config });
|
|
@@ -200,10 +200,10 @@ program
|
|
|
200
200
|
});
|
|
201
201
|
});
|
|
202
202
|
|
|
203
|
-
// ----
|
|
203
|
+
// ---- dev-build -----------------------------------------------------------
|
|
204
204
|
|
|
205
205
|
program
|
|
206
|
-
.command("
|
|
206
|
+
.command("dev-build")
|
|
207
207
|
.description("Run clean → validate → build → dev-sync pipeline")
|
|
208
208
|
.action((_opts, cmd) => {
|
|
209
209
|
const globalOpts = cmd.optsWithGlobals();
|
|
@@ -224,6 +224,10 @@ program
|
|
|
224
224
|
["tsx", path.join(SCRIPTS_DIR, "validate.ts"), ...baseArgs],
|
|
225
225
|
{ cwd: ROOT, stdio: quiet ? ["inherit", "ignore", "pipe"] : "inherit" },
|
|
226
226
|
);
|
|
227
|
+
if (valResult.error) {
|
|
228
|
+
console.error(`Validation failed to start: ${valResult.error.message}`);
|
|
229
|
+
process.exit(1);
|
|
230
|
+
}
|
|
227
231
|
if (valResult.status !== 0) {
|
|
228
232
|
console.error("Validation failed.");
|
|
229
233
|
process.exit(valResult.status ?? 1);
|
|
@@ -236,6 +240,10 @@ program
|
|
|
236
240
|
["tsx", path.join(SCRIPTS_DIR, "compile.ts"), ...baseArgs],
|
|
237
241
|
{ cwd: ROOT, stdio: quiet ? ["inherit", "ignore", "pipe"] : "inherit" },
|
|
238
242
|
);
|
|
243
|
+
if (buildResult.error) {
|
|
244
|
+
console.error(`Build failed to start: ${buildResult.error.message}`);
|
|
245
|
+
process.exit(1);
|
|
246
|
+
}
|
|
239
247
|
if (buildResult.status !== 0) {
|
|
240
248
|
console.error("Build failed.");
|
|
241
249
|
process.exit(buildResult.status ?? 1);
|
|
@@ -248,12 +256,17 @@ program
|
|
|
248
256
|
["tsx", path.join(SCRIPTS_DIR, "dev-sync.ts"), ...baseArgs],
|
|
249
257
|
{ cwd: ROOT, stdio: quiet ? ["inherit", "ignore", "pipe"] : "inherit" },
|
|
250
258
|
);
|
|
259
|
+
if (syncResult.error) {
|
|
260
|
+
console.error(`Dev-sync failed to start: ${syncResult.error.message}`);
|
|
261
|
+
process.exit(1);
|
|
262
|
+
}
|
|
251
263
|
if (syncResult.status !== 0) {
|
|
252
264
|
console.error("Dev-sync failed.");
|
|
253
265
|
process.exit(syncResult.status ?? 1);
|
|
254
266
|
}
|
|
255
267
|
|
|
256
|
-
if (!quiet) console.log("✓
|
|
268
|
+
if (!quiet) console.log("✓ dev-build complete");
|
|
269
|
+
process.exit(0);
|
|
257
270
|
});
|
|
258
271
|
|
|
259
272
|
// ---- setup (AB-33) --------------------------------------------------------
|
|
@@ -293,7 +306,7 @@ program
|
|
|
293
306
|
}
|
|
294
307
|
} catch { /* no git, use default */ }
|
|
295
308
|
|
|
296
|
-
console.log(chalk.cyan(` Detected org: ${orgName}`));
|
|
309
|
+
console.log(chalk.cyan(` Detected org: ${orgName}`) + chalk.gray(" (edit agentboot.config.json to change)"));
|
|
297
310
|
|
|
298
311
|
// Scaffold config
|
|
299
312
|
const configContent = JSON.stringify({
|
|
@@ -351,8 +364,8 @@ program
|
|
|
351
364
|
.argument("<name>", "name for the new item (lowercase-with-hyphens)")
|
|
352
365
|
.action((type: string, name: string) => {
|
|
353
366
|
// Validate name format
|
|
354
|
-
if (!/^[a-z][a-z0-9-]
|
|
355
|
-
console.error(chalk.red(`Name must be lowercase alphanumeric with hyphens: got '${name}'`));
|
|
367
|
+
if (!/^[a-z][a-z0-9-]{0,63}$/.test(name)) {
|
|
368
|
+
console.error(chalk.red(`Name must be 1-64 lowercase alphanumeric chars with hyphens: got '${name}'`));
|
|
356
369
|
process.exit(1);
|
|
357
370
|
}
|
|
358
371
|
|
|
@@ -636,7 +649,13 @@ program
|
|
|
636
649
|
process.exit(1);
|
|
637
650
|
}
|
|
638
651
|
|
|
639
|
-
|
|
652
|
+
let config;
|
|
653
|
+
try {
|
|
654
|
+
config = loadConfig(configPath);
|
|
655
|
+
} catch (e: unknown) {
|
|
656
|
+
console.error(chalk.red(`Failed to parse config: ${e instanceof Error ? e.message : String(e)}`));
|
|
657
|
+
process.exit(1);
|
|
658
|
+
}
|
|
640
659
|
const pkgPath = path.join(ROOT, "package.json");
|
|
641
660
|
const version = fs.existsSync(pkgPath) ? JSON.parse(fs.readFileSync(pkgPath, "utf-8")).version : "unknown";
|
|
642
661
|
|
|
@@ -734,7 +753,13 @@ program
|
|
|
734
753
|
process.exit(1);
|
|
735
754
|
}
|
|
736
755
|
|
|
737
|
-
|
|
756
|
+
let config;
|
|
757
|
+
try {
|
|
758
|
+
config = loadConfig(configPath);
|
|
759
|
+
} catch (e: unknown) {
|
|
760
|
+
console.error(chalk.red(`Failed to parse config: ${e instanceof Error ? e.message : String(e)}`));
|
|
761
|
+
process.exit(1);
|
|
762
|
+
}
|
|
738
763
|
const isJson = opts.format === "json";
|
|
739
764
|
if (!isJson) console.log(chalk.bold("\nAgentBoot — lint\n"));
|
|
740
765
|
|
|
@@ -752,6 +777,7 @@ program
|
|
|
752
777
|
|
|
753
778
|
const personasDir = path.join(cwd, "core", "personas");
|
|
754
779
|
const enabledPersonas = config.personas?.enabled ?? [];
|
|
780
|
+
const enabledTraits = config.traits?.enabled ?? [];
|
|
755
781
|
const tokenBudget = config.output?.tokenBudget?.warnAt ?? 8000;
|
|
756
782
|
|
|
757
783
|
// Vague language patterns
|
|
@@ -861,7 +887,6 @@ program
|
|
|
861
887
|
|
|
862
888
|
// Check for unused trait
|
|
863
889
|
const traitName = file.replace(/\.md$/, "");
|
|
864
|
-
const enabledTraits = config.traits?.enabled ?? [];
|
|
865
890
|
if (enabledTraits.length > 0 && !enabledTraits.includes(traitName)) {
|
|
866
891
|
findings.push({ rule: "unused-trait", severity: "info", file: `core/traits/${file}`, message: `Trait not in traits.enabled list` });
|
|
867
892
|
}
|
|
@@ -921,7 +946,7 @@ program
|
|
|
921
946
|
.command("uninstall")
|
|
922
947
|
.description("Remove AgentBoot managed files from a repository")
|
|
923
948
|
.option("--repo <path>", "target repository path")
|
|
924
|
-
.option("--dry-run", "preview what would be removed")
|
|
949
|
+
.option("-d, --dry-run", "preview what would be removed")
|
|
925
950
|
.action((opts) => {
|
|
926
951
|
const targetRepo = opts.repo ? path.resolve(opts.repo) : process.cwd();
|
|
927
952
|
const dryRun = opts.dryRun ?? false;
|
|
@@ -1023,9 +1048,12 @@ program
|
|
|
1023
1048
|
.description("View configuration (read-only)")
|
|
1024
1049
|
.argument("[key]", "config key (e.g., personas.enabled)")
|
|
1025
1050
|
.argument("[value]", "not yet supported")
|
|
1026
|
-
.action((key
|
|
1051
|
+
.action((key: string | undefined, value: string | undefined, _opts, cmd) => {
|
|
1052
|
+
const globalOpts = cmd.optsWithGlobals();
|
|
1027
1053
|
const cwd = process.cwd();
|
|
1028
|
-
const configPath =
|
|
1054
|
+
const configPath = globalOpts.config
|
|
1055
|
+
? path.resolve(globalOpts.config)
|
|
1056
|
+
: path.join(cwd, "agentboot.config.json");
|
|
1029
1057
|
|
|
1030
1058
|
if (!fs.existsSync(configPath)) {
|
|
1031
1059
|
console.error(chalk.red("No agentboot.config.json found."));
|
package/scripts/compile.ts
CHANGED
|
@@ -236,8 +236,12 @@ function buildClaudeOutput(
|
|
|
236
236
|
const invocation = personaConfig?.invocation ?? `/${personaName}`;
|
|
237
237
|
const skillName = invocation.replace(/^\//, "");
|
|
238
238
|
const description = personaConfig?.description ?? personaName;
|
|
239
|
-
// Escape
|
|
240
|
-
const safeDescription = description
|
|
239
|
+
// Escape for YAML double-quoted strings
|
|
240
|
+
const safeDescription = description
|
|
241
|
+
.replace(/\\/g, "\\\\")
|
|
242
|
+
.replace(/"/g, '\\"')
|
|
243
|
+
.replace(/\n/g, " ")
|
|
244
|
+
.replace(/---/g, "\\-\\-\\-");
|
|
241
245
|
|
|
242
246
|
// AB-18: CC skill frontmatter with context:fork → delegates to agent
|
|
243
247
|
const frontmatterLines: string[] = [
|
|
@@ -363,9 +367,12 @@ function compilePersona(
|
|
|
363
367
|
const model = personaConfig?.model; // undefined = omit from frontmatter
|
|
364
368
|
const permMode = personaConfig?.permissionMode;
|
|
365
369
|
const agentDescription = personaConfig?.description ?? personaName;
|
|
366
|
-
// Escape
|
|
367
|
-
|
|
368
|
-
|
|
370
|
+
// Escape for YAML double-quoted strings: backslashes, quotes, newlines, and --- sequences.
|
|
371
|
+
const safeDescription = agentDescription
|
|
372
|
+
.replace(/\\/g, "\\\\") // backslashes first (before other escapes add more)
|
|
373
|
+
.replace(/"/g, '\\"') // double quotes
|
|
374
|
+
.replace(/\n/g, " ") // newlines → spaces
|
|
375
|
+
.replace(/---/g, "\\-\\-\\-"); // prevent YAML document markers
|
|
369
376
|
const withoutFrontmatter = composed.replace(/^---\n[\s\S]*?\n---\n*/, "");
|
|
370
377
|
const agentFrontmatter: string[] = [
|
|
371
378
|
"---",
|
|
@@ -651,7 +658,23 @@ function generateSettingsJson(
|
|
|
651
658
|
}
|
|
652
659
|
}
|
|
653
660
|
|
|
654
|
-
|
|
661
|
+
// Security: hooks execute shell commands in target repos — warn prominently
|
|
662
|
+
if (hooks) {
|
|
663
|
+
log(chalk.red(" ⚠ CAUTION: settings.json contains hooks that execute shell commands in target repos."));
|
|
664
|
+
log(chalk.red(" Review claude.hooks in agentboot.config.json carefully before syncing."));
|
|
665
|
+
// Validate hook event names against known CC events
|
|
666
|
+
const validEvents = [
|
|
667
|
+
"PreToolUse", "PostToolUse", "Notification", "Stop",
|
|
668
|
+
"SubagentStop", "SubagentStart",
|
|
669
|
+
];
|
|
670
|
+
for (const key of Object.keys(hooks)) {
|
|
671
|
+
if (!validEvents.includes(key)) {
|
|
672
|
+
log(chalk.yellow(` ⚠ Unknown hook event: "${key}" — may not be recognized by Claude Code`));
|
|
673
|
+
}
|
|
674
|
+
}
|
|
675
|
+
} else {
|
|
676
|
+
log(chalk.yellow(" ⚠ Generating settings.json with permissions — these will be synced to all target repos"));
|
|
677
|
+
}
|
|
655
678
|
|
|
656
679
|
const settings: Record<string, unknown> = {};
|
|
657
680
|
if (hooks) settings.hooks = hooks;
|
|
@@ -755,7 +778,7 @@ function main(): void {
|
|
|
755
778
|
}
|
|
756
779
|
|
|
757
780
|
if (config.personas?.customDir) {
|
|
758
|
-
const extendDir = path.resolve(configDir, config.personas.
|
|
781
|
+
const extendDir = path.resolve(configDir, config.personas.customDir);
|
|
759
782
|
if (fs.existsSync(extendDir)) {
|
|
760
783
|
for (const entry of fs.readdirSync(extendDir)) {
|
|
761
784
|
const dir = path.join(extendDir, entry);
|
package/scripts/dev-sync.ts
CHANGED
package/scripts/lib/config.ts
CHANGED
|
@@ -133,5 +133,21 @@ export function loadConfig(configPath: string): AgentBootConfig {
|
|
|
133
133
|
}
|
|
134
134
|
const raw = fs.readFileSync(configPath, "utf-8");
|
|
135
135
|
const stripped = stripJsoncComments(raw);
|
|
136
|
-
|
|
136
|
+
const parsed = JSON.parse(stripped);
|
|
137
|
+
|
|
138
|
+
// Minimal runtime validation for critical fields
|
|
139
|
+
if (typeof parsed !== "object" || parsed === null) {
|
|
140
|
+
throw new Error("Config must be a JSON object");
|
|
141
|
+
}
|
|
142
|
+
if (typeof parsed.org !== "string" || parsed.org.length === 0) {
|
|
143
|
+
throw new Error('Config requires a non-empty "org" field (string)');
|
|
144
|
+
}
|
|
145
|
+
if (parsed.personas?.enabled !== undefined && !Array.isArray(parsed.personas.enabled)) {
|
|
146
|
+
throw new Error('"personas.enabled" must be an array of strings');
|
|
147
|
+
}
|
|
148
|
+
if (parsed.sync?.targetDir !== undefined && typeof parsed.sync.targetDir !== "string") {
|
|
149
|
+
throw new Error('"sync.targetDir" must be a string');
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
return parsed as AgentBootConfig;
|
|
137
153
|
}
|
package/scripts/validate.ts
CHANGED
|
@@ -110,7 +110,7 @@ function checkPersonaExistence(config: AgentBootConfig, configDir: string): Chec
|
|
|
110
110
|
|
|
111
111
|
const corePersonasDir = path.join(ROOT, "core", "personas");
|
|
112
112
|
const extendDir = config.personas?.customDir
|
|
113
|
-
? path.resolve(configDir, config.personas.
|
|
113
|
+
? path.resolve(configDir, config.personas.customDir)
|
|
114
114
|
: null;
|
|
115
115
|
|
|
116
116
|
// Collect all available persona directories.
|
|
@@ -183,7 +183,7 @@ function checkTraitReferences(config: AgentBootConfig, configDir: string): Check
|
|
|
183
183
|
// Scan all persona.config.json files.
|
|
184
184
|
const personaRoots: string[] = [path.join(ROOT, "core", "personas")];
|
|
185
185
|
if (config.personas?.customDir) {
|
|
186
|
-
const ext = path.resolve(configDir, config.personas.
|
|
186
|
+
const ext = path.resolve(configDir, config.personas.customDir);
|
|
187
187
|
if (fs.existsSync(ext)) personaRoots.push(ext);
|
|
188
188
|
}
|
|
189
189
|
|
|
@@ -243,7 +243,7 @@ function checkSkillFrontmatter(config: AgentBootConfig, configDir: string): Chec
|
|
|
243
243
|
|
|
244
244
|
const personaRoots: string[] = [path.join(ROOT, "core", "personas")];
|
|
245
245
|
if (config.personas?.customDir) {
|
|
246
|
-
const ext = path.resolve(configDir, config.personas.
|
|
246
|
+
const ext = path.resolve(configDir, config.personas.customDir);
|
|
247
247
|
if (fs.existsSync(ext)) personaRoots.push(ext);
|
|
248
248
|
}
|
|
249
249
|
|
|
@@ -295,9 +295,14 @@ function checkSkillFrontmatter(config: AgentBootConfig, configDir: string): Chec
|
|
|
295
295
|
// ---------------------------------------------------------------------------
|
|
296
296
|
|
|
297
297
|
function buildSecretPatterns(config: AgentBootConfig): RegExp[] {
|
|
298
|
-
const configPatterns =
|
|
299
|
-
|
|
300
|
-
|
|
298
|
+
const configPatterns: RegExp[] = [];
|
|
299
|
+
for (const p of config.validation?.secretPatterns ?? []) {
|
|
300
|
+
try {
|
|
301
|
+
configPatterns.push(new RegExp(p));
|
|
302
|
+
} catch (e: unknown) {
|
|
303
|
+
console.error(` ⚠ Invalid secretPattern regex "${p}": ${e instanceof Error ? e.message : String(e)} — skipping`);
|
|
304
|
+
}
|
|
305
|
+
}
|
|
301
306
|
return [...DEFAULT_SECRET_PATTERNS, ...configPatterns];
|
|
302
307
|
}
|
|
303
308
|
|
|
@@ -311,7 +316,7 @@ function checkNoSecrets(config: AgentBootConfig, configDir: string): CheckResult
|
|
|
311
316
|
];
|
|
312
317
|
|
|
313
318
|
if (config.personas?.customDir) {
|
|
314
|
-
const ext = path.resolve(configDir, config.personas.
|
|
319
|
+
const ext = path.resolve(configDir, config.personas.customDir);
|
|
315
320
|
if (fs.existsSync(ext)) scanRoots.push(ext);
|
|
316
321
|
}
|
|
317
322
|
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: Persona request
|
|
3
|
-
about: Propose a new persona for AgentBoot core
|
|
4
|
-
title: "persona: [name here]"
|
|
5
|
-
labels: persona-request
|
|
6
|
-
assignees: ""
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
## Persona name
|
|
10
|
-
|
|
11
|
-
<!-- What would you call this persona? This becomes the display name in PERSONAS.md. -->
|
|
12
|
-
|
|
13
|
-
## Invocation
|
|
14
|
-
|
|
15
|
-
<!-- What slash command would invoke it? e.g., /review-architecture, /audit-deps -->
|
|
16
|
-
|
|
17
|
-
## Use case
|
|
18
|
-
|
|
19
|
-
<!-- What problem does this persona solve? Describe the situation: what does a developer
|
|
20
|
-
want to do, what is painful about doing it today, and how does this persona make
|
|
21
|
-
it better? Be concrete. -->
|
|
22
|
-
|
|
23
|
-
## What traits would it compose?
|
|
24
|
-
|
|
25
|
-
<!-- List the core traits this persona would use, with weights where applicable.
|
|
26
|
-
Example:
|
|
27
|
-
- critical-thinking: HIGH
|
|
28
|
-
- structured-output: true
|
|
29
|
-
- source-citation: true
|
|
30
|
-
|
|
31
|
-
If this persona requires a new trait that does not exist yet, explain what that
|
|
32
|
-
trait would do and why existing traits are insufficient. -->
|
|
33
|
-
|
|
34
|
-
## Example invocation
|
|
35
|
-
|
|
36
|
-
<!-- Show a realistic prompt a developer would give this persona and describe
|
|
37
|
-
the output they would expect. This is the primary way maintainers evaluate
|
|
38
|
-
whether the persona is scoped correctly and fills a real gap. -->
|
|
39
|
-
|
|
40
|
-
**Input:**
|
|
41
|
-
```
|
|
42
|
-
[paste a realistic prompt here]
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
**Expected output structure:**
|
|
46
|
-
```
|
|
47
|
-
[describe or sketch the expected output here]
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
## Why core, not a domain extension?
|
|
51
|
-
|
|
52
|
-
<!-- AgentBoot core contains only generic, domain-agnostic personas that are useful
|
|
53
|
-
to any engineering team regardless of industry. Explain why this persona fits
|
|
54
|
-
that bar.
|
|
55
|
-
|
|
56
|
-
If it is specific to a compliance regime, a framework, an industry, or an internal
|
|
57
|
-
standard, it should be a domain extension instead. See docs/extending.md. -->
|
|
58
|
-
|
|
59
|
-
## Additional context
|
|
60
|
-
|
|
61
|
-
<!-- Anything else that would help maintainers evaluate this proposal. Links to
|
|
62
|
-
prior art, related issues, examples from other tools, etc. -->
|
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: Quality feedback
|
|
3
|
-
about: Report bad or unexpected output from a persona
|
|
4
|
-
title: "quality: [persona-id] [brief description]"
|
|
5
|
-
labels: quality-feedback
|
|
6
|
-
assignees: ""
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
## Persona name
|
|
10
|
-
|
|
11
|
-
<!-- Which persona produced the bad output? e.g., code-reviewer, security-reviewer -->
|
|
12
|
-
|
|
13
|
-
## What you asked it to do
|
|
14
|
-
|
|
15
|
-
<!-- Describe what you asked the persona to do. Include the exact prompt or command
|
|
16
|
-
if you can. If the input is large, include the most relevant portion. -->
|
|
17
|
-
|
|
18
|
-
**Prompt / invocation:**
|
|
19
|
-
```
|
|
20
|
-
[paste your prompt here]
|
|
21
|
-
```
|
|
22
|
-
|
|
23
|
-
**Input (if relevant):**
|
|
24
|
-
```
|
|
25
|
-
[paste the code, file, or context you gave it, or a representative excerpt]
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
## What it actually did
|
|
29
|
-
|
|
30
|
-
<!-- Describe what the persona produced. If the output was long, include the most
|
|
31
|
-
relevant portion — the finding that was wrong, the section that was missing,
|
|
32
|
-
the format that was broken, etc. -->
|
|
33
|
-
|
|
34
|
-
**Actual output:**
|
|
35
|
-
```
|
|
36
|
-
[paste the relevant portion of the output here]
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
## What you expected
|
|
40
|
-
|
|
41
|
-
<!-- Describe what you expected it to do instead. Be specific. "Better output" is
|
|
42
|
-
not actionable. "The persona should have flagged the missing null check on line 14
|
|
43
|
-
but instead flagged a style preference" is actionable. -->
|
|
44
|
-
|
|
45
|
-
## Claude Code version
|
|
46
|
-
|
|
47
|
-
<!-- Run `claude --version` and paste the output here. -->
|
|
48
|
-
|
|
49
|
-
## Trait weight or config (if known)
|
|
50
|
-
|
|
51
|
-
<!-- If you know which trait weight was active for this persona (HIGH / MEDIUM / LOW),
|
|
52
|
-
include it here. If you modified any agentboot.config.json settings that might
|
|
53
|
-
be relevant, include those too. -->
|
|
54
|
-
|
|
55
|
-
## Is this a regression?
|
|
56
|
-
|
|
57
|
-
<!-- Did this persona work correctly before and then stop working? If so, when did you
|
|
58
|
-
last see it working correctly, and do you know of any changes (to Claude Code,
|
|
59
|
-
to AgentBoot, to the persona file) that happened around that time? -->
|
|
60
|
-
|
|
61
|
-
- [ ] Yes, this worked correctly before
|
|
62
|
-
- [ ] No, this is a first-time deployment and it has never worked correctly
|
|
63
|
-
- [ ] Unknown
|
|
64
|
-
|
|
65
|
-
## Additional context
|
|
66
|
-
|
|
67
|
-
<!-- Anything else that would help reproduce or understand the issue. -->
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
name: CLA Assistant
|
|
2
|
-
on:
|
|
3
|
-
issue_comment:
|
|
4
|
-
types: [created]
|
|
5
|
-
pull_request_target:
|
|
6
|
-
types: [opened, synchronize, reopened]
|
|
7
|
-
|
|
8
|
-
permissions:
|
|
9
|
-
actions: write
|
|
10
|
-
contents: write
|
|
11
|
-
pull-requests: write
|
|
12
|
-
statuses: write
|
|
13
|
-
|
|
14
|
-
jobs:
|
|
15
|
-
cla:
|
|
16
|
-
runs-on: ubuntu-latest
|
|
17
|
-
steps:
|
|
18
|
-
- uses: contributor-assistant/github-action@v2
|
|
19
|
-
env:
|
|
20
|
-
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
21
|
-
with:
|
|
22
|
-
path-to-signatures: "signatures/cla.json"
|
|
23
|
-
path-to-document: "https://github.com/agentboot-dev/agentboot/blob/main/CLA.md"
|
|
24
|
-
branch: "main"
|
|
25
|
-
allowlist: "saavyone,dependabot[bot]"
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
name: Validate
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
push:
|
|
5
|
-
branches:
|
|
6
|
-
- main
|
|
7
|
-
pull_request:
|
|
8
|
-
|
|
9
|
-
jobs:
|
|
10
|
-
validate:
|
|
11
|
-
name: Validate and build
|
|
12
|
-
runs-on: ubuntu-latest
|
|
13
|
-
|
|
14
|
-
steps:
|
|
15
|
-
- name: Checkout
|
|
16
|
-
uses: actions/checkout@v4
|
|
17
|
-
|
|
18
|
-
- name: Set up Node.js
|
|
19
|
-
uses: actions/setup-node@v4
|
|
20
|
-
with:
|
|
21
|
-
node-version: "18"
|
|
22
|
-
cache: "npm"
|
|
23
|
-
|
|
24
|
-
- name: Install dependencies
|
|
25
|
-
run: npm install
|
|
26
|
-
|
|
27
|
-
- name: Validate personas and traits
|
|
28
|
-
run: npm run validate
|
|
29
|
-
# Exits 1 if any persona is missing required frontmatter fields,
|
|
30
|
-
# any trait referenced in a persona does not exist, or
|
|
31
|
-
# agentboot.config.json fails schema validation.
|
|
32
|
-
|
|
33
|
-
- name: Build
|
|
34
|
-
run: npm run build
|
|
35
|
-
# Resolves all trait compositions and produces compiled output in .build/.
|
|
36
|
-
# Fails if any persona cannot be compiled (missing trait, malformed SKILL.md, etc.).
|
|
37
|
-
|
|
38
|
-
- name: Check PERSONAS.md is up to date
|
|
39
|
-
run: |
|
|
40
|
-
# The build step regenerates PERSONAS.md from the compiled persona set.
|
|
41
|
-
# If the committed PERSONAS.md differs from the regenerated version,
|
|
42
|
-
# this step fails. Run `npm run build` locally and commit the updated
|
|
43
|
-
# PERSONAS.md to fix this check.
|
|
44
|
-
if ! git diff --exit-code PERSONAS.md; then
|
|
45
|
-
echo ""
|
|
46
|
-
echo "PERSONAS.md is out of date."
|
|
47
|
-
echo "Run 'npm run build' locally and commit the updated PERSONAS.md."
|
|
48
|
-
exit 1
|
|
49
|
-
fi
|
package/.idea/agentboot.iml
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
-
<module type="JAVA_MODULE" version="4">
|
|
3
|
-
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
|
4
|
-
<exclude-output />
|
|
5
|
-
<content url="file://$MODULE_DIR$" />
|
|
6
|
-
<orderEntry type="inheritedJdk" />
|
|
7
|
-
<orderEntry type="sourceFolder" forTests="false" />
|
|
8
|
-
</component>
|
|
9
|
-
</module>
|
package/.idea/misc.xml
DELETED
package/.idea/modules.xml
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
-
<project version="4">
|
|
3
|
-
<component name="ProjectModuleManager">
|
|
4
|
-
<modules>
|
|
5
|
-
<module fileurl="file://$PROJECT_DIR$/.idea/agentboot.iml" filepath="$PROJECT_DIR$/.idea/agentboot.iml" />
|
|
6
|
-
</modules>
|
|
7
|
-
</component>
|
|
8
|
-
</project>
|