@kaged/dsl

YAML + Zod project DSL parser and validator with federated config, URI-prefix enforcement, local overlays, and recursive project-reference resolution

15
source files
10
test files
~12.0k
lines
✓ 516 pass
tests
pass
typecheck
1w
lint

Test results 516

compileProjectDsl: single-level resolution > resolves one project reference and attaches _compiled [23.78ms]
compileProjectDsl: single-level resolution > preserves declared name/description/overrides alongside _compiled [6.04ms]
compileProjectDsl: single-level resolution > regular subagents pass through unchanged [9.94ms]
compileProjectDsl: single-level resolution > no project references: returns input unchanged [1.76ms]
compileProjectDsl: single-level resolution > hasProjectReferences true when any ref exists [2.92ms]
compileProjectDsl: recursion > A → B → C with paths relative to each parent's root [5.39ms]
compileProjectDsl: recursion > silo boundary: nested ref at project:/data is NOT resolved against parent root [9.64ms]
compileProjectDsl: cycle detection > unbounded chain is blocked at the depth limit [9.65ms]
compileProjectDsl: cycle detection > diamond (A → B and A → C, pointing to distinct D's) is NOT flagged [14.88ms]
compileProjectDsl: depth limit > aborts at the default depth limit (16) [53.10ms]
compileProjectDsl: depth limit > custom maxDepth=2 stops at depth 2 [10.28ms]
compileProjectDsl: depth limit > depth equal to limit is permitted [9.22ms]
compileProjectDsl: overrides > simple top-level override of primary.model [4.19ms]
compileProjectDsl: overrides > nested .local.yaml is applied BEFORE the parent's overrides [4.65ms]
compileProjectDsl: failure modes > missing nested project.yaml yields nested_project_missing diagnostic [2.40ms]
compileProjectDsl: failure modes > invalid nested project.yaml yields a compile diagnostic [5.36ms]
compileProjectDsl: failure modes > diagnostic path traces to the offending map key [2.83ms]
compileProjectDsl: failure modes > warnings from nested cage:disabled bubble up with map-key prefix [2.89ms]
compileProjectDsl: injectable readFile > uses provided readFile in place of node:fs [1.66ms]
resolveCompaction > returns parent when child is undefined [0.040ms]
resolveCompaction > child fields override parent fields [0.050ms]
resolveCompaction > child strategy overrides parent strategy [0.070ms]
resolveCompaction > child summarize block overrides parent summarize block [0.050ms]
resolveCompaction > child always_keep replaces parent always_keep (no merge) [0.030ms]
resolveCompaction > all child fields specified produces fully overridden result [0.050ms]
compileProjectDsl: compaction materialization > agent with no compaction gets DEFAULT_COMPACTION materialized [1.01ms]
compileProjectDsl: compaction materialization > primary compaction is materialized with resolved defaults [1.42ms]
compileProjectDsl: compaction materialization > subagent inherits parent compaction when unset [5.78ms]
compileProjectDsl: compaction materialization > subagent overrides specific fields, inherits the rest [2.43ms]
compileProjectDsl: compaction materialization > three-level inheritance: grandchild inherits from child override [2.41ms]
compileProjectDsl: compaction materialization > project-reference boundary resets compaction to default [2.97ms]
compileProjectDsl: compaction materialization > nested project with its own compaction uses that, not parent's [2.44ms]
compileProjectDsl: compaction materialization > plugins pass through unchanged during compilation [1.95ms]
DEFAULT_COMPACTION defaults (ADR-0024 amendment §7) > includes summarize block with default prompt path [0.030ms]
DEFAULT_COMPACTION defaults (ADR-0024 amendment §7) > summarize block omits model (agent uses its own) [0.020ms]
CompactionSummarizeSchema: optional model and prompt > accepts summarize block with prompt only (no model) [0.940ms]
CompactionSummarizeSchema: optional model and prompt > accepts summarize block with model only (no prompt) [0.730ms]
CompactionSummarizeSchema: optional model and prompt > accepts summarize block with no model and no prompt [0.740ms]
worked examples > minimal.yaml validates successfully [1.35ms]
worked examples > single-subagent.yaml validates successfully [2.38ms]
worked examples > multi-subagent.yaml validates successfully [3.18ms]
worked examples > network-allowlist.yaml validates successfully [2.88ms]
worked examples > with-plugins.yaml validates successfully [2.01ms]
worked examples > insecure.yaml validates successfully [2.31ms]
worked examples > portable.yaml validates successfully [2.72ms]
worked examples > insecure.yaml emits cage:disabled warning [2.27ms]
worked examples > minimal.yaml has no subagents on primary [0.780ms]
worked examples > with-plugins.yaml has plugins [1.98ms]
schema: accepts valid > minimal valid project [0.660ms]
schema: accepts valid > project with description [0.700ms]
schema: accepts valid > primary with parameters [0.780ms]
schema: accepts valid > subagent with cage: disabled is valid [1.43ms]
schema: accepts valid > cage with all optional fields [1.60ms]
schema: accepts valid > model alias: various valid names [2.45ms]
schema: accepts valid > project slug: various valid slugs [1.86ms]
schema: accepts valid > system_prompt: URI-prefixed paths accepted [1.87ms]
schema: accepts valid > system_prompt: naked path rejected [1.03ms]
schema: accepts valid > plugins with all fields [0.860ms]
schema: accepts valid > primary with per-agent tools [0.920ms]
schema: rejects invalid > missing version [0.720ms]
schema: rejects invalid > version: 2 is rejected [0.750ms]
schema: rejects invalid > version: "1" (string) is rejected [0.690ms]
schema: rejects invalid > missing project [0.650ms]
schema: rejects invalid > missing primary [0.550ms]
schema: rejects invalid > unknown top-level field [0.870ms]
schema: rejects invalid > model alias with colon is rejected [0.730ms]
schema: rejects invalid > reserved model alias rejected [3.21ms]
schema: rejects invalid > reserved subagent name rejected [3.80ms]
schema: rejects invalid > absolute path in system_prompt rejected [0.710ms]
schema: rejects invalid > path with .. escape rejected [0.670ms]
schema: rejects invalid > absolute path in cage.fs rejected [1.38ms]
schema: rejects invalid > description over 280 chars rejected [0.780ms]
schema: rejects invalid > description at 280 chars accepted [0.660ms]
schema: rejects invalid > more than 64 subagents rejected [28.17ms]
schema: rejects invalid > cage value that is neither object nor disabled [1.04ms]
schema: rejects invalid > cage.state invalid enum value [0.830ms]
schema: rejects invalid > cage.seccomp invalid enum value [0.780ms]
schema: rejects invalid > cage.limits.memory_mb below minimum [0.770ms]
schema: rejects invalid > mount.mode invalid value [0.760ms]
schema: rejects invalid > YAML syntax error throws DslError [0.480ms]
schema: rejects invalid > top-level subagents key rejected (ADR-0022) [0.520ms]
schema: rejects invalid > top-level interconnect key rejected (ADR-0022) [0.520ms]
schema: rejects invalid > top-level cage_defaults key rejected (ADR-0022) [0.490ms]
schema: rejects invalid > top-level tools key rejected (ADR-0022) [0.440ms]
cross-reference validation > root agent cage must be disabled [0.480ms]
cross-reference validation > principal_scope: root-only tool on non-root agent rejected [0.720ms]
cross-reference validation > principal_scope: root-only tool on root agent accepted [0.400ms]
cross-reference validation > tool-name collision: project-ref name override matches sibling map key [0.980ms]
cross-reference validation > no errors when subagents have unique names [0.890ms]
error messages > errors include doc links [0.450ms]
error messages > unknown field includes did-you-mean [0.460ms]
error messages > DslError has diagnostics array [0.510ms]
error messages > YAML syntax error has line info [0.780ms]
error messages > file path appears in diagnostic when provided [0.440ms]
utilities > parse() returns data + warnings separately [0.470ms]
utilities > validateCrossRefs returns empty for valid DSL [0.450ms]
tasks block: accepts valid > project without tasks is valid [0.440ms]
tasks block: accepts valid > project with empty tasks map is valid [0.510ms]
tasks block: accepts valid > single named task with all fields [0.740ms]
tasks block: accepts valid > minimal task (command only) [0.530ms]
tasks block: accepts valid > long_running task [0.510ms]
tasks block: accepts valid > confirm task [0.500ms]
tasks block: accepts valid > multiple tasks with groups [0.560ms]
tasks block: accepts valid > task name with hyphens and underscores [1.45ms]
tasks block: rejects invalid > reserved task name: adhoc [0.550ms]
tasks block: rejects invalid > reserved task name: all [0.510ms]
tasks block: rejects invalid > reserved task name: new [0.480ms]
tasks block: rejects invalid > task name starting with digit rejected [0.510ms]
tasks block: rejects invalid > task name with uppercase rejected [0.510ms]
tasks block: rejects invalid > single-char task name rejected [0.510ms]
tasks block: rejects invalid > task missing command rejected [0.510ms]
tasks block: rejects invalid > task with empty command rejected [0.550ms]
tasks block: rejects invalid > task description over 280 chars rejected [0.630ms]
tasks block: rejects invalid > task with absolute cwd rejected [0.540ms]
tasks block: rejects invalid > task with .. cwd rejected [0.560ms]
tasks block: rejects invalid > task with unknown field rejected (strict mode) [0.580ms]
tasks block: rejects invalid > more than 64 tasks rejected [2.23ms]
tasks block: rejects invalid > task env with non-string value rejected [0.470ms]
tasks block: cross-reference validation > unique task names pass validation [0.430ms]
workflows block: accepts valid > project without workflows is valid [0.350ms]
workflows block: accepts valid > project with empty workflows map is valid [0.430ms]
workflows block: accepts valid > single workflow with all fields [2.05ms]
workflows block: accepts valid > minimal workflow (required fields only) [0.680ms]
workflows block: accepts valid > workflow name with dots, hyphens, underscores [2.07ms]
workflows block: accepts valid > multiple workflows [0.950ms]
workflows block: accepts valid > workflow with empty inputs map [0.550ms]
workflows block: accepts valid > input required defaults to true [0.630ms]
workflows block: rejects invalid > reserved workflow name: adhoc [0.560ms]
workflows block: rejects invalid > reserved workflow name: all [0.570ms]
workflows block: rejects invalid > workflow name starting with digit rejected [0.570ms]
workflows block: rejects invalid > workflow name with uppercase rejected [0.580ms]
workflows block: rejects invalid > single-char workflow name rejected [0.570ms]
workflows block: rejects invalid > workflow missing description rejected [0.580ms]
workflows block: rejects invalid > workflow missing steps rejected (ADR-0038) [0.530ms]
workflows block: rejects invalid > workflow with empty steps array rejected (ADR-0038) [0.550ms]
workflows block: rejects invalid > workflow missing inputs rejected [0.610ms]
workflows block: rejects invalid > workflow missing tools rejected [0.620ms]
workflows block: rejects invalid > workflow description over 280 chars rejected [0.690ms]
workflows block: rejects invalid > workflow with system_prompt rejected (ADR-0038 removed field) [1.00ms]
workflows block: rejects invalid > workflow input with invalid type rejected [0.720ms]
workflows block: rejects invalid > workflow input missing type rejected [0.770ms]
workflows block: rejects invalid > workflow with unknown field rejected (strict) [0.810ms]
workflows block: rejects invalid > workflow input with unknown field rejected (strict) [0.840ms]
workflows block: rejects invalid > workflow tools with unknown field rejected (strict) [0.730ms]
workflows block: rejects invalid > workflow invokable_by with invalid value rejected [0.730ms]
workflows block: rejects invalid > workflow timeout_seconds zero rejected [0.740ms]
workflows block: rejects invalid > more than 64 workflows rejected [13.97ms]
workflow steps: accepts valid > agent step with all fields [1.52ms]
workflow steps: accepts valid > confirm step with message and show [0.790ms]
workflow steps: accepts valid > task step referencing project task [0.890ms]
workflow steps: accepts valid > multi-step workflow with bindings across steps [0.970ms]
workflow steps: accepts valid > step with on_fail: continue is accepted [0.740ms]
workflow steps: accepts valid > 32 steps accepted (max) [2.16ms]
workflow steps: accepts valid > workflow-level model override accepted (ADR-0038) [0.720ms]
workflow steps: accepts valid > workflow without model inherits (model undefined, ADR-0038) [0.710ms]
workflow steps: accepts valid > per-step model override on agent step accepted (ADR-0038) [0.800ms]
workflow steps: accepts valid > workflow-level and step-level model overrides coexist (ADR-0038) [0.830ms]
workflow steps: rejects invalid > step with invalid kind rejected [0.840ms]
workflow steps: rejects invalid > step missing id rejected [0.730ms]
workflow steps: rejects invalid > step missing kind rejected [0.750ms]
workflow steps: rejects invalid > duplicate step IDs rejected [0.740ms]
workflow steps: rejects invalid > 33 steps rejected (over max 32) [2.18ms]
workflow steps: rejects invalid > agent step missing prompt rejected [0.570ms]
workflow steps: rejects invalid > agent step with naked prompt path rejected [0.630ms]
workflow steps: rejects invalid > confirm step missing message rejected [0.570ms]
workflow steps: rejects invalid > task step missing task rejected [0.580ms]
workflow steps: rejects invalid > step output with file type rejected [0.660ms]
workflow steps: rejects invalid > more than 8 outputs per step rejected [0.880ms]
workflow steps: rejects invalid > more than 16 with entries per step rejected [0.890ms]
workflow steps: rejects invalid > step id too short (1 char) rejected [0.640ms]
workflow steps: rejects invalid > step id with uppercase rejected [0.740ms]
workflow steps: rejects invalid > step with unknown field rejected (strict) [0.830ms]
workflow steps: rejects invalid > step on_fail naming a non-verb non-step target is a cross-ref error (ADR-0048: on_fail is no longer an enum) [0.800ms]
workflow steps: rejects invalid > confirm step show over 8 entries rejected [0.940ms]
workflow steps: rejects invalid > model on confirm step rejected (ADR-0038) [0.840ms]
workflow steps: rejects invalid > model on task step rejected (ADR-0038) [0.870ms]
binding syntax validation > valid input binding accepted [0.870ms]
binding syntax validation > valid step output binding accepted [0.930ms]
binding syntax validation > mixed text and bindings accepted [1.00ms]
binding syntax validation > unclosed binding rejected at schema level [0.820ms]
binding syntax validation > empty binding rejected at schema level [0.850ms]
binding syntax validation > unknown binding root rejected at schema level [0.800ms]
binding syntax validation > binding without output segment rejected [2.24ms]
workflow steps: cross-reference validation > unknown input reference produces error [1.07ms]
workflow steps: cross-reference validation > forward step reference is statically legal (ADR-0048 §6 withdraws step_ref_forward; runtime-checked instead) [3.93ms]
workflow steps: cross-reference validation > reference to a step that exists nowhere produces step_ref_unknown_step [0.720ms]
workflow steps: cross-reference validation > undeclared output reference produces error [0.750ms]
workflow steps: cross-reference validation > dependency on an on_fail:continue step is statically legal (ADR-0048 §6 withdraws step_ref_skippable) [0.760ms]
workflow steps: cross-reference validation > file input in confirm binding produces error [0.640ms]
workflow steps: cross-reference validation > non-file input in confirm binding is valid [0.580ms]
workflow steps: cross-reference validation > task step referencing unknown task produces error [0.640ms]
workflow steps: cross-reference validation > task step referencing long_running task produces error [0.650ms]
workflow steps: cross-reference validation > step tools not subset of workflow tools produces error [0.650ms]
workflow steps: cross-reference validation > step tools that are a subset pass validation [0.600ms]
workflow steps: cross-reference validation > step tools matching namespace glob pass validation [0.610ms]
workflow steps: cross-reference validation > valid backward step reference passes [0.670ms]
workflow steps: cross-reference validation > step without on_fail defaults to abort (no skippable error) [0.680ms]
workflow steps ADR-0048: routing schema > on_success and on_fail accept reserved verbs [0.750ms]
workflow steps ADR-0048: routing schema > on_success and on_fail accept a step id as target [0.810ms]
workflow steps ADR-0048: routing schema > a step id equal to a reserved routing word is rejected [0.710ms]
workflow steps ADR-0048: routing schema > routing to a target that is neither a verb nor a real step id produces step_route_unknown [0.640ms]
workflow steps ADR-0048: bounded loops > max_runs accepts a positive integer [0.640ms]
workflow steps ADR-0048: bounded loops > max_runs below 1 is rejected [0.660ms]
workflow steps ADR-0048: bounded loops > a back-edge target without max_runs produces step_loop_unbounded [0.730ms]
workflow steps ADR-0048: bounded loops > a back-edge target with max_runs is valid [0.660ms]
workflow steps ADR-0048: kind compare > a numeric compare step parses with a/b/comparison and routing [0.820ms]
workflow steps ADR-0048: kind compare > compare with the in verb accepts a YAML array for b [0.780ms]
workflow steps ADR-0048: kind compare > an unknown comparison verb is rejected [0.680ms]
workflow steps ADR-0048: kind compare > compare may not carry timeout_seconds [0.720ms]
workflow steps ADR-0048: task parameters and implicit outputs > a task step accepts a with array of argv tokens [0.680ms]
workflow steps ADR-0048: task parameters and implicit outputs > a downstream agent may bind a task step's implicit stdout/stderr/exit_code [0.700ms]
workflow steps ADR-0048: task parameters and implicit outputs > binding a task output other than stdout/stderr/exit_code produces step_ref_undeclared_output [0.690ms]
workflow steps ADR-0048: task parameters and implicit outputs > a task step still rejects an outputs block [0.650ms]
workflow steps ADR-0048: run_count binding root > self.run_count and steps.<id>.run_count are bindable in an agent with block [0.670ms]
workflow steps ADR-0048: run_count binding root > run_count referencing an unknown step produces step_ref_unknown_step [0.620ms]
mcp block: accepts valid > minimal stdio server [0.590ms]
mcp block: accepts valid > sse server with auth and headers [0.640ms]
mcp block: accepts valid > stdio server with env and cwd [0.490ms]
mcp block: accepts valid > null server removes entry (nullification) [0.480ms]
mcp block: accepts valid > header auth with custom header name [0.470ms]
mcp block: accepts valid > no-auth server (auth omitted) [0.410ms]
mcp block: rejects invalid > stdio without command [0.510ms]
mcp block: rejects invalid > sse without url [0.430ms]
mcp block: rejects invalid > stdio with url (wrong transport fields) [0.530ms]
mcp block: rejects invalid > sse with command (wrong transport fields) [0.520ms]
mcp block: rejects invalid > header auth without secret_ref [0.490ms]
mcp block: rejects invalid > invalid server key (uppercase) [0.490ms]
mcp block: rejects invalid > invalid transport type [0.460ms]
mcp block: rejects invalid > unknown field in server block [0.490ms]
mcp block: rejects invalid > more than 16 servers [1.19ms]
wiki: accepts valid > minimal wiki with path only [0.400ms]
wiki: accepts valid > wiki with home override [0.430ms]
wiki: accepts valid > wiki with config:/ scoped path [0.380ms]
wiki: accepts valid > wiki with full git config [0.470ms]
wiki: accepts valid > wiki with git block, all defaults [0.410ms]
wiki: accepts valid > project without wiki is valid [0.340ms]
wiki: rejects invalid > wiki with naked path (no URI prefix) [0.490ms]
wiki: rejects invalid > wiki with path traversal [0.410ms]
wiki: rejects invalid > wiki home with subdirectory path [0.410ms]
wiki: rejects invalid > auto_push without auto_commit [0.420ms]
wiki: rejects invalid > unknown field in wiki block [0.410ms]
wiki: rejects invalid > unknown field in wiki.git block [0.420ms]
wiki: rejects invalid > wiki missing required path [0.420ms]
deepMergeDsl > scalars: overlay replaces base [0.070ms]
deepMergeDsl > absent keys: base value passes through [0.030ms]
deepMergeDsl > null: removes the key (nullification) [0.040ms]
deepMergeDsl > objects: deep-merge recursively [0.030ms]
deepMergeDsl > objects: deep-merge multiple levels [0.030ms]
deepMergeDsl > arrays: overlay replaces base entirely [0.030ms]
deepMergeDsl > arrays: empty overlay array replaces base array [0.020ms]
deepMergeDsl > type mismatch: overlay replaces base [0.020ms]
deepMergeDsl > type mismatch: object replaced by scalar [0.020ms]
deepMergeDsl > type mismatch: scalar replaced by object [0.020ms]
deepMergeDsl > does not mutate base or overlay [0.070ms]
deepMergeDsl > empty overlay returns base clone [0.030ms]
deepMergeDsl > empty base returns overlay clone [0.030ms]
deepMergeDsl > nullify nested key [0.030ms]
deepMergeDsl > overlay adds new keys [0.020ms]
parseUri > parses project:/ prefix [0.040ms]
parseUri > parses config:/ prefix [0.020ms]
parseUri > parses deeply nested path [0.020ms]
parseUri > parses single-segment path [0.030ms]
parseUri > rejects naked path [0.040ms]
parseUri > rejects absolute path [0.030ms]
parseUri > rejects empty string [0.030ms]
parseUri > rejects unknown prefix [0.020ms]
parseUri > double-slash: second slash becomes part of path [0.020ms]
parseUri > rejects .. escape at start [0.020ms]
parseUri > rejects .. escape in middle [0.020ms]
parseUri > rejects bare .. path [0.020ms]
parseUri > allows segments containing .. in names [0.020ms]
resolveUri > project:/ resolves to project root [0.070ms]
resolveUri > config:/ resolves to .kaged/ under project root [0.020ms]
resolveUri > project:/ single file [0.030ms]
resolveUri > config:/ deeply nested [0.030ms]
resolveUri > throws on invalid URI [0.030ms]
shadowPath > config:/ with extension inserts .local before ext [0.060ms]
shadowPath > config:/ with .json extension [0.030ms]
shadowPath > config:/ with .yaml extension [0.010ms]
shadowPath > config:/ without extension appends .local [0.020ms]
shadowPath > config:/ deeply nested path [0.020ms]
shadowPath > project:/ returns null (no shadowing) [0.010ms]
shadowPath > config:/ with dot in directory name but no extension in filename [0.010ms]
loadProjectDsl > no overlay: behaves like parseDsl [0.780ms]
loadProjectDsl > overlay merges: overrides primary.model [0.620ms]
loadProjectDsl > overlay merges: adds description [0.520ms]
loadProjectDsl > overlay rejects version override [0.620ms]
loadProjectDsl > overlay rejects project override [0.440ms]
loadProjectDsl > overlay merges: deep-merges primary parameters [0.570ms]
loadProjectDsl > overlay merges: subagents record deep-merges (empty overlay preserves base) [0.940ms]
loadProjectDsl > overlay merges: subagent nullified via null value [0.650ms]
loadProjectDsl > overlay YAML syntax error throws DslError [0.470ms]
loadProjectDsl > base YAML syntax error throws DslError [0.190ms]
loadProjectDsl > merged result that fails schema throws DslError [0.590ms]
loadProjectDsl > overlay file path appears in forbidden-key error [0.260ms]
loadProjectDsl > overlay with cage:disabled produces warning [0.910ms]
PrefixedPathSchema integration > project:/ in system_prompt accepted [0.410ms]
PrefixedPathSchema integration > config:/ in system_prompt accepted [0.420ms]
PrefixedPathSchema integration > naked path in system_prompt rejected [0.470ms]
PrefixedPathSchema integration > project:/ in task cwd accepted [0.500ms]
PrefixedPathSchema integration > naked path in task cwd rejected [0.540ms]
ToolOverrideSchema integration > tools with overrides accepted [0.540ms]
ToolOverrideSchema integration > tools with null value (disable) accepted [0.450ms]
ToolOverrideSchema integration > tools with parameters accepted [0.500ms]
ToolOverrideSchema integration > project without tools is valid [0.410ms]
ToolOverrideSchema integration > overlay merges tools [0.590ms]
per-agent plugins: accepts valid > primary with a single plugin override (registry + per-agent) [1.20ms]
per-agent plugins: accepts valid > primary with enabled: true override [0.630ms]
per-agent plugins: accepts valid > minimal per-agent override (only enabled) [0.570ms]
per-agent plugins: accepts valid > multiple plugins on same agent [0.730ms]
per-agent plugins: accepts valid > pre_compact hook accepted [0.600ms]
per-agent plugins: accepts valid > subagent with its own plugin override [0.920ms]
per-agent plugins: accepts valid > registry entry with source field [0.540ms]
per-agent plugins: accepts valid > registry entry with git: source [0.530ms]
per-agent plugins: accepts valid > registry entry with project: source [0.540ms]
per-agent plugins: accepts valid > registry entry with config: source [0.530ms]
per-agent plugins: rejects invalid > unknown field in per-agent plugin declaration [0.680ms]
per-agent plugins: rejects invalid > invalid hook name rejected [0.630ms]
per-agent plugins: rejects invalid > plugin slot name starting with digit rejected [0.590ms]
per-agent plugins: rejects invalid > plugin slot name with uppercase rejected [0.570ms]
per-agent plugins: rejects invalid > more than 16 plugins per agent rejected [1.45ms]
per-agent plugins: rejects invalid > registry entry without package rejected [0.590ms]
per-agent plugins: rejects invalid > invalid source prefix rejected [0.540ms]
per-agent plugins: rejects invalid > per-agent package field rejected (belongs in registry) [0.640ms]
per-agent plugins: rejects invalid > per-agent source field rejected (belongs in registry) [0.590ms]
per-agent plugins: cross-ref validation > per-agent slot not in project registry → error [0.150ms]
per-agent plugins: cross-ref validation > per-agent slot in project registry → no error [0.040ms]
per-agent plugins: cross-ref validation > subagent per-agent slot not in project registry → error [0.090ms]
per-agent plugins: cross-ref validation > primary-only hooks on subagent → warning [0.080ms]
per-agent plugins: cross-ref validation > pre_compact on subagent → no warning [0.050ms]
per-agent plugins: cross-ref validation > primary-only hooks on root agent → no warning [0.040ms]
per-agent compaction: accepts valid > compaction with drop strategy (default) [0.550ms]
per-agent compaction: accepts valid > compaction with summarize strategy [0.590ms]
per-agent compaction: accepts valid > compaction with delegate strategy [0.650ms]
per-agent compaction: accepts valid > compaction with checkpoint strategy [0.570ms]
per-agent compaction: accepts valid > compaction with auto_resume_timeout_sec: null [0.490ms]
per-agent compaction: accepts valid > compaction with always_keep predicates [0.560ms]
per-agent compaction: accepts valid > minimal compaction (no fields = all defaults) [0.450ms]
per-agent compaction: accepts valid > compaction on subagent [0.790ms]
per-agent compaction: rejects invalid > invalid strategy rejected [0.510ms]
per-agent compaction: rejects invalid > upper_threshold > 1.0 rejected [0.530ms]
per-agent compaction: rejects invalid > lower_threshold < 0 rejected [0.530ms]
per-agent compaction: rejects invalid > unknown field in compaction rejected [0.580ms]
per-agent compaction: rejects invalid > unknown field in summarize sub-block rejected [0.580ms]
per-agent compaction: rejects invalid > summarize model must be a valid alias [0.560ms]
per-agent compaction: rejects invalid > summarize prompt must use URI prefix [0.540ms]
per-agent compaction: rejects invalid > delegate fallback_strategy rejects checkpoint [0.550ms]
per-agent compaction: cross-ref validation > lower_threshold >= upper_threshold → error [0.120ms]
per-agent compaction: cross-ref validation > lower_threshold == upper_threshold → error [0.060ms]
per-agent compaction: cross-ref validation > valid threshold ordering → no error [0.030ms]
per-agent compaction: cross-ref validation > default thresholds (omitted) → no error [0.030ms]
per-agent compaction: cross-ref validation > strategy summarize without summarize block → error [0.040ms]
per-agent compaction: cross-ref validation > strategy delegate without delegate block → error [0.040ms]
per-agent compaction: cross-ref validation > delegate.plugin referencing existing plugin → no error [0.050ms]
per-agent compaction: cross-ref validation > delegate.plugin referencing missing plugin → cross_reference error [0.050ms]
per-agent compaction: cross-ref validation > delegate.plugin with no plugins block → cross_reference error [0.040ms]
per-agent compaction: cross-ref validation > strategy drop with summarize block → no cross-ref error (extra fields ok) [0.030ms]
round-trip integration > full agent with plugins + compaction + subagents [1.26ms]
DEFAULT_ROOT_TOOLS > contains 18 tools across 9 namespaces [0.030ms]
DEFAULT_ROOT_TOOLS > covers all expected namespaces [0.090ms]
DEFAULT_ROOT_TOOLS > has no duplicates [0.030ms]
DEFAULT_ROOT_TOOLS > every entry matches naming convention (dotted or singleton) [0.100ms]
DEFAULT_ENABLED_TOOLS > contains exactly 5 kaged.* tools [0.020ms]
DEFAULT_ENABLED_TOOLS > all entries are in kaged namespace [0.030ms]
DEFAULT_ENABLED_TOOLS > is a subset of DEFAULT_ROOT_TOOLS [0.030ms]
DEFAULT_ENABLED_TOOLS > non-kaged namespaces are not in the set [0.040ms]
resolveRootTools: no overrides > returns only default-enabled tools from available list [0.140ms]
resolveRootTools: no overrides > returns empty when no available tools are default-enabled [0.020ms]
resolveRootTools: no overrides > preserves input order of enabled tools [0.020ms]
resolveRootTools: no overrides > returns empty array for empty available list [0.020ms]
resolveRootTools: no overrides > returns all kaged.* when full DEFAULT_ROOT_TOOLS provided [0.040ms]
resolveRootTools: single layer opt-in > enabled: true opts in a disabled-by-default tool [0.160ms]
resolveRootTools: single layer opt-in > null disables a default-enabled tool [0.040ms]
resolveRootTools: single layer opt-in > enabled: false disables a default-enabled tool [0.030ms]
resolveRootTools: single layer opt-in > enabled: true on already-enabled tool is a no-op [0.040ms]
resolveRootTools: single layer opt-in > empty object has no effect [0.030ms]
resolveRootTools: single layer opt-in > overrides for unknown tools are ignored [0.020ms]
resolveRootTools: single layer opt-in > multiple tools enabled in one layer [0.030ms]
resolveRootTools: layered overrides > later layer overrides earlier: operator enables, project disables [0.040ms]
resolveRootTools: layered overrides > later layer overrides earlier: operator disables default, project re-enables [0.040ms]
resolveRootTools: layered overrides > operator enables, project has empty object = stays enabled [0.030ms]
resolveRootTools: layered overrides > operator enables disabled-by-default, project disables default-enabled [0.060ms]
resolveRootTools: layered overrides > non-overlapping layers compose correctly [0.040ms]
compileProjectDsl: resolvedRootTools > resolvedRootTools is null when availableTools not provided [0.900ms]
compileProjectDsl: resolvedRootTools > resolvedRootTools returns only default-enabled tools when no overrides [0.590ms]
compileProjectDsl: resolvedRootTools > operator overrides can enable disabled-by-default tools [0.610ms]
compileProjectDsl: resolvedRootTools > operator overrides can disable default-enabled tools [0.550ms]
compileProjectDsl: resolvedRootTools > DSL primary.tools applied as second layer [0.640ms]
compileProjectDsl: resolvedRootTools > DSL overrides take precedence over operator overrides [0.640ms]
compileProjectDsl: resolvedRootTools > operator disables + DSL re-enables = tool is enabled [0.570ms]
compileProjectDsl: resolvedRootTools > materialized tools reflect default-disabled state [0.540ms]
compileProjectDsl: recursive tool materialization > inline subagent gets materialized tools with nothing enabled by default [0.900ms]
compileProjectDsl: recursive tool materialization > inline subagent tools opt-in via its own tools block [0.940ms]
compileProjectDsl: recursive tool materialization > deeply nested subagent gets materialized tools [1.22ms]
compileProjectDsl: recursive tool materialization > root agent still gets kaged.* enabled by default [0.850ms]
compileProjectDsl: recursive tool materialization > operator overrides apply to subagents too [0.950ms]
compileProjectDsl: recursive tool materialization > no materialization when availableTools not provided [0.830ms]
project references: accepts valid > minimal project reference (path only) [1.21ms]
project references: accepts valid > project reference with name override [0.810ms]
project references: accepts valid > project reference with description override [0.770ms]
project references: accepts valid > project reference with overrides block (opaque to parser) [0.830ms]
project references: accepts valid > project reference with all four fields [0.810ms]
project references: accepts valid > multiple project references coexist [1.29ms]
project references: accepts valid > project reference coexists with regular subagent [1.16ms]
project references: accepts valid > project reference with nested deeper path [0.690ms]
project references: rejects invalid > config:/ scheme is rejected [0.800ms]
project references: rejects invalid > git:/ scheme is rejected (deferred) [1.45ms]
project references: rejects invalid > https:/ scheme is rejected (deferred) [0.690ms]
project references: rejects invalid > file:/ scheme is rejected [0.690ms]
project references: rejects invalid > naked path (no prefix) — parser treats as AgentSpec and fails [0.690ms]
project references: rejects invalid > '..' escape in path is rejected [0.660ms]
project references: rejects invalid > empty path portion is rejected [0.720ms]
project references: rejects invalid > double-slash (project://) is rejected [0.720ms]
project references: rejects invalid > mixed shape: path: + cage: is rejected [0.830ms]
project references: rejects invalid > mixed shape: path: + model: is rejected [0.740ms]
project references: rejects invalid > mixed shape: path: + system_prompt: is rejected [0.740ms]
project references: rejects invalid > unknown field on project reference is rejected [0.730ms]
project references: rejects invalid > name override violating subagent-name pattern is rejected [0.700ms]
project references: rejects invalid > name override using reserved name is rejected [1.95ms]
project references: rejects invalid > description exceeding 280 chars is rejected [0.740ms]
project references: rejects invalid > overrides containing 'version' is rejected [0.710ms]
project references: rejects invalid > overrides containing 'project' is rejected [0.700ms]
project references: rejects invalid > overrides is not a plain object (string) — rejected [0.690ms]
project references: cross-reference validation > a project-ref's `name:` override colliding with another map key is an error [1.02ms]
project references: cross-reference validation > two project-refs whose `name:` overrides match each other is an error [0.870ms]
project references: cross-reference validation > two project-refs at distinct map keys without name-collision validate [0.860ms]
project references: cross-reference validation > a project-ref's `name:` matching its own map key is fine (redundant but valid) [0.670ms]
project references: warnings > project references do not produce cage:disabled warnings [0.650ms]
project references: warnings > cage:disabled warning still fires on adjacent regular subagent [0.960ms]
project references: type guard > isProjectReference correctly discriminates [1.10ms]
PromptPathSchema: accepts valid > single prefixed path [1.64ms]
PromptPathSchema: accepts valid > single config:/ path [0.060ms]
PromptPathSchema: accepts valid > array of one path [0.070ms]
PromptPathSchema: accepts valid > array of multiple paths [0.050ms]
PromptPathSchema: accepts valid > mixed project:/ and config:/ in array [0.030ms]
PromptPathSchema: rejects invalid > empty string [0.090ms]
PromptPathSchema: rejects invalid > naked path (no URI prefix) [0.030ms]
PromptPathSchema: rejects invalid > empty array [0.040ms]
PromptPathSchema: rejects invalid > array with naked path [0.040ms]
PromptPathSchema: rejects invalid > array with .. escape [0.030ms]
PromptPathSchema: rejects invalid > number is rejected [0.060ms]
PromptPathSchema: rejects invalid > array with empty string entry [0.030ms]
normalizePromptPath > string becomes one-element array [0.040ms]
normalizePromptPath > array passes through unchanged [0.020ms]
composePromptContents > single entry is trimmed [0.050ms]
composePromptContents > multiple entries joined with blank line [0.020ms]
composePromptContents > entries are trimmed before joining [0.020ms]
composePromptContents > empty array yields empty string [0.010ms]
composePromptContents > single entry array — no double newline [0.020ms]
composePromptContents > three entries produce two blank-line joins [0.020ms]
DSL round-trip: compound prompts > primary system_prompt accepts string (backwards compat) [0.660ms]
DSL round-trip: compound prompts > primary system_prompt accepts array [0.490ms]
DSL round-trip: compound prompts > subagent system_prompt accepts array [0.740ms]
DSL round-trip: compound prompts > workflow step prompt accepts array [0.750ms]
DSL round-trip: compound prompts > compaction summarize prompt accepts array [0.510ms]
DSL round-trip: compound prompts > compaction summarize prompt accepts single string [0.440ms]
DSL round-trip: compound prompts > rejects naked path in system_prompt array [0.470ms]
DSL round-trip: compound prompts > rejects empty array for system_prompt [0.430ms]
ProjectGitRootSchema > accepts project:/ (project root) [0.090ms]
ProjectGitRootSchema > accepts project:/packages/foo [0.050ms]
ProjectGitRootSchema > accepts project:/models.dev [0.030ms]
ProjectGitRootSchema > rejects config:/ scheme (not accepted in MVP) [0.050ms]
ProjectGitRootSchema > rejects absolute host path [0.030ms]
ProjectGitRootSchema > rejects bare relative path [0.030ms]
ProjectGitRootSchema > rejects ../ traversal [0.020ms]
ProjectGitRootSchema > rejects mid-path ../ traversal [0.030ms]
ProjectGitRootSchema > rejects empty string [0.050ms]
ProjectGitRootSchema > rejects git:/ scheme (not the same as the git: DSL field) [0.030ms]
ProjectDslSchema git field — default behavior > omitted git field defaults to [project:/] [0.660ms]
ProjectDslSchema git field — default behavior > explicit git: [project:/] is accepted [0.470ms]
ProjectDslSchema git field — default behavior > explicit multi-root git list is accepted [0.460ms]
ProjectDslSchema git field — rejection > empty git list is rejected [0.520ms]
ProjectDslSchema git field — rejection > config:/ root is rejected [0.420ms]
ProjectDslSchema git field — rejection > absolute path root is rejected [0.430ms]
ProjectDslSchema git field — rejection > > 32 roots is rejected [0.740ms]
ProjectDslSchema git field — rejection > ../ traversal in a root is rejected [0.420ms]
ProjectDslSchema git field — strict object > unknown field git_foo is rejected (strict) [0.420ms]
ProjectDslSchema git field — strict object > did-you-mean hint includes git for git_x typo [0.420ms]
parseSkillFile > parse valid file with all fields [0.650ms]
parseSkillFile > parse file without name field — uses fallback [0.130ms]
parseSkillFile > reject missing description [0.310ms]
parseSkillFile > reject empty description [0.120ms]
parseSkillFile > reject description over 280 chars [0.180ms]
parseSkillFile > accept description exactly 280 chars [0.130ms]
parseSkillFile > handle unknown frontmatter fields [0.130ms]
parseSkillFile > handle file without frontmatter [0.060ms]
parseSkillFile > handle empty body [0.080ms]
parseSkillFile > handle malformed YAML frontmatter [0.230ms]
parseSkillFile > reject invalid name pattern [0.160ms]
parseSkillFile > frontmatter name overrides fallback [0.110ms]
parseSkillFile > globs parsed as array [0.160ms]
skillGlobMatch > wildcard matches everything [0.110ms]
skillGlobMatch > exact match [0.070ms]
skillGlobMatch > prefix glob [0.050ms]
skillGlobMatch > multiple patterns — any match wins [0.030ms]
skillGlobMatch > empty patterns — no match [0.010ms]
discoverSkills > discover single skill [0.930ms]
discoverSkills > discover multiple skills — sorted alphabetically [0.770ms]
discoverSkills > no skills directory — returns empty [0.110ms]
discoverSkills > missing SKILL.md — warning + skip [0.120ms]
discoverSkills > parse error — warning + skip [0.370ms]
discoverSkills > duplicate skill name — warning + skip duplicate [0.360ms]
discoverSkills > glob filter — only matching skills [0.450ms]
discoverSkills > non-directory entry is skipped [0.230ms]
buildSkillCatalog > returns null for empty array [0.060ms]
buildSkillCatalog > builds catalog with skills [0.070ms]
buildSkillCatalog > excludes hidden skills [0.040ms]
formatSkillActivation > formats with body and path hint [0.080ms]
formatSkillActivation > includes skill_resources when resources provided [0.040ms]
formatSkillActivation > omits skill_resources when no resources [0.030ms]
DSL skills field (ADR-0044) > skills defaults to ['*'] when omitted [0.750ms]
DSL skills field (ADR-0044) > skills accepts explicit glob patterns [0.530ms]
DSL skills field (ADR-0044) > skills accepts ['*'] explicitly [0.490ms]
DSL skills field (ADR-0044) > skills accepts empty array [0.420ms]
DSL skills field (ADR-0044) > skills on subagent [0.810ms]
DSL skills field (ADR-0044) > skills rejects non-string array elements [0.500ms]

Mentioned in

Type Document
adr ADR-0006: Project DSL is YAML with JSON Schema + Zod validation
adr ADR-0008: Plugins are subprocesses over JSON-RPC on stdio
adr ADR-0011: Projects are portable; operator-local concerns live in local config
adr ADR-0013: Observability substrate is Langfuse, self-hosted, optional
adr ADR-0018: Guest access to projects is granted via per-project permission sets, not project DSL
adr ADR-0019: Workflows are operator-authored, parameterised DSL artifacts agents invoke
adr ADR-0022: Agents are recursive; tools and cage are per-agent
adr ADR-0023: Project-plugin lifecycle hooks, per-agent declaration, isolation as a core principle
adr ADR-0024: Context compaction is kaged-owned, layered, observable, and operator-tunable
adr ADR-0025: Typecheck orchestrates per-package; root tsc is a marker
adr ADR-0032: Monaco Editor as the code editor for kaged UI
adr ADR-0033: Tool dot-namespace convention
adr ADR-0034: Sessions bind to one issue; the issue owns the agent's todos and drives closure
adr ADR-0037 — Compound prompts: every prompt field is string | string[]
adr ADR-0038 — Workflows: mandatory steps, no root prompt, per-level model override
adr ADR-0042: Package distribution, CI, and the release pipeline
adr ADR-0043: MCP as a tool source
adr ADR-0044: Skills — declarative agent capabilities as prompt modules
adr ADR-0045: Project wiki — markdown knowledge base as a DSL surface
adr ADR-0048 — Workflows: branching, loops, logic steps, and parameterised tasks
spec Spec: Agent Tooling
spec Spec: Agent Harness
spec Spec: Daemon
spec Spec: Federated Project Configuration
spec Spec: HTTP + WebSocket API
spec Spec: Local config
spec Spec: Plugin Host
spec Spec: Project DSL
spec Release pipeline
spec Spec: Sandbox
spec Spec: Session Manager
spec Spec: Task Runner
spec Spec: Workflows