@kaged/dsl

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

13
source files
6
test files
~8.1k
lines
✓ 333 pass
tests
pass
typecheck
clean
lint

Test results 333

compileProjectDsl: single-level resolution > resolves one project reference and attaches _compiled [23.98ms]
compileProjectDsl: single-level resolution > preserves declared name/description/overrides alongside _compiled [6.02ms]
compileProjectDsl: single-level resolution > regular subagents pass through unchanged [11.04ms]
compileProjectDsl: single-level resolution > no project references: returns input unchanged [1.61ms]
compileProjectDsl: single-level resolution > hasProjectReferences true when any ref exists [3.50ms]
compileProjectDsl: recursion > A → B → C with paths relative to each parent's root [5.09ms]
compileProjectDsl: recursion > silo boundary: nested ref at project:/data is NOT resolved against parent root [7.00ms]
compileProjectDsl: cycle detection > unbounded chain is blocked at the depth limit [5.79ms]
compileProjectDsl: cycle detection > diamond (A → B and A → C, pointing to distinct D's) is NOT flagged [11.09ms]
compileProjectDsl: depth limit > aborts at the default depth limit (16) [26.07ms]
compileProjectDsl: depth limit > custom maxDepth=2 stops at depth 2 [9.57ms]
compileProjectDsl: depth limit > depth equal to limit is permitted [5.29ms]
compileProjectDsl: overrides > simple top-level override of primary.model [3.15ms]
compileProjectDsl: overrides > nested .local.yaml is applied BEFORE the parent's overrides [6.12ms]
compileProjectDsl: failure modes > missing nested project.yaml yields nested_project_missing diagnostic [1.57ms]
compileProjectDsl: failure modes > invalid nested project.yaml yields a compile diagnostic [3.85ms]
compileProjectDsl: failure modes > diagnostic path traces to the offending map key [3.36ms]
compileProjectDsl: failure modes > warnings from nested cage:disabled bubble up with map-key prefix [7.73ms]
compileProjectDsl: injectable readFile > uses provided readFile in place of node:fs [1.75ms]
resolveCompaction > returns parent when child is undefined [0.050ms]
resolveCompaction > child fields override parent fields [0.060ms]
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.050ms]
resolveCompaction > all child fields specified produces fully overridden result [0.060ms]
compileProjectDsl: compaction materialization > agent with no compaction gets DEFAULT_COMPACTION materialized [1.13ms]
compileProjectDsl: compaction materialization > primary compaction is materialized with resolved defaults [1.67ms]
compileProjectDsl: compaction materialization > subagent inherits parent compaction when unset [2.20ms]
compileProjectDsl: compaction materialization > subagent overrides specific fields, inherits the rest [2.11ms]
compileProjectDsl: compaction materialization > three-level inheritance: grandchild inherits from child override [5.71ms]
compileProjectDsl: compaction materialization > project-reference boundary resets compaction to default [2.70ms]
compileProjectDsl: compaction materialization > nested project with its own compaction uses that, not parent's [2.49ms]
compileProjectDsl: compaction materialization > plugins pass through unchanged during compilation [2.02ms]
DEFAULT_COMPACTION defaults (ADR-0024 amendment §7) > includes summarize block with default prompt path [0.040ms]
DEFAULT_COMPACTION defaults (ADR-0024 amendment §7) > summarize block omits model (agent uses its own) [0.030ms]
CompactionSummarizeSchema: optional model and prompt > accepts summarize block with prompt only (no model) [0.660ms]
CompactionSummarizeSchema: optional model and prompt > accepts summarize block with model only (no prompt) [0.660ms]
CompactionSummarizeSchema: optional model and prompt > accepts summarize block with no model and no prompt [0.710ms]
worked examples > minimal.yaml validates successfully [1.14ms]
worked examples > single-subagent.yaml validates successfully [2.25ms]
worked examples > multi-subagent.yaml validates successfully [3.07ms]
worked examples > network-allowlist.yaml validates successfully [3.09ms]
worked examples > with-plugins.yaml validates successfully [2.29ms]
worked examples > insecure.yaml validates successfully [2.26ms]
worked examples > portable.yaml validates successfully [2.77ms]
worked examples > insecure.yaml emits cage:disabled warning [2.17ms]
worked examples > minimal.yaml has no subagents on primary [0.760ms]
worked examples > with-plugins.yaml has plugins [1.95ms]
schema: accepts valid > minimal valid project [0.650ms]
schema: accepts valid > project with description [0.690ms]
schema: accepts valid > primary with parameters [0.740ms]
schema: accepts valid > subagent with cage: disabled is valid [1.16ms]
schema: accepts valid > cage with all optional fields [1.62ms]
schema: accepts valid > model alias: various valid names [2.38ms]
schema: accepts valid > project slug: various valid slugs [1.79ms]
schema: accepts valid > system_prompt: URI-prefixed paths accepted [2.12ms]
schema: accepts valid > system_prompt: naked path rejected [1.00ms]
schema: accepts valid > plugins with all fields [0.910ms]
schema: accepts valid > primary with per-agent tools [0.920ms]
schema: rejects invalid > missing version [0.670ms]
schema: rejects invalid > version: 2 is rejected [0.720ms]
schema: rejects invalid > version: "1" (string) is rejected [0.670ms]
schema: rejects invalid > missing project [0.640ms]
schema: rejects invalid > missing primary [0.510ms]
schema: rejects invalid > unknown top-level field [0.820ms]
schema: rejects invalid > model alias with colon is rejected [0.710ms]
schema: rejects invalid > reserved model alias rejected [3.14ms]
schema: rejects invalid > reserved subagent name rejected [3.44ms]
schema: rejects invalid > absolute path in system_prompt rejected [0.720ms]
schema: rejects invalid > path with .. escape rejected [0.670ms]
schema: rejects invalid > absolute path in cage.fs rejected [1.42ms]
schema: rejects invalid > description over 280 chars rejected [0.760ms]
schema: rejects invalid > description at 280 chars accepted [0.670ms]
schema: rejects invalid > more than 64 subagents rejected [24.79ms]
schema: rejects invalid > cage value that is neither object nor disabled [1.37ms]
schema: rejects invalid > cage.state invalid enum value [1.23ms]
schema: rejects invalid > cage.seccomp invalid enum value [4.75ms]
schema: rejects invalid > cage.limits.memory_mb below minimum [1.01ms]
schema: rejects invalid > mount.mode invalid value [0.890ms]
schema: rejects invalid > YAML syntax error throws DslError [0.560ms]
schema: rejects invalid > top-level subagents key rejected (ADR-0022) [0.610ms]
schema: rejects invalid > top-level interconnect key rejected (ADR-0022) [0.590ms]
schema: rejects invalid > top-level cage_defaults key rejected (ADR-0022) [0.570ms]
schema: rejects invalid > top-level tools key rejected (ADR-0022) [0.520ms]
cross-reference validation > root agent cage must be disabled [0.540ms]
cross-reference validation > principal_scope: root-only tool on non-root agent rejected [0.870ms]
cross-reference validation > principal_scope: root-only tool on root agent accepted [0.480ms]
cross-reference validation > tool-name collision: project-ref name override matches sibling map key [1.01ms]
cross-reference validation > no errors when subagents have unique names [0.860ms]
error messages > errors include doc links [0.460ms]
error messages > unknown field includes did-you-mean [0.430ms]
error messages > DslError has diagnostics array [0.490ms]
error messages > YAML syntax error has line info [0.840ms]
error messages > file path appears in diagnostic when provided [0.420ms]
utilities > parse() returns data + warnings separately [0.440ms]
utilities > validateCrossRefs returns empty for valid DSL [0.420ms]
tasks block: accepts valid > project without tasks is valid [0.430ms]
tasks block: accepts valid > project with empty tasks map is valid [0.510ms]
tasks block: accepts valid > single named task with all fields [0.780ms]
tasks block: accepts valid > minimal task (command only) [0.520ms]
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.550ms]
tasks block: accepts valid > task name with hyphens and underscores [1.39ms]
tasks block: rejects invalid > reserved task name: adhoc [0.490ms]
tasks block: rejects invalid > reserved task name: all [0.530ms]
tasks block: rejects invalid > reserved task name: new [0.500ms]
tasks block: rejects invalid > task name starting with digit rejected [0.500ms]
tasks block: rejects invalid > task name with uppercase rejected [0.490ms]
tasks block: rejects invalid > single-char task name rejected [0.540ms]
tasks block: rejects invalid > task missing command rejected [0.500ms]
tasks block: rejects invalid > task with empty command rejected [0.540ms]
tasks block: rejects invalid > task description over 280 chars rejected [0.610ms]
tasks block: rejects invalid > task with absolute cwd rejected [0.530ms]
tasks block: rejects invalid > task with .. cwd rejected [0.530ms]
tasks block: rejects invalid > task with unknown field rejected (strict mode) [0.580ms]
tasks block: rejects invalid > more than 64 tasks rejected [2.40ms]
tasks block: rejects invalid > task env with non-string value rejected [0.540ms]
tasks block: cross-reference validation > unique task names pass validation [0.510ms]
workflows block: accepts valid > project without workflows is valid [0.400ms]
workflows block: accepts valid > project with empty workflows map is valid [0.470ms]
workflows block: accepts valid > single workflow with all fields [1.71ms]
workflows block: accepts valid > minimal workflow (required fields only) [0.700ms]
workflows block: accepts valid > workflow name with dots, hyphens, underscores [2.22ms]
workflows block: accepts valid > multiple workflows [0.900ms]
workflows block: accepts valid > workflow with empty inputs map [0.560ms]
workflows block: accepts valid > input required defaults to true [0.620ms]
workflows block: rejects invalid > reserved workflow name: adhoc [0.590ms]
workflows block: rejects invalid > reserved workflow name: all [0.600ms]
workflows block: rejects invalid > workflow name starting with digit rejected [0.610ms]
workflows block: rejects invalid > workflow name with uppercase rejected [0.570ms]
workflows block: rejects invalid > single-char workflow name rejected [0.570ms]
workflows block: rejects invalid > workflow missing description rejected [0.550ms]
workflows block: rejects invalid > workflow missing system_prompt rejected [0.570ms]
workflows block: rejects invalid > workflow missing inputs rejected [0.560ms]
workflows block: rejects invalid > workflow missing tools rejected [0.530ms]
workflows block: rejects invalid > workflow description over 280 chars rejected [0.630ms]
workflows block: rejects invalid > workflow with naked system_prompt path rejected [0.610ms]
workflows block: rejects invalid > workflow input with invalid type rejected [0.640ms]
workflows block: rejects invalid > workflow input missing type rejected [0.670ms]
workflows block: rejects invalid > workflow with unknown field rejected (strict) [0.680ms]
workflows block: rejects invalid > workflow input with unknown field rejected (strict) [0.700ms]
workflows block: rejects invalid > workflow tools with unknown field rejected (strict) [0.630ms]
workflows block: rejects invalid > workflow invokable_by with invalid value rejected [0.660ms]
workflows block: rejects invalid > workflow timeout_seconds zero rejected [0.650ms]
workflows block: rejects invalid > more than 64 workflows rejected [9.22ms]
deepMergeDsl > scalars: overlay replaces base [2.66ms]
deepMergeDsl > absent keys: base value passes through [0.070ms]
deepMergeDsl > null: removes the key (nullification) [0.040ms]
deepMergeDsl > objects: deep-merge recursively [0.040ms]
deepMergeDsl > objects: deep-merge multiple levels [0.040ms]
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.040ms]
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.070ms]
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.020ms]
parseUri > rejects naked path [0.060ms]
parseUri > rejects absolute path [0.030ms]
parseUri > rejects empty string [0.020ms]
parseUri > rejects unknown prefix [0.020ms]
parseUri > double-slash: second slash becomes part of path [0.040ms]
parseUri > rejects .. escape at start [0.020ms]
parseUri > rejects .. escape in middle [0.030ms]
parseUri > rejects bare .. path [0.020ms]
parseUri > allows segments containing .. in names [0.020ms]
resolveUri > project:/ resolves to project root [0.060ms]
resolveUri > config:/ resolves to .kaged/ under project root [0.020ms]
resolveUri > project:/ single file [0.020ms]
resolveUri > config:/ deeply nested [0.020ms]
resolveUri > throws on invalid URI [0.020ms]
shadowPath > config:/ with extension inserts .local before ext [0.070ms]
shadowPath > config:/ with .json extension [0.020ms]
shadowPath > config:/ with .yaml extension [0.010ms]
shadowPath > config:/ without extension appends .local [0.030ms]
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.820ms]
loadProjectDsl > overlay merges: overrides primary.model [0.580ms]
loadProjectDsl > overlay merges: adds description [0.500ms]
loadProjectDsl > overlay rejects version override [0.620ms]
loadProjectDsl > overlay rejects project override [0.460ms]
loadProjectDsl > overlay merges: deep-merges primary parameters [0.580ms]
loadProjectDsl > overlay merges: subagents record deep-merges (empty overlay preserves base) [0.960ms]
loadProjectDsl > overlay merges: subagent nullified via null value [0.640ms]
loadProjectDsl > overlay YAML syntax error throws DslError [0.490ms]
loadProjectDsl > base YAML syntax error throws DslError [0.240ms]
loadProjectDsl > merged result that fails schema throws DslError [0.540ms]
loadProjectDsl > overlay file path appears in forbidden-key error [0.260ms]
loadProjectDsl > overlay with cage:disabled produces warning [0.860ms]
PrefixedPathSchema integration > project:/ in system_prompt accepted [0.390ms]
PrefixedPathSchema integration > config:/ in system_prompt accepted [0.380ms]
PrefixedPathSchema integration > naked path in system_prompt rejected [0.460ms]
PrefixedPathSchema integration > project:/ in task cwd accepted [0.510ms]
PrefixedPathSchema integration > naked path in task cwd rejected [0.530ms]
ToolOverrideSchema integration > tools with overrides accepted [0.550ms]
ToolOverrideSchema integration > tools with null value (disable) accepted [0.490ms]
ToolOverrideSchema integration > tools with parameters accepted [0.470ms]
ToolOverrideSchema integration > project without tools is valid [0.460ms]
ToolOverrideSchema integration > overlay merges tools [0.550ms]
per-agent plugins: accepts valid > primary with a single plugin override (registry + per-agent) [1.11ms]
per-agent plugins: accepts valid > primary with enabled: true override [0.610ms]
per-agent plugins: accepts valid > minimal per-agent override (only enabled) [0.550ms]
per-agent plugins: accepts valid > multiple plugins on same agent [0.700ms]
per-agent plugins: accepts valid > pre_compact hook accepted [0.580ms]
per-agent plugins: accepts valid > subagent with its own plugin override [0.880ms]
per-agent plugins: accepts valid > registry entry with source field [0.450ms]
per-agent plugins: accepts valid > registry entry with git: source [0.440ms]
per-agent plugins: accepts valid > registry entry with project: source [0.480ms]
per-agent plugins: accepts valid > registry entry with config: source [0.430ms]
per-agent plugins: rejects invalid > unknown field in per-agent plugin declaration [0.580ms]
per-agent plugins: rejects invalid > invalid hook name rejected [0.520ms]
per-agent plugins: rejects invalid > plugin slot name starting with digit rejected [0.480ms]
per-agent plugins: rejects invalid > plugin slot name with uppercase rejected [0.460ms]
per-agent plugins: rejects invalid > more than 16 plugins per agent rejected [1.24ms]
per-agent plugins: rejects invalid > registry entry without package rejected [0.500ms]
per-agent plugins: rejects invalid > invalid source prefix rejected [0.490ms]
per-agent plugins: rejects invalid > per-agent package field rejected (belongs in registry) [0.510ms]
per-agent plugins: rejects invalid > per-agent source field rejected (belongs in registry) [0.490ms]
per-agent plugins: cross-ref validation > per-agent slot not in project registry → error [0.120ms]
per-agent plugins: cross-ref validation > per-agent slot in project registry → no error [0.030ms]
per-agent plugins: cross-ref validation > subagent per-agent slot not in project registry → error [0.070ms]
per-agent plugins: cross-ref validation > primary-only hooks on subagent → warning [0.070ms]
per-agent plugins: cross-ref validation > pre_compact on subagent → no warning [0.040ms]
per-agent plugins: cross-ref validation > primary-only hooks on root agent → no warning [0.030ms]
per-agent compaction: accepts valid > compaction with drop strategy (default) [0.470ms]
per-agent compaction: accepts valid > compaction with summarize strategy [0.500ms]
per-agent compaction: accepts valid > compaction with delegate strategy [0.590ms]
per-agent compaction: accepts valid > compaction with checkpoint strategy [0.490ms]
per-agent compaction: accepts valid > compaction with auto_resume_timeout_sec: null [0.440ms]
per-agent compaction: accepts valid > compaction with always_keep predicates [0.480ms]
per-agent compaction: accepts valid > minimal compaction (no fields = all defaults) [0.410ms]
per-agent compaction: accepts valid > compaction on subagent [0.650ms]
per-agent compaction: rejects invalid > invalid strategy rejected [0.460ms]
per-agent compaction: rejects invalid > upper_threshold > 1.0 rejected [0.470ms]
per-agent compaction: rejects invalid > lower_threshold < 0 rejected [0.510ms]
per-agent compaction: rejects invalid > unknown field in compaction rejected [0.540ms]
per-agent compaction: rejects invalid > unknown field in summarize sub-block rejected [0.500ms]
per-agent compaction: rejects invalid > summarize model must be a valid alias [0.480ms]
per-agent compaction: rejects invalid > summarize prompt must use URI prefix [0.480ms]
per-agent compaction: rejects invalid > delegate fallback_strategy rejects checkpoint [0.450ms]
per-agent compaction: cross-ref validation > lower_threshold >= upper_threshold → error [0.100ms]
per-agent compaction: cross-ref validation > lower_threshold == upper_threshold → error [0.050ms]
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.020ms]
per-agent compaction: cross-ref validation > strategy summarize without summarize block → error [0.030ms]
per-agent compaction: cross-ref validation > strategy delegate without delegate block → error [0.030ms]
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.060ms]
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.04ms]
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.090ms]
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.030ms]
resolveRootTools: no overrides > returns only default-enabled tools from available list [0.110ms]
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.150ms]
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.030ms]
resolveRootTools: single layer opt-in > empty object has no effect [0.040ms]
resolveRootTools: single layer opt-in > overrides for unknown tools are ignored [0.030ms]
resolveRootTools: single layer opt-in > multiple tools enabled in one layer [0.050ms]
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.030ms]
resolveRootTools: layered overrides > operator enables, project has empty object = stays enabled [0.040ms]
resolveRootTools: layered overrides > operator enables disabled-by-default, project disables default-enabled [0.050ms]
resolveRootTools: layered overrides > non-overlapping layers compose correctly [0.060ms]
compileProjectDsl: resolvedRootTools > resolvedRootTools is null when availableTools not provided [0.810ms]
compileProjectDsl: resolvedRootTools > resolvedRootTools returns only default-enabled tools when no overrides [0.570ms]
compileProjectDsl: resolvedRootTools > operator overrides can enable disabled-by-default tools [0.600ms]
compileProjectDsl: resolvedRootTools > operator overrides can disable default-enabled tools [0.550ms]
compileProjectDsl: resolvedRootTools > DSL primary.tools applied as second layer [0.600ms]
compileProjectDsl: resolvedRootTools > DSL overrides take precedence over operator overrides [0.610ms]
compileProjectDsl: resolvedRootTools > operator disables + DSL re-enables = tool is enabled [0.570ms]
compileProjectDsl: resolvedRootTools > materialized tools reflect default-disabled state [0.530ms]
compileProjectDsl: recursive tool materialization > inline subagent gets materialized tools with nothing enabled by default [0.870ms]
compileProjectDsl: recursive tool materialization > inline subagent tools opt-in via its own tools block [0.910ms]
compileProjectDsl: recursive tool materialization > deeply nested subagent gets materialized tools [1.20ms]
compileProjectDsl: recursive tool materialization > root agent still gets kaged.* enabled by default [0.810ms]
compileProjectDsl: recursive tool materialization > operator overrides apply to subagents too [0.940ms]
compileProjectDsl: recursive tool materialization > no materialization when availableTools not provided [0.790ms]
project references: accepts valid > minimal project reference (path only) [1.13ms]
project references: accepts valid > project reference with name override [0.730ms]
project references: accepts valid > project reference with description override [0.720ms]
project references: accepts valid > project reference with overrides block (opaque to parser) [0.800ms]
project references: accepts valid > project reference with all four fields [0.840ms]
project references: accepts valid > multiple project references coexist [1.25ms]
project references: accepts valid > project reference coexists with regular subagent [0.900ms]
project references: accepts valid > project reference with nested deeper path [0.580ms]
project references: rejects invalid > config:/ scheme is rejected [0.610ms]
project references: rejects invalid > git:/ scheme is rejected (deferred) [0.600ms]
project references: rejects invalid > https:/ scheme is rejected (deferred) [0.600ms]
project references: rejects invalid > file:/ scheme is rejected [0.600ms]
project references: rejects invalid > naked path (no prefix) — parser treats as AgentSpec and fails [0.630ms]
project references: rejects invalid > '..' escape in path is rejected [0.610ms]
project references: rejects invalid > empty path portion is rejected [0.610ms]
project references: rejects invalid > double-slash (project://) is rejected [0.590ms]
project references: rejects invalid > mixed shape: path: + cage: is rejected [0.750ms]
project references: rejects invalid > mixed shape: path: + model: is rejected [0.660ms]
project references: rejects invalid > mixed shape: path: + system_prompt: is rejected [0.720ms]
project references: rejects invalid > unknown field on project reference is rejected [0.750ms]
project references: rejects invalid > name override violating subagent-name pattern is rejected [0.660ms]
project references: rejects invalid > name override using reserved name is rejected [1.82ms]
project references: rejects invalid > description exceeding 280 chars is rejected [0.720ms]
project references: rejects invalid > overrides containing 'version' is rejected [0.660ms]
project references: rejects invalid > overrides containing 'project' is rejected [0.630ms]
project references: rejects invalid > overrides is not a plain object (string) — rejected [0.640ms]
project references: cross-reference validation > a project-ref's `name:` override colliding with another map key is an error [0.920ms]
project references: cross-reference validation > two project-refs whose `name:` overrides match each other is an error [0.820ms]
project references: cross-reference validation > two project-refs at distinct map keys without name-collision validate [0.770ms]
project references: cross-reference validation > a project-ref's `name:` matching its own map key is fine (redundant but valid) [0.600ms]
project references: warnings > project references do not produce cage:disabled warnings [0.590ms]
project references: warnings > cage:disabled warning still fires on adjacent regular subagent [0.840ms]
project references: type guard > isProjectReference correctly discriminates [1.22ms]

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
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 Spec: Sandbox
spec Spec: Session Manager
spec Spec: Task Runner
spec Spec: Workflows