From c2db74ba81e2ca38ccb4d2aba25d88aae6f5a617 Mon Sep 17 00:00:00 2001 From: Jeffrey Phillips Freeman Date: Tue, 10 Mar 2026 00:08:11 -0400 Subject: [PATCH] Docs: Restyled ADR pages --- docs/adr/ADR-001-layered-architecture.md | 90 ++- docs/adr/ADR-002-namespace-system.md | 88 ++- docs/adr/ADR-003-dependency-injection.md | 83 +- docs/adr/ADR-004-data-validation.md | 84 +- docs/adr/ADR-005-technical-stack.md | 96 +-- docs/adr/ADR-006-plan-lifecycle.md | 108 +-- .../ADR-007-decision-tree-and-correction.md | 92 +-- docs/adr/ADR-008-resource-system.md | 104 +-- docs/adr/ADR-009-project-model.md | 84 +- .../ADR-010-actor-and-agent-architecture.md | 108 +-- docs/adr/ADR-011-tool-system.md | 112 +-- docs/adr/ADR-012-skill-system.md | 96 +-- docs/adr/ADR-013-validation-abstraction.md | 84 +- docs/adr/ADR-014-context-management-acms.md | 84 +- docs/adr/ADR-015-sandbox-and-checkpoint.md | 99 +-- docs/adr/ADR-016-invariant-system.md | 87 ++- docs/adr/ADR-017-automation-profiles.md | 84 +- docs/adr/ADR-018-semantic-error-prevention.md | 87 ++- docs/adr/ADR-019-storage-and-persistence.md | 83 +- docs/adr/ADR-020-session-model.md | 83 +- docs/adr/ADR-021-cli-and-output-rendering.md | 79 +- ...ADR-022-langchain-langgraph-integration.md | 91 +-- docs/adr/ADR-023-server-mode.md | 88 ++- docs/adr/ADR-024-configuration-system.md | 84 +- docs/adr/ADR-025-observability-and-logging.md | 79 +- docs/adr/ADR-026-agent-client-protocol.md | 95 +-- docs/adr/ADR-027-language-server-protocol.md | 107 +-- docs/adr/ADR-028-agent-skills-standard.md | 95 +-- docs/adr/ADR-029-model-context-protocol.md | 91 +-- .../ADR-030-skill-abstraction-definition.md | 87 ++- .../ADR-031-actor-abstraction-definition.md | 103 +-- ...-032-jinja2-yaml-template-preprocessing.md | 84 +- .../ADR-033-decision-recording-protocol.md | 99 +-- ...34-decision-tree-versioning-and-history.md | 88 ++- ...R-035-decision-tree-rollback-and-replay.md | 88 ++- ...-036-resource-dag-operational-semantics.md | 95 +-- ...tool-reachability-and-access-projection.md | 91 +-- ...38-cross-mechanism-sandbox-coordination.md | 91 +-- docs/adr/ADR-039-container-resource-types.md | 91 +-- docs/adr/ADR-040-lsp-resource-types.md | 95 +-- docs/adr/ADR-041-safety-profile-extraction.md | 83 +- docs/adr/ADR-042-resource-type-inheritance.md | 91 +-- docs/adr/ADR-043-devcontainer-integration.md | 95 +-- docs/adr/img/adr-workflow.png | Bin 0 -> 10767 bytes docs/adr/index.md | 232 +++--- docs/javascripts/adr-page.js | 84 ++ docs/stylesheets/extra.css | 363 +++++++++ hooks/adr_hooks.py | 724 ++++++++++++++++++ mkdocs.yml | 19 + 49 files changed, 3402 insertions(+), 1946 deletions(-) create mode 100644 docs/adr/img/adr-workflow.png create mode 100644 docs/javascripts/adr-page.js create mode 100644 hooks/adr_hooks.py diff --git a/docs/adr/ADR-001-layered-architecture.md b/docs/adr/ADR-001-layered-architecture.md index e908c11c4..c9ec6ff92 100644 --- a/docs/adr/ADR-001-layered-architecture.md +++ b/docs/adr/ADR-001-layered-architecture.md @@ -1,10 +1,43 @@ -# ADR-001: Layered Architecture - -**Status:** Accepted -**Date:** 2026-02-16 -**Supersedes:** None -**Author(s):** Jeffrey Phillips Freeman -**Approver(s):** Jeffrey Phillips Freeman +--- +adr_number: 1 +title: Layered Architecture +status_history: +- - '2026-02-16' + - Draft + - Jeffrey Phillips Freeman +- - '2026-02-16' + - Proposed + - Jeffrey Phillips Freeman +- - '2026-02-16' + - Accepted + - Jeffrey Phillips Freeman +tier: 1 +authors: +- Jeffrey Phillips Freeman +superseded_by: null +related_adrs: +- number: 3 + title: Dependency Injection + relationship: Provides the composition root that wires components across all four layers +- number: 5 + title: Technical Stack + relationship: Defines the concrete technologies used in each architectural layer +- number: 19 + title: Storage and Persistence + relationship: Implements the Infrastructure Layer's persistence adapters +- number: 22 + title: LangChain/LangGraph Integration + relationship: Implements the Infrastructure Layer's LLM runtime adapters +- number: 26 + title: Agent Client Protocol (ACP) + relationship: Defines the versioned protocol boundary between the Presentation and Application layers; all client-to-backend communication flows through ACP +acceptance: + votes_for: + - voter: Jeffrey Phillips Freeman + comment: Four-layer separation is the right foundation to keep domain logic portable across deployment modes + votes_against: [] + abstentions: [] +--- ## Context @@ -12,6 +45,15 @@ CleverAgents is a complex AI-powered development assistant that must support two The architecture must enforce strict boundaries so that domain logic remains independent of infrastructure choices (which database, which LLM provider, which vector store), and so that the presentation layer (CLI, TUI, REST API) can evolve without affecting core business rules. +## Decision Drivers + +- Must support two deployment modes (local CLI and multi-user server) sharing the same core logic +- Domain logic must remain independent of infrastructure choices (database, LLM provider, vector store) +- Presentation surfaces (CLI, TUI, REST API) must evolve without affecting business rules +- Need strict boundaries between layers to enable independent testing and swappable infrastructure +- System spans multiple complex subsystems (plans, decisions, actors, tools, resources) requiring clear structural decomposition +- Must support CQRS data flow and event-driven observability without entangling concerns + ## Decision CleverAgents adopts a **four-layer architecture** — Presentation, Application, Domain, and Infrastructure — organized according to **hexagonal architecture (ports and adapters)** principles. The architecture incorporates **Command Query Responsibility Segregation (CQRS)** for data flow and an **event-driven** pattern for observability and decoupled side effects. @@ -101,37 +143,3 @@ None — specification-driven requirement. The four-layer hexagonal architecture - **Dependency injection audit**: The DI container configuration is reviewed to ensure all cross-layer dependencies flow through declared providers, not direct imports. - **Architecture tests**: Dedicated test suite verifying layer dependency rules using static analysis (e.g., `import-linter` or custom AST checks). - **Code review**: Pull requests that introduce new cross-layer dependencies require explicit justification. - -## Related ADRs - -| ADR | Title | Relationship | -|-----|-------|-------------| -| [ADR-003](ADR-003-dependency-injection.md) | Dependency Injection | Provides the composition root that wires components across all four layers | -| [ADR-005](ADR-005-technical-stack.md) | Technical Stack | Defines the concrete technologies used in each architectural layer | -| [ADR-019](ADR-019-storage-and-persistence.md) | Storage and Persistence | Implements the Infrastructure Layer's persistence adapters | -| [ADR-022](ADR-022-langchain-langgraph-integration.md) | LangChain/LangGraph Integration | Implements the Infrastructure Layer's LLM runtime adapters | -| [ADR-026](ADR-026-agent-client-protocol.md) | Agent Client Protocol (ACP) | Defines the versioned protocol boundary between the Presentation and Application layers; all client-to-backend communication flows through ACP | - -## Acceptance - -### Votes For - -| Voter | Comment | -|-------|---------| -| Jeffrey Phillips Freeman | Four-layer separation is the right foundation to keep domain logic portable across deployment modes | - -**Total: 1** - -### Votes Against - -| Voter | Comment | -|-------|---------| - -**Total: 0** - -### Abstentions - -| Voter | Comment | -|-------|---------| - -**Total: 0** diff --git a/docs/adr/ADR-002-namespace-system.md b/docs/adr/ADR-002-namespace-system.md index 1a1dc9af6..83ea6015a 100644 --- a/docs/adr/ADR-002-namespace-system.md +++ b/docs/adr/ADR-002-namespace-system.md @@ -1,17 +1,55 @@ -# ADR-002: Namespace System - -**Status:** Accepted -**Date:** 2026-02-16 -**Supersedes:** None -**Author(s):** Jeffrey Phillips Freeman -**Approver(s):** Jeffrey Phillips Freeman - +--- +adr_number: 2 +title: Namespace System +status_history: +- - '2026-02-16' + - Proposed + - Jeffrey Phillips Freeman +- - '2026-02-16' + - Accepted + - Jeffrey Phillips Freeman +tier: 1 +authors: +- Jeffrey Phillips Freeman +superseded_by: null +related_adrs: +- number: 9 + title: Project Model + relationship: Projects are namespace-scoped entities that use the naming convention +- number: 10 + title: Actor and Agent Architecture + relationship: Actors and agents are identified and resolved via namespaced names +- number: 11 + title: Tool System + relationship: Tools use namespaced identifiers for discovery and conflict resolution +- number: 12 + title: Skill System + relationship: Skills use namespaced names and resolve tool name conflicts via qualification +- number: 23 + title: Server Mode + relationship: Server mode introduces server-prefixed namespaces for multi-server resolution +acceptance: + votes_for: + - voter: Jeffrey Phillips Freeman + comment: A universal naming scheme avoids ambiguity and makes entity resolution predictable across all contexts + votes_against: [] + abstentions: [] +--- ## Context CleverAgents manages a wide variety of named entities — actors, tools, skills, resources, resource types, actions, projects, and plans. These entities must be uniquely identifiable, scopeable to different ownership levels (local machine, personal server account, organization), and discoverable across deployment boundaries. Without a uniform naming scheme, entity references would be ambiguous, collision-prone, and incompatible between local and server modes. The system must also support connecting to multiple servers simultaneously and resolving names unambiguously in that context. +## Decision Drivers + +- Entities (actors, tools, skills, resources, projects, plans) must be uniquely identifiable across deployment boundaries +- Must support multiple ownership scopes: local machine, personal server account, and organization +- Local-first development must work with zero server configuration +- System must handle simultaneous connections to multiple servers without name collisions +- Naming scheme must be uniform across all entity types to reduce cognitive overhead +- Transition from local-only to shared/collaborative usage should not require structural migration + ## Decision All named entities in CleverAgents use a universal **namespace-qualified name** format: `[[server:]namespace/]name`. Four namespace types define ownership and storage scope. The `local/` namespace is the default when no namespace is specified. @@ -89,37 +127,3 @@ None — specification-driven requirement. The universal namespace system is a f - **Name format tests**: Unit tests verify that entity name parsing correctly handles all forms (`name`, `namespace/name`, `server:namespace/name`) and rejects malformed inputs. - **Integration tests**: Multi-namespace scenarios (local + server, multiple servers) are exercised in integration test suites. - **Code review**: New entity types must demonstrate they follow the namespace convention before merging. - -## Related ADRs - -| ADR | Title | Relationship | -|-----|-------|-------------| -| [ADR-009](ADR-009-project-model.md) | Project Model | Projects are namespace-scoped entities that use the naming convention | -| [ADR-010](ADR-010-actor-and-agent-architecture.md) | Actor and Agent Architecture | Actors and agents are identified and resolved via namespaced names | -| [ADR-011](ADR-011-tool-system.md) | Tool System | Tools use namespaced identifiers for discovery and conflict resolution | -| [ADR-012](ADR-012-skill-system.md) | Skill System | Skills use namespaced names and resolve tool name conflicts via qualification | -| [ADR-023](ADR-023-server-mode.md) | Server Mode | Server mode introduces server-prefixed namespaces for multi-server resolution | - -## Acceptance - -### Votes For - -| Voter | Comment | -|-------|---------| -| Jeffrey Phillips Freeman | A universal naming scheme avoids ambiguity and makes entity resolution predictable across all contexts | - -**Total: 1** - -### Votes Against - -| Voter | Comment | -|-------|---------| - -**Total: 0** - -### Abstentions - -| Voter | Comment | -|-------|---------| - -**Total: 0** diff --git a/docs/adr/ADR-003-dependency-injection.md b/docs/adr/ADR-003-dependency-injection.md index cae1d4671..72eeca4b8 100644 --- a/docs/adr/ADR-003-dependency-injection.md +++ b/docs/adr/ADR-003-dependency-injection.md @@ -1,17 +1,51 @@ -# ADR-003: Dependency Injection - -**Status:** Accepted -**Date:** 2026-02-16 -**Supersedes:** None -**Author(s):** Jeffrey Phillips Freeman -**Approver(s):** Jeffrey Phillips Freeman - +--- +adr_number: 3 +title: Dependency Injection +status_history: +- - '2026-02-16' + - Proposed + - Jeffrey Phillips Freeman +- - '2026-02-16' + - Accepted + - Jeffrey Phillips Freeman +tier: 1 +authors: +- Jeffrey Phillips Freeman +superseded_by: null +related_adrs: +- number: 1 + title: Layered Architecture + relationship: DI enforces the layered dependency rule by wiring outer-to-inner dependencies +- number: 5 + title: Technical Stack + relationship: Specifies `dependency-injector` as the chosen DI framework +- number: 19 + title: Storage and Persistence + relationship: Repository implementations are injected via the DI container +- number: 22 + title: LangChain/LangGraph Integration + relationship: LLM providers and LangGraph components are registered through the DI container +acceptance: + votes_for: + - voter: Jeffrey Phillips Freeman + comment: A single composition root with declarative containers keeps wiring explicit and testable + votes_against: [] + abstentions: [] +--- ## Context The layered architecture (ADR-001) requires that outer layers depend on inner layers through abstract interfaces, never through concrete implementations. Services in the Application Layer need repositories, LLM providers, indexing backends, and sandbox managers — but must not instantiate them directly. Testing requires replacing real infrastructure with mocks. Runtime reconfiguration (e.g., switching LLM providers or swapping database backends between local and server modes) must be possible without modifying application or domain code. A dependency injection mechanism is needed to wire all components together, enforce the layer boundary rules, and support both production and test configurations. +## Decision Drivers + +- Layered architecture requires outer layers to depend on inner layers through abstract interfaces, never concrete implementations +- Application Layer services need repositories, LLM providers, and sandbox managers without instantiating them directly +- Testing requires replacing real infrastructure with mocks without modifying application or domain code +- Runtime reconfiguration (switching LLM providers or database backends between deployment modes) must not require code changes +- All cross-layer wiring must be explicit and auditable from a single location + ## Decision All service dependencies are wired through a **`DeclarativeContainer`** from the `dependency-injector` library (>= 4.41.0). This container is the single composition root for the entire application. No service instantiates its own dependencies — all are received through constructor injection managed by the container. @@ -88,36 +122,3 @@ The container's `override()` context manager allows swapping providers for indiv - **Import linting**: CI rules verify that `domain` modules do not import from `dependency_injector`. - **Code review**: New services must include their container registration in the same pull request that introduces them. - **Test coverage**: Integration tests verify that the production container configuration resolves all dependencies correctly. Test configurations verify that override mechanisms work as expected. - -## Related ADRs - -| ADR | Title | Relationship | -|-----|-------|-------------| -| [ADR-001](ADR-001-layered-architecture.md) | Layered Architecture | DI enforces the layered dependency rule by wiring outer-to-inner dependencies | -| [ADR-005](ADR-005-technical-stack.md) | Technical Stack | Specifies `dependency-injector` as the chosen DI framework | -| [ADR-019](ADR-019-storage-and-persistence.md) | Storage and Persistence | Repository implementations are injected via the DI container | -| [ADR-022](ADR-022-langchain-langgraph-integration.md) | LangChain/LangGraph Integration | LLM providers and LangGraph components are registered through the DI container | - -## Acceptance - -### Votes For - -| Voter | Comment | -|-------|---------| -| Jeffrey Phillips Freeman | A single composition root with declarative containers keeps wiring explicit and testable | - -**Total: 1** - -### Votes Against - -| Voter | Comment | -|-------|---------| - -**Total: 0** - -### Abstentions - -| Voter | Comment | -|-------|---------| - -**Total: 0** diff --git a/docs/adr/ADR-004-data-validation.md b/docs/adr/ADR-004-data-validation.md index e9e27bdff..4dcbee22b 100644 --- a/docs/adr/ADR-004-data-validation.md +++ b/docs/adr/ADR-004-data-validation.md @@ -1,17 +1,52 @@ -# ADR-004: Data Validation - -**Status:** Accepted -**Date:** 2026-02-16 -**Supersedes:** None -**Author(s):** Jeffrey Phillips Freeman -**Approver(s):** Jeffrey Phillips Freeman - +--- +adr_number: 4 +title: Data Validation +status_history: +- - '2026-02-16' + - Proposed + - Jeffrey Phillips Freeman +- - '2026-02-16' + - Accepted + - Jeffrey Phillips Freeman +tier: 1 +authors: +- Jeffrey Phillips Freeman +superseded_by: null +related_adrs: +- number: 1 + title: Layered Architecture + relationship: Pydantic models enforce Domain Layer contracts at layer boundaries +- number: 5 + title: Technical Stack + relationship: Specifies Pydantic V2 as the chosen validation library +- number: 11 + title: Tool System + relationship: Tool input/output schemas are Pydantic models that generate JSON Schema +- number: 24 + title: Configuration System + relationship: Pydantic Settings powers environment variable loading and config validation +acceptance: + votes_for: + - voter: Jeffrey Phillips Freeman + comment: Pydantic V2 strict mode gives us runtime type safety with minimal boilerplate and native JSON Schema support + votes_against: [] + abstentions: [] +--- ## Context CleverAgents processes data from multiple untrusted or semi-trusted sources: user CLI input, YAML configuration files, LLM-generated tool call arguments, MCP server responses, environment variables, and database records. Every boundary crossing — between layers, between the system and external services, between the user and the application — is an opportunity for invalid data to enter the system and cause subtle downstream failures. The system needs a uniform validation mechanism that provides runtime type checking, schema generation (for tool calling and API contracts), serialization/deserialization, and clear error messages — without requiring developers to write manual validation logic for each data boundary. +## Decision Drivers + +- Data enters from multiple untrusted sources: user CLI input, LLM-generated tool arguments, MCP responses, YAML configs, environment variables +- Every layer boundary crossing is an opportunity for invalid data to cause subtle downstream failures +- Tool-calling protocols require JSON Schema definitions generated from the same models used for validation +- Need a single modeling framework for domain models, configuration, API schemas, and tool definitions to avoid duplication +- Validation error messages must be structured and actionable for CLI display +- Runtime type checking must be enforced without requiring manual validation logic at each boundary + ## Decision All domain models, configuration objects, and API schemas use **Pydantic V2** (>= 2.7.0) for runtime data validation, JSON Schema generation, and serialization. **Pydantic Settings** (>= 2.11.0) extends this to environment variable loading. Pydantic serves as the type-safe data boundary between all layers. @@ -79,36 +114,3 @@ Pydantic handles serialization to and from JSON, YAML (via dict intermediary), a - **Schema drift tests**: Automated tests verify that JSON Schema generated from Pydantic tool models matches the schemas expected by MCP and LangChain tool-calling protocols. - **Validation coverage**: Unit tests exercise validation edge cases — missing required fields, wrong types, out-of-range values, malformed nested objects — for every domain model and configuration object. - **Code review**: New data structures that cross layer boundaries must be Pydantic models. Raw dict usage at boundaries is flagged during review. - -## Related ADRs - -| ADR | Title | Relationship | -|-----|-------|-------------| -| [ADR-001](ADR-001-layered-architecture.md) | Layered Architecture | Pydantic models enforce Domain Layer contracts at layer boundaries | -| [ADR-005](ADR-005-technical-stack.md) | Technical Stack | Specifies Pydantic V2 as the chosen validation library | -| [ADR-011](ADR-011-tool-system.md) | Tool System | Tool input/output schemas are Pydantic models that generate JSON Schema | -| [ADR-024](ADR-024-configuration-system.md) | Configuration System | Pydantic Settings powers environment variable loading and config validation | - -## Acceptance - -### Votes For - -| Voter | Comment | -|-------|---------| -| Jeffrey Phillips Freeman | Pydantic V2 strict mode gives us runtime type safety with minimal boilerplate and native JSON Schema support | - -**Total: 1** - -### Votes Against - -| Voter | Comment | -|-------|---------| - -**Total: 0** - -### Abstentions - -| Voter | Comment | -|-------|---------| - -**Total: 0** diff --git a/docs/adr/ADR-005-technical-stack.md b/docs/adr/ADR-005-technical-stack.md index 26553dafc..69938c576 100644 --- a/docs/adr/ADR-005-technical-stack.md +++ b/docs/adr/ADR-005-technical-stack.md @@ -1,15 +1,59 @@ -# ADR-005: Technical Stack - -**Status:** Accepted -**Date:** 2026-02-16 -**Supersedes:** None -**Author(s):** Jeffrey Phillips Freeman -**Approver(s):** Jeffrey Phillips Freeman - +--- +adr_number: 5 +title: Technical Stack +status_history: +- - '2026-02-16' + - Proposed + - Jeffrey Phillips Freeman +- - '2026-02-16' + - Accepted + - Jeffrey Phillips Freeman +tier: 1 +authors: +- Jeffrey Phillips Freeman +superseded_by: null +related_adrs: +- number: 1 + title: Layered Architecture + relationship: Stack choices are organized according to the four-layer structure +- number: 3 + title: Dependency Injection + relationship: '`dependency-injector` is a core stack choice for service wiring' +- number: 4 + title: Data Validation + relationship: Pydantic V2 is a core stack choice for validation and modeling +- number: 19 + title: Storage and Persistence + relationship: SQLAlchemy and SQLite/PostgreSQL are the chosen persistence stack +- number: 21 + title: CLI and Output Rendering + relationship: Typer and Rich are the chosen CLI stack +- number: 22 + title: LangChain/LangGraph Integration + relationship: LangChain and LangGraph are the chosen LLM orchestration stack +- number: 25 + title: Observability and Logging + relationship: structlog is the chosen logging stack +acceptance: + votes_for: + - voter: Jeffrey Phillips Freeman + comment: This stack balances maturity, ecosystem support, and alignment with our architectural goals + votes_against: [] + abstentions: [] +--- ## Context CleverAgents requires a cohesive technology stack that supports a CLI-first interface, LLM orchestration with multiple providers, structured data persistence, code intelligence indexing (full-text, vector, and graph), reactive event processing, sandboxed execution, and both local and server deployment modes. The stack must be Python-only for consistency and alignment with the LLM ecosystem. Every technology choice must have a clear rationale and defined minimum version. +## Decision Drivers + +- Must be Python-only for consistency and alignment with the LLM ecosystem (LangChain, MCP SDK) +- Requires CLI-first interface, LLM orchestration with multiple providers, and structured data persistence +- Need configurable backends at every infrastructure layer (full-text, vector, graph indexing) swappable via configuration +- Must support both local single-process and multi-user server deployment modes +- Testing stack must cover behavioral (BDD), integration, unit, and property-based testing +- Every technology choice must have a clear rationale and defined minimum version for reproducibility + ## Decision CleverAgents is built on **Python >= 3.13** as the sole implementation language. The stack is organized by functional area, with specific libraries chosen for CLI, LLM runtime, data persistence, indexing, configuration, testing, code quality, infrastructure, and observability. @@ -154,39 +198,3 @@ None — specification-driven requirement. The technical stack is enumerated in - **Vulnerability scanning**: Automated dependency vulnerability scanning (e.g., `pip-audit` or `safety`) runs in CI. - **Build verification**: Docker image builds are tested in CI to catch platform-specific build failures for native extensions. - **Performance benchmarks**: ASV tracks key performance metrics across commits to detect regressions from dependency changes. - -## Related ADRs - -| ADR | Title | Relationship | -|-----|-------|-------------| -| [ADR-001](ADR-001-layered-architecture.md) | Layered Architecture | Stack choices are organized according to the four-layer structure | -| [ADR-003](ADR-003-dependency-injection.md) | Dependency Injection | `dependency-injector` is a core stack choice for service wiring | -| [ADR-004](ADR-004-data-validation.md) | Data Validation | Pydantic V2 is a core stack choice for validation and modeling | -| [ADR-019](ADR-019-storage-and-persistence.md) | Storage and Persistence | SQLAlchemy and SQLite/PostgreSQL are the chosen persistence stack | -| [ADR-021](ADR-021-cli-and-output-rendering.md) | CLI and Output Rendering | Typer and Rich are the chosen CLI stack | -| [ADR-022](ADR-022-langchain-langgraph-integration.md) | LangChain/LangGraph Integration | LangChain and LangGraph are the chosen LLM orchestration stack | -| [ADR-025](ADR-025-observability-and-logging.md) | Observability and Logging | structlog is the chosen logging stack | - -## Acceptance - -### Votes For - -| Voter | Comment | -|-------|---------| -| Jeffrey Phillips Freeman | This stack balances maturity, ecosystem support, and alignment with our architectural goals | - -**Total: 1** - -### Votes Against - -| Voter | Comment | -|-------|---------| - -**Total: 0** - -### Abstentions - -| Voter | Comment | -|-------|---------| - -**Total: 0** diff --git a/docs/adr/ADR-006-plan-lifecycle.md b/docs/adr/ADR-006-plan-lifecycle.md index 66f7a5e9f..d0bdb2cf5 100644 --- a/docs/adr/ADR-006-plan-lifecycle.md +++ b/docs/adr/ADR-006-plan-lifecycle.md @@ -1,15 +1,68 @@ -# ADR-006: Plan Lifecycle - -**Status:** Accepted -**Date:** 2026-02-16 -**Supersedes:** None -**Author(s):** Jeffrey Phillips Freeman -**Approver(s):** Jeffrey Phillips Freeman - +--- +adr_number: 6 +title: Plan Lifecycle +status_history: +- - '2026-02-16' + - Proposed + - Jeffrey Phillips Freeman +- - '2026-02-16' + - Accepted + - Jeffrey Phillips Freeman +tier: 2 +authors: +- Jeffrey Phillips Freeman +superseded_by: null +related_adrs: +- number: 7 + title: Decision Tree and Correction + relationship: Decisions are recorded at each phase transition in the plan lifecycle +- number: 8 + title: Resource System + relationship: Resources are bound to plans and sandboxed per the lifecycle phases +- number: 9 + title: Project Model + relationship: Plans operate within project scope and inherit project-level configuration +- number: 10 + title: Actor and Agent Architecture + relationship: Actors drive phase transitions and execute plan steps +- number: 15 + title: Sandbox and Checkpoint + relationship: Sandboxes are created per-plan and checkpoints track execution progress +- number: 16 + title: Invariant System + relationship: Invariants are reconciled at Strategize entry and enforced throughout the lifecycle +- number: 17 + title: Automation Profiles + relationship: Profiles control which phase transitions require human approval +- number: 33 + title: Decision Recording Protocol + relationship: Defines how decisions are recorded during Strategize and Execute phases of the plan lifecycle +- number: 34 + title: Decision Tree Versioning and History + relationship: Specifies how decision trees are versioned across plan lifecycle transitions +- number: 35 + title: Decision Tree Rollback and Replay + relationship: Governs rollback mechanics during mid-phase corrections within the plan lifecycle +acceptance: + votes_for: + - voter: Jeffrey Phillips Freeman + comment: The four-phase lifecycle with reversion rules gives us the right balance of structure and recovery + votes_against: [] + abstentions: [] +--- ## Context CleverAgents needs a structured workflow that takes a user's intent (e.g., "increase test coverage to 85%") and transforms it into verified, applied changes across project resources. This workflow must support human review gates, autonomous execution, hierarchical decomposition into child plans, sandboxed execution with rollback, and correction of decisions at any point. A linear "run and hope" approach is insufficient — the system needs distinct phases with clear inputs, outputs, transition rules, and failure handling. +## Decision Drivers + +- User intent (e.g., "increase test coverage to 85%") must be transformed into verified, applied changes through a structured workflow +- Must support human review gates at any transition point, controlled by automation profiles +- Sandboxed execution must ensure incomplete or incorrect work never contaminates real project resources +- Need hierarchical decomposition for tasks of arbitrary scale while keeping each plan's context bounded +- Correction of decisions at any point requires phase reversion rather than plan abandonment +- A linear "run and hope" approach is insufficient — distinct phases with clear inputs, outputs, and failure handling are required + ## Decision Every unit of work in CleverAgents follows a **four-phase lifecycle**: **Action → Strategize → Execute → Apply**. Each phase has defined inputs, outputs, processing states, and transition rules. The lifecycle supports forward progression, phase reversion (Execute → Strategize, Apply → Strategize), hierarchical decomposition via child plans, and automation profile-controlled autonomy at each transition. @@ -182,42 +235,3 @@ Resume Summary - **Reversion boundary tests**: Tests verify that Execute-phase code cannot modify resources outside the sandbox and that reversion correctly preserves and transmits findings to the strategy actor. - **BDD scenarios**: Behave feature files describe end-to-end plan lifecycle scenarios including hierarchical decomposition, parallel child plan execution, and phase reversion. - **Automation profile integration tests**: Tests verify that each automation profile correctly gates the appropriate phase transitions. - -## Related ADRs - -| ADR | Title | Relationship | -|-----|-------|-------------| -| [ADR-007](ADR-007-decision-tree-and-correction.md) | Decision Tree and Correction | Decisions are recorded at each phase transition in the plan lifecycle | -| [ADR-008](ADR-008-resource-system.md) | Resource System | Resources are bound to plans and sandboxed per the lifecycle phases | -| [ADR-009](ADR-009-project-model.md) | Project Model | Plans operate within project scope and inherit project-level configuration | -| [ADR-010](ADR-010-actor-and-agent-architecture.md) | Actor and Agent Architecture | Actors drive phase transitions and execute plan steps | -| [ADR-015](ADR-015-sandbox-and-checkpoint.md) | Sandbox and Checkpoint | Sandboxes are created per-plan and checkpoints track execution progress | -| [ADR-016](ADR-016-invariant-system.md) | Invariant System | Invariants are reconciled at Strategize entry and enforced throughout the lifecycle | -| [ADR-017](ADR-017-automation-profiles.md) | Automation Profiles | Profiles control which phase transitions require human approval | -| [ADR-033](ADR-033-decision-recording-protocol.md) | Decision Recording Protocol | Defines how decisions are recorded during Strategize and Execute phases of the plan lifecycle | -| [ADR-034](ADR-034-decision-tree-versioning-and-history.md) | Decision Tree Versioning and History | Specifies how decision trees are versioned across plan lifecycle transitions | -| [ADR-035](ADR-035-decision-tree-rollback-and-replay.md) | Decision Tree Rollback and Replay | Governs rollback mechanics during mid-phase corrections within the plan lifecycle | - -## Acceptance - -### Votes For - -| Voter | Comment | -|-------|---------| -| Jeffrey Phillips Freeman | The four-phase lifecycle with reversion rules gives us the right balance of structure and recovery | - -**Total: 1** - -### Votes Against - -| Voter | Comment | -|-------|---------| - -**Total: 0** - -### Abstentions - -| Voter | Comment | -|-------|---------| - -**Total: 0** diff --git a/docs/adr/ADR-007-decision-tree-and-correction.md b/docs/adr/ADR-007-decision-tree-and-correction.md index 18f05da59..3396484db 100644 --- a/docs/adr/ADR-007-decision-tree-and-correction.md +++ b/docs/adr/ADR-007-decision-tree-and-correction.md @@ -1,17 +1,58 @@ -# ADR-007: Decision Tree and Correction - -**Status:** Accepted -**Date:** 2026-02-16 -**Supersedes:** None -**Author(s):** Jeffrey Phillips Freeman -**Approver(s):** Jeffrey Phillips Freeman - +--- +adr_number: 7 +title: Decision Tree and Correction +status_history: +- - '2026-02-16' + - Proposed + - Jeffrey Phillips Freeman +- - '2026-02-16' + - Accepted + - Jeffrey Phillips Freeman +tier: 2 +authors: +- Jeffrey Phillips Freeman +superseded_by: null +related_adrs: +- number: 6 + title: Plan Lifecycle + relationship: Decision trees are built during lifecycle phases and drive phase transitions +- number: 16 + title: Invariant System + relationship: Enforced invariants are recorded as decision nodes in the tree +- number: 17 + title: Automation Profiles + relationship: Confidence thresholds determine which decisions require human intervention +- number: 33 + title: Decision Recording Protocol + relationship: Details the tool-based mechanism by which decisions are recorded in the tree +- number: 34 + title: Decision Tree Versioning and History + relationship: Defines the dual structure (structural tree + influence DAG) and versioning model for the decision tree +- number: 35 + title: Decision Tree Rollback and Replay + relationship: Specifies the rollback and replay mechanics for corrections within the decision tree +acceptance: + votes_for: + - voter: Jeffrey Phillips Freeman + comment: Persistent decision graphs enable targeted correction without re-running entire plans + votes_against: [] + abstentions: [] +--- ## Context When an AI system generates a plan and executes it, individual decisions along the way may prove incorrect — a strategy choice may be suboptimal, a resource selection may be wrong, or the original prompt may be too vague. Without a persistent record of what decisions were made, why, and how they relate to each other, correction requires re-running the entire plan from scratch. For large, hierarchically decomposed plans, this is prohibitively expensive. The system needs a structured decision graph that captures every choice point, its rationale, its context, and its downstream dependencies — enabling targeted correction that only invalidates and re-runs the affected subtree. +## Decision Drivers + +- Individual decisions in a plan may prove incorrect, but re-running the entire plan from scratch is prohibitively expensive for large hierarchically decomposed plans +- Must capture every choice point with its rationale, context, and downstream dependencies to enable targeted correction +- Corrections (including prompt corrections) should use a single unified mechanism operating on decision nodes +- The dependency graph between decisions must be explicit so invalidation cascades affect only the relevant subtree +- Context snapshots must be preserved per-decision to enable replay and debugging in isolation +- Confidence-based autonomy requires structured decision records with scores to determine when human intervention is needed + ## Decision Every plan maintains a **persistent decision tree** where each node is a typed decision record. The tree captures the prompt, invariant enforcement, strategy choices, resource selections, child plan blueprints, tool invocations, error recoveries, validation responses, and user interventions. All corrections — including prompt corrections — use a unified `agents plan correct` command that operates on decision nodes by ID. @@ -146,38 +187,3 @@ Decisions are stored in a `decisions` table with columns for all record fields, - **Context snapshot integrity**: Tests verify that replaying a decision from its context snapshot produces consistent results. - **BDD scenarios**: Behave features exercise correction workflows including prompt correction, strategy revision, and cross-hierarchy correction. - **Storage retention tests**: Tests verify that decision history cleanup respects retention policies. - -## Related ADRs - -| ADR | Title | Relationship | -|-----|-------|-------------| -| [ADR-006](ADR-006-plan-lifecycle.md) | Plan Lifecycle | Decision trees are built during lifecycle phases and drive phase transitions | -| [ADR-016](ADR-016-invariant-system.md) | Invariant System | Enforced invariants are recorded as decision nodes in the tree | -| [ADR-017](ADR-017-automation-profiles.md) | Automation Profiles | Confidence thresholds determine which decisions require human intervention | -| [ADR-033](ADR-033-decision-recording-protocol.md) | Decision Recording Protocol | Details the tool-based mechanism by which decisions are recorded in the tree | -| [ADR-034](ADR-034-decision-tree-versioning-and-history.md) | Decision Tree Versioning and History | Defines the dual structure (structural tree + influence DAG) and versioning model for the decision tree | -| [ADR-035](ADR-035-decision-tree-rollback-and-replay.md) | Decision Tree Rollback and Replay | Specifies the rollback and replay mechanics for corrections within the decision tree | - -## Acceptance - -### Votes For - -| Voter | Comment | -|-------|---------| -| Jeffrey Phillips Freeman | Persistent decision graphs enable targeted correction without re-running entire plans | - -**Total: 1** - -### Votes Against - -| Voter | Comment | -|-------|---------| - -**Total: 0** - -### Abstentions - -| Voter | Comment | -|-------|---------| - -**Total: 0** diff --git a/docs/adr/ADR-008-resource-system.md b/docs/adr/ADR-008-resource-system.md index 6660a50cf..5e5883dfe 100644 --- a/docs/adr/ADR-008-resource-system.md +++ b/docs/adr/ADR-008-resource-system.md @@ -1,15 +1,65 @@ -# ADR-008: Resource System - -**Status:** Accepted -**Date:** 2026-02-16 -**Supersedes:** None -**Author(s):** Jeffrey Phillips Freeman -**Approver(s):** Jeffrey Phillips Freeman - +--- +adr_number: 8 +title: Resource System +status_history: +- - '2026-02-16' + - Proposed + - Jeffrey Phillips Freeman +- - '2026-02-16' + - Accepted + - Jeffrey Phillips Freeman +tier: 2 +authors: +- Jeffrey Phillips Freeman +superseded_by: null +related_adrs: +- number: 2 + title: Namespace System + relationship: Resources are identified and resolved via the universal naming convention +- number: 9 + title: Project Model + relationship: Projects aggregate and scope the resources available to plans +- number: 11 + title: Tool System + relationship: Tools declare resource bindings that determine which resources they operate on +- number: 15 + title: Sandbox and Checkpoint + relationship: Per-resource-type sandbox strategies isolate resource modifications +- number: 36 + title: Resource DAG Operational Semantics + relationship: Defines the operational semantics (sandbox boundary algebra, reachability, change propagation) that build on the DAG structure +- number: 37 + title: Tool Reachability and Access Projection + relationship: Formalizes transitive tool reachability through DAG containment edges +- number: 38 + title: Cross-Mechanism Sandbox Coordination + relationship: Defines coherence and coordination across equivalent physical resources in different sandbox domains +- number: 39 + title: Container and Execution Environment Resource Types + relationship: Extends the built-in type registry with container and execution environment types +- number: 40 + title: LSP Resource Types + relationship: Extends the built-in type registry with LSP server, workspace, and document types +acceptance: + votes_for: + - voter: Jeffrey Phillips Freeman + comment: Typed resources with DAG relationships and per-type sandbox strategies provide the right abstraction for safe manipulation + votes_against: [] + abstentions: [] +--- ## Context CleverAgents must operate on a wide variety of artifacts — git repositories, filesystem directories, databases, APIs, configuration files, documentation, and more. Each resource type has different read/write semantics, different sandboxing strategies, and different merge behaviors. The system needs a uniform abstraction that makes resources discoverable, linkable to projects, bindable to tools, and sandboxable — while accommodating the inherent diversity of resource types. +## Decision Drivers + +- Must operate on diverse artifact types (git repos, filesystems, databases, APIs, config files) with different read/write semantics +- Each resource type requires a different sandboxing strategy and merge behavior +- Resources must be discoverable, linkable to projects, and bindable to tools through a uniform abstraction +- Need DAG-based relationships between resources for correct sandbox creation and cleanup ordering +- Resources must be independently registered and shareable across multiple projects +- Per-type sandbox strategies must ensure appropriate isolation without per-resource manual configuration + ## Decision CleverAgents uses a **typed resource system** with a resource registry, independently registered resource types, and per-type sandbox strategies. Resources are first-class entities with namespaced names, ULID identifiers, and DAG-based relationships. Resource types define the schema, sandbox strategy, and merge behavior for each category of artifact. @@ -107,41 +157,3 @@ None — specification-driven requirement. The typed resource system with regist - **Sandbox strategy tests**: Each sandbox strategy has integration tests verifying isolation, modification, rollback, and cleanup. - **Binding resolution tests**: Unit tests verify that all three binding modes (contextual, static, parameter) resolve correctly for each resource type. - **BDD scenarios**: Behave features exercise multi-resource, multi-type plan execution including sandbox creation, tool binding, and result merging. - -## Related ADRs - -| ADR | Title | Relationship | -|-----|-------|-------------| -| [ADR-002](ADR-002-namespace-system.md) | Namespace System | Resources are identified and resolved via the universal naming convention | -| [ADR-009](ADR-009-project-model.md) | Project Model | Projects aggregate and scope the resources available to plans | -| [ADR-011](ADR-011-tool-system.md) | Tool System | Tools declare resource bindings that determine which resources they operate on | -| [ADR-015](ADR-015-sandbox-and-checkpoint.md) | Sandbox and Checkpoint | Per-resource-type sandbox strategies isolate resource modifications | -| [ADR-036](ADR-036-resource-dag-operational-semantics.md) | Resource DAG Operational Semantics | Defines the operational semantics (sandbox boundary algebra, reachability, change propagation) that build on the DAG structure | -| [ADR-037](ADR-037-tool-reachability-and-access-projection.md) | Tool Reachability and Access Projection | Formalizes transitive tool reachability through DAG containment edges | -| [ADR-038](ADR-038-cross-mechanism-sandbox-coordination.md) | Cross-Mechanism Sandbox Coordination | Defines coherence and coordination across equivalent physical resources in different sandbox domains | -| [ADR-039](ADR-039-container-resource-types.md) | Container and Execution Environment Resource Types | Extends the built-in type registry with container and execution environment types | -| [ADR-040](ADR-040-lsp-resource-types.md) | LSP Resource Types | Extends the built-in type registry with LSP server, workspace, and document types | - -## Acceptance - -### Votes For - -| Voter | Comment | -|-------|---------| -| Jeffrey Phillips Freeman | Typed resources with DAG relationships and per-type sandbox strategies provide the right abstraction for safe manipulation | - -**Total: 1** - -### Votes Against - -| Voter | Comment | -|-------|---------| - -**Total: 0** - -### Abstentions - -| Voter | Comment | -|-------|---------| - -**Total: 0** diff --git a/docs/adr/ADR-009-project-model.md b/docs/adr/ADR-009-project-model.md index 0d400ff9d..c5a1e4e32 100644 --- a/docs/adr/ADR-009-project-model.md +++ b/docs/adr/ADR-009-project-model.md @@ -1,15 +1,50 @@ -# ADR-009: Project Model - -**Status:** Accepted -**Date:** 2026-02-16 -**Supersedes:** None -**Author(s):** Jeffrey Phillips Freeman -**Approver(s):** Jeffrey Phillips Freeman - +--- +adr_number: 9 +title: Project Model +status_history: +- - '2026-02-16' + - Proposed + - Jeffrey Phillips Freeman +- - '2026-02-16' + - Accepted + - Jeffrey Phillips Freeman +tier: 2 +authors: +- Jeffrey Phillips Freeman +superseded_by: null +related_adrs: +- number: 2 + title: Namespace System + relationship: Projects are namespace-scoped entities using the universal naming convention +- number: 8 + title: Resource System + relationship: Projects link and scope the resources available for plan execution +- number: 14 + title: Context Management (ACMS) + relationship: Projects configure context retrieval strategies and index scopes +- number: 16 + title: Invariant System + relationship: Projects define project-scoped invariants that constrain all plans within +acceptance: + votes_for: + - voter: Jeffrey Phillips Freeman + comment: Projects as named scopes linking resources, context, and invariants provide a clean organizational boundary + votes_against: [] + abstentions: [] +--- ## Context Plans need a defined scope that answers: "Where is the work happening? What can this plan read and write? What skills and tools are available? What context is available?" Without a project abstraction, every plan would need to independently specify its resources, context configuration, and constraints — leading to repetition, inconsistency, and difficulty managing shared configuration across related plans. +## Decision Drivers + +- Plans need a defined scope answering: what resources can be accessed, what tools are available, and how context is assembled +- Without a project abstraction, every plan would independently specify resources, context config, and constraints — causing repetition and inconsistency +- Must support multi-project operations where a single plan targets multiple codebases +- Project-scoped configuration must override global defaults while being overridable by plan-level or CLI-level settings +- Resources should be linked (not defined inline) so resource definitions are maintained in one place even when shared +- Projects must be created via CLI commands to align with the operational workflow, not YAML configuration files + ## Decision A **project** is the named scope that binds together a collection of linked resources, context configuration, and invariants. Projects are created via CLI commands (not YAML configuration files). They determine what a plan can access and how context is assembled. A plan targets one or more projects when used. @@ -98,36 +133,3 @@ None — specification-driven requirement. The project model as a named scope wi - **Multi-project tests**: Integration tests exercise plans targeting multiple projects with overlapping and non-overlapping resources. - **Configuration resolution tests**: Tests verify the full resolution chain (CLI > plan > action > project > global > default) for project-scopable keys. - **Code review**: New project-scopable configuration keys must be documented and tested for correct precedence. - -## Related ADRs - -| ADR | Title | Relationship | -|-----|-------|-------------| -| [ADR-002](ADR-002-namespace-system.md) | Namespace System | Projects are namespace-scoped entities using the universal naming convention | -| [ADR-008](ADR-008-resource-system.md) | Resource System | Projects link and scope the resources available for plan execution | -| [ADR-014](ADR-014-context-management-acms.md) | Context Management (ACMS) | Projects configure context retrieval strategies and index scopes | -| [ADR-016](ADR-016-invariant-system.md) | Invariant System | Projects define project-scoped invariants that constrain all plans within | - -## Acceptance - -### Votes For - -| Voter | Comment | -|-------|---------| -| Jeffrey Phillips Freeman | Projects as named scopes linking resources, context, and invariants provide a clean organizational boundary | - -**Total: 1** - -### Votes Against - -| Voter | Comment | -|-------|---------| - -**Total: 0** - -### Abstentions - -| Voter | Comment | -|-------|---------| - -**Total: 0** diff --git a/docs/adr/ADR-010-actor-and-agent-architecture.md b/docs/adr/ADR-010-actor-and-agent-architecture.md index 70de63fc8..edd96fe36 100644 --- a/docs/adr/ADR-010-actor-and-agent-architecture.md +++ b/docs/adr/ADR-010-actor-and-agent-architecture.md @@ -1,15 +1,68 @@ -# ADR-010: Actor and Agent Architecture - -**Status:** Accepted -**Date:** 2026-02-16 -**Supersedes:** None -**Author(s):** Jeffrey Phillips Freeman -**Approver(s):** Jeffrey Phillips Freeman - +--- +adr_number: 10 +title: Actor and Agent Architecture +status_history: +- - '2026-02-16' + - Proposed + - Jeffrey Phillips Freeman +- - '2026-02-16' + - Accepted + - Jeffrey Phillips Freeman +tier: 2 +authors: +- Jeffrey Phillips Freeman +superseded_by: null +related_adrs: +- number: 2 + title: Namespace System + relationship: Actors and agents are identified via namespaced names +- number: 6 + title: Plan Lifecycle + relationship: Actors drive plan phase transitions and execute plan steps +- number: 11 + title: Tool System + relationship: Tools serve as atomic execution nodes within actor graphs +- number: 12 + title: Skill System + relationship: Skills provide the tool collections that actors are equipped with +- number: 22 + title: LangChain/LangGraph Integration + relationship: Actors are implemented as LangGraph StateGraph instances +- number: 30 + title: Skill Abstraction Definition + relationship: Skills are the unit of capability assignment to actors +- number: 31 + title: Actor Abstraction Definition + relationship: Formalizes the canonical definition of what an actor is +- number: 32 + title: Jinja2 YAML Template Preprocessing + relationship: Defines the two-phase Jinja2 + env var preprocessing pipeline for actor YAML files +- number: 33 + title: Decision Recording Protocol + relationship: Actors call `record_decision` tool during Strategize and Execute to record decisions in the tree +- number: 27 + title: Language Server Protocol (LSP) Integration + relationship: Actors acquire language intelligence through LSP servers bound via the `lsp` configuration field +acceptance: + votes_for: + - voter: Jeffrey Phillips Freeman + comment: Actor-as-graph with hierarchical composition gives us flexible orchestration without tight coupling + votes_against: [] + abstentions: [] +--- ## Context CleverAgents must orchestrate multiple AI-driven roles — strategy planning, code execution, cost estimation, invariant reconciliation, code review, and more. Some of these roles are single LLM agents; others are complex multi-step workflows involving multiple LLMs, deterministic tool nodes, and sub-graphs. The system needs an abstraction that unifies all of these behind a common interface, supports hierarchical composition, and is defined declaratively via configuration rather than code. +## Decision Drivers + +- Must orchestrate multiple AI-driven roles (strategy planning, code execution, cost estimation, invariant reconciliation, code review) under a single abstraction +- Some roles are single LLM agents; others are complex multi-step workflows with multiple LLMs, deterministic tool nodes, and sub-graphs +- Actors must be defined declaratively via YAML configuration, not code, to enable non-developer customization +- Need hierarchical composition so complex behaviors are built from simple, reusable named components +- Must support namespaced identification and resolution of actors across deployment boundaries +- The "agent" concept (LLM with tools and reasoning) must be preserved as a specialization, not the only orchestration primitive + ## Decision CleverAgents uses the **actor** as its fundamental orchestration abstraction. An actor generalizes "agent" into "anything conversational." Every custom actor is a **LangGraph graph** defined via YAML configuration — even a simple single-LLM actor is a graph with one node. Actors are namespaced, composable, and referenceable by name. An **agent** is a specialized actor with a conversational interface, tool-calling capability, and optionally memory and planning heuristics. @@ -114,42 +167,3 @@ Agent behavior is configurable without code changes: prompt templates, tool sets - **Composition tests**: Integration tests verify that hierarchically composed actors correctly delegate to sub-actors and aggregate results. - **Role tests**: BDD scenarios verify that strategy, execution, estimation, and invariant actors fulfill their roles correctly within the plan lifecycle. - **Code review**: New actor definitions are reviewed for correct graph structure, appropriate skill access policies, and reasonable limit configurations. - -## Related ADRs - -| ADR | Title | Relationship | -|-----|-------|-------------| -| [ADR-002](ADR-002-namespace-system.md) | Namespace System | Actors and agents are identified via namespaced names | -| [ADR-006](ADR-006-plan-lifecycle.md) | Plan Lifecycle | Actors drive plan phase transitions and execute plan steps | -| [ADR-011](ADR-011-tool-system.md) | Tool System | Tools serve as atomic execution nodes within actor graphs | -| [ADR-012](ADR-012-skill-system.md) | Skill System | Skills provide the tool collections that actors are equipped with | -| [ADR-022](ADR-022-langchain-langgraph-integration.md) | LangChain/LangGraph Integration | Actors are implemented as LangGraph StateGraph instances | -| [ADR-030](ADR-030-skill-abstraction-definition.md) | Skill Abstraction Definition | Skills are the unit of capability assignment to actors | -| [ADR-031](ADR-031-actor-abstraction-definition.md) | Actor Abstraction Definition | Formalizes the canonical definition of what an actor is | -| [ADR-032](ADR-032-jinja2-yaml-template-preprocessing.md) | Jinja2 YAML Template Preprocessing | Defines the two-phase Jinja2 + env var preprocessing pipeline for actor YAML files | -| [ADR-033](ADR-033-decision-recording-protocol.md) | Decision Recording Protocol | Actors call `record_decision` tool during Strategize and Execute to record decisions in the tree | -| [ADR-027](ADR-027-language-server-protocol.md) | Language Server Protocol (LSP) Integration | Actors acquire language intelligence through LSP servers bound via the `lsp` configuration field | - -## Acceptance - -### Votes For - -| Voter | Comment | -|-------|---------| -| Jeffrey Phillips Freeman | Actor-as-graph with hierarchical composition gives us flexible orchestration without tight coupling | - -**Total: 1** - -### Votes Against - -| Voter | Comment | -|-------|---------| - -**Total: 0** - -### Abstentions - -| Voter | Comment | -|-------|---------| - -**Total: 0** diff --git a/docs/adr/ADR-011-tool-system.md b/docs/adr/ADR-011-tool-system.md index 6d37dfbb6..8f651b2e4 100644 --- a/docs/adr/ADR-011-tool-system.md +++ b/docs/adr/ADR-011-tool-system.md @@ -1,15 +1,71 @@ -# ADR-011: Tool System - -**Status:** Accepted -**Date:** 2026-02-16 -**Supersedes:** None -**Author(s):** Jeffrey Phillips Freeman -**Approver(s):** Jeffrey Phillips Freeman - +--- +adr_number: 11 +title: Tool System +status_history: +- - '2026-02-16' + - Proposed + - Jeffrey Phillips Freeman +- - '2026-02-16' + - Accepted + - Jeffrey Phillips Freeman +tier: 2 +authors: +- Jeffrey Phillips Freeman +superseded_by: null +related_adrs: +- number: 2 + title: Namespace System + relationship: Tools use namespaced identifiers for discovery and conflict resolution +- number: 4 + title: Data Validation + relationship: Tool input/output schemas are Pydantic models with JSON Schema generation +- number: 8 + title: Resource System + relationship: Tools declare resource bindings that determine which resources they operate on +- number: 10 + title: Actor and Agent Architecture + relationship: Tools serve as atomic execution nodes within actor graphs +- number: 12 + title: Skill System + relationship: Skills compose tools into reusable collections for actor assignment +- number: 13 + title: Validation Abstraction + relationship: Validations are a specialized Tool subtype with structured pass/fail semantics +- number: 15 + title: Sandbox and Checkpoint + relationship: Tool invocations create checkpoints for rollback and recovery +- number: 28 + title: Agent Skills Standard (AgentSkills.io) + relationship: Agent Skills are a tool source (`agent_skill`) integrated into the Tool Registry +- number: 29 + title: Model Context Protocol (MCP) Adoption + relationship: MCP tools are registered as Tool records and follow the four-stage tool lifecycle +- number: 30 + title: Skill Abstraction Definition + relationship: Tools are the atomic operations that skills collect and present to actors +- number: 37 + title: Tool Reachability and Access Projection + relationship: Extends resource bindings with transitive reachability, access projection, and read/write routing +acceptance: + votes_for: + - voter: Jeffrey Phillips Freeman + comment: The four-stage lifecycle with dual role as skill component and graph node is a clean unification + votes_against: [] + abstentions: [] +--- ## Context CleverAgents must integrate tools from multiple sources — built-in file/git operations, MCP server-hosted tools, Agent Skills (SKILL.md-based instructions), and custom user-defined tools. Each source has different discovery mechanisms, execution protocols, and capability characteristics. The system needs a uniform tool abstraction that normalizes these differences while preserving source-specific capabilities like checkpointing, resource binding, and sandbox awareness. +## Decision Drivers + +- Must integrate tools from four distinct sources (built-in, MCP servers, Agent Skills, custom) with different discovery and execution protocols +- Tools must serve a dual role: as LLM tool-calling targets within skills and as deterministic graph nodes in actor workflows +- Resource bindings must decouple tools from specific resources, enabling portability across projects +- Need a uniform four-stage lifecycle (discover, activate, execute, deactivate) to normalize source-specific differences +- Change tracking must be driven by tool invocations, not by parsing LLM output, to ensure reliable auditable changesets +- Capability metadata (read-only, checkpointable, side effects) must be declared per tool to enable safety enforcement at runtime + ## Decision A **tool** is the atomic unit of execution — the smallest piece of functionality that can read, write, or transform resources. Tools are namespaced, independently registered, and follow a **four-stage lifecycle** (discover, activate, execute, deactivate). Every tool has a uniform interface regardless of source, and plays a **dual role**: as a component of a skill (available for LLM tool-calling) and as a tool node in an actor graph (deterministic, non-LLM execution step). @@ -137,43 +193,3 @@ None — specification-driven requirement. The tool system with its four-stage l - **Capability enforcement tests**: Tests verify that `read_only` actions reject tools with `writes: true`, and that `human_approval_required` tools trigger approval gates. - **Change tracking tests**: Tests verify that the changeset accurately reflects all tool invocations and contains no changes from LLM output parsing. - **Schema validation**: Tool registration validates input/output schemas against JSON Schema specification. - -## Related ADRs - -| ADR | Title | Relationship | -|-----|-------|-------------| -| [ADR-002](ADR-002-namespace-system.md) | Namespace System | Tools use namespaced identifiers for discovery and conflict resolution | -| [ADR-004](ADR-004-data-validation.md) | Data Validation | Tool input/output schemas are Pydantic models with JSON Schema generation | -| [ADR-008](ADR-008-resource-system.md) | Resource System | Tools declare resource bindings that determine which resources they operate on | -| [ADR-010](ADR-010-actor-and-agent-architecture.md) | Actor and Agent Architecture | Tools serve as atomic execution nodes within actor graphs | -| [ADR-012](ADR-012-skill-system.md) | Skill System | Skills compose tools into reusable collections for actor assignment | -| [ADR-013](ADR-013-validation-abstraction.md) | Validation Abstraction | Validations are a specialized Tool subtype with structured pass/fail semantics | -| [ADR-015](ADR-015-sandbox-and-checkpoint.md) | Sandbox and Checkpoint | Tool invocations create checkpoints for rollback and recovery | -| [ADR-028](ADR-028-agent-skills-standard.md) | Agent Skills Standard (AgentSkills.io) | Agent Skills are a tool source (`agent_skill`) integrated into the Tool Registry | -| [ADR-029](ADR-029-model-context-protocol.md) | Model Context Protocol (MCP) Adoption | MCP tools are registered as Tool records and follow the four-stage tool lifecycle | -| [ADR-030](ADR-030-skill-abstraction-definition.md) | Skill Abstraction Definition | Tools are the atomic operations that skills collect and present to actors | -| [ADR-037](ADR-037-tool-reachability-and-access-projection.md) | Tool Reachability and Access Projection | Extends resource bindings with transitive reachability, access projection, and read/write routing | - -## Acceptance - -### Votes For - -| Voter | Comment | -|-------|---------| -| Jeffrey Phillips Freeman | The four-stage lifecycle with dual role as skill component and graph node is a clean unification | - -**Total: 1** - -### Votes Against - -| Voter | Comment | -|-------|---------| - -**Total: 0** - -### Abstentions - -| Voter | Comment | -|-------|---------| - -**Total: 0** diff --git a/docs/adr/ADR-012-skill-system.md b/docs/adr/ADR-012-skill-system.md index 0805a45a8..04fb9a84d 100644 --- a/docs/adr/ADR-012-skill-system.md +++ b/docs/adr/ADR-012-skill-system.md @@ -1,15 +1,59 @@ -# ADR-012: Skill System - -**Status:** Accepted -**Date:** 2026-02-16 -**Supersedes:** None -**Author(s):** Jeffrey Phillips Freeman -**Approver(s):** Jeffrey Phillips Freeman - +--- +adr_number: 12 +title: Skill System +status_history: +- - '2026-02-16' + - Proposed + - Jeffrey Phillips Freeman +- - '2026-02-16' + - Accepted + - Jeffrey Phillips Freeman +tier: 2 +authors: +- Jeffrey Phillips Freeman +superseded_by: null +related_adrs: +- number: 2 + title: Namespace System + relationship: Skills use namespaced names and resolve tool conflicts via qualified names +- number: 10 + title: Actor and Agent Architecture + relationship: Skills are assigned to actors to provide their tool capabilities +- number: 11 + title: Tool System + relationship: Skills compose tools into reusable, hierarchical collections +- number: 13 + title: Validation Abstraction + relationship: Validation tools can be included in skills alongside regular tools +- number: 28 + title: Agent Skills Standard (AgentSkills.io) + relationship: Agent Skills are composed and exposed through the skill system +- number: 29 + title: Model Context Protocol (MCP) Adoption + relationship: MCP tools are exposed through skills for actor access +- number: 30 + title: Skill Abstraction Definition + relationship: Formalizes the canonical definition of what a skill is +acceptance: + votes_for: + - voter: Jeffrey Phillips Freeman + comment: Composable skill collections with hierarchical inclusion keep actor configuration manageable + votes_against: [] + abstentions: [] +--- ## Context Actors need curated sets of tools to perform their roles — a code execution actor needs file operations, git tools, and test runners; a DevOps actor needs infrastructure provisioning and deployment tools. Assigning tools individually to each actor would be repetitive, error-prone, and difficult to maintain. The system needs an organizational unit that groups related tools into reusable, composable collections. +## Decision Drivers + +- Must compose tool collections from four distinct sources (MCP, Agent Skills, built-in, custom) +- Skills must be reusable across different actors without duplication of tool assignments +- Need hierarchical inclusion with automatic flattening for LLM tool binding +- Tool name conflicts across composed skills must be resolvable without manual renaming +- Actors performing similar roles should share common tool sets without redundant configuration +- Skill access must be restrictable per-actor to enforce capability boundaries + ## Decision A **skill** is a namespaced, reusable collection of tools that serves as the organizational layer between individual tools and actors. Skills are defined in YAML, support hierarchical composition through skill-includes, and are flattened into a unified tool set when referenced by an actor. @@ -112,39 +156,3 @@ Actors specify a `skill_access_policy` that controls which skills they can use. - **Override tests**: Tests verify that metadata overrides at inclusion points are applied correctly and do not persist back to the source. - **Access policy tests**: Tests verify that actor skill access policies correctly restrict the available tool set. - **BDD scenarios**: Behave features exercise actors using hierarchically composed skills across all tool sources. - -## Related ADRs - -| ADR | Title | Relationship | -|-----|-------|-------------| -| [ADR-002](ADR-002-namespace-system.md) | Namespace System | Skills use namespaced names and resolve tool conflicts via qualified names | -| [ADR-010](ADR-010-actor-and-agent-architecture.md) | Actor and Agent Architecture | Skills are assigned to actors to provide their tool capabilities | -| [ADR-011](ADR-011-tool-system.md) | Tool System | Skills compose tools into reusable, hierarchical collections | -| [ADR-013](ADR-013-validation-abstraction.md) | Validation Abstraction | Validation tools can be included in skills alongside regular tools | -| [ADR-028](ADR-028-agent-skills-standard.md) | Agent Skills Standard (AgentSkills.io) | Agent Skills are composed and exposed through the skill system | -| [ADR-029](ADR-029-model-context-protocol.md) | Model Context Protocol (MCP) Adoption | MCP tools are exposed through skills for actor access | -| [ADR-030](ADR-030-skill-abstraction-definition.md) | Skill Abstraction Definition | Formalizes the canonical definition of what a skill is | - -## Acceptance - -### Votes For - -| Voter | Comment | -|-------|---------| -| Jeffrey Phillips Freeman | Composable skill collections with hierarchical inclusion keep actor configuration manageable | - -**Total: 1** - -### Votes Against - -| Voter | Comment | -|-------|---------| - -**Total: 0** - -### Abstentions - -| Voter | Comment | -|-------|---------| - -**Total: 0** diff --git a/docs/adr/ADR-013-validation-abstraction.md b/docs/adr/ADR-013-validation-abstraction.md index 567090f0f..ea08ef760 100644 --- a/docs/adr/ADR-013-validation-abstraction.md +++ b/docs/adr/ADR-013-validation-abstraction.md @@ -1,15 +1,50 @@ -# ADR-013: Validation Abstraction - -**Status:** Accepted -**Date:** 2026-02-16 -**Supersedes:** None -**Author(s):** Jeffrey Phillips Freeman -**Approver(s):** Jeffrey Phillips Freeman - +--- +adr_number: 13 +title: Validation Abstraction +status_history: +- - '2026-02-16' + - Proposed + - Jeffrey Phillips Freeman +- - '2026-02-16' + - Accepted + - Jeffrey Phillips Freeman +tier: 2 +authors: +- Jeffrey Phillips Freeman +superseded_by: null +related_adrs: +- number: 6 + title: Plan Lifecycle + relationship: Validations gate phase transitions and can trigger phase reversion +- number: 11 + title: Tool System + relationship: Validations are a specialized Tool subtype inheriting the tool lifecycle +- number: 12 + title: Skill System + relationship: Validation tools can be composed into skills alongside regular tools +- number: 16 + title: Invariant System + relationship: Invariant enforcement uses validation tools as its execution mechanism +acceptance: + votes_for: + - voter: Jeffrey Phillips Freeman + comment: Modeling validation as a Tool subtype with structured pass/fail keeps the system uniform and composable + votes_against: [] + abstentions: [] +--- ## Context Plans must verify that their work meets quality, correctness, and compliance criteria before changes are applied to real project resources. This verification must be structured (machine-parseable pass/fail results, not free-text), composable (multiple validations can run in parallel), and gating (required validations block Apply if they fail). The system needs a validation mechanism that integrates with the existing tool infrastructure rather than being a separate system. +## Decision Drivers + +- Verification results must be machine-parseable (structured pass/fail), not free-text LLM interpretation +- Validations must integrate with the existing tool infrastructure rather than creating a parallel system +- Required validations must gate the Apply phase — failed checks block changes from reaching real resources +- Read-only enforcement is essential for safe parallel execution and retry without side effects +- Validation attachment must support multiple scoping levels (direct, project, plan) for fine-grained control +- Existing tools should be reusable as validations via wrapping, avoiding reimplementation + ## Decision A **Validation** is a specialized subtype of Tool designed to verify work. It extends Tool via standard class inheritance, adding `mode` (required/informational), a structured JSON return format (`{ "passed": bool, "message": str, "data": object }`), and strict read-only enforcement. Validations share the tool namespace, reuse the entire tool infrastructure, and are composable into skills and actor graphs. @@ -127,36 +162,3 @@ Validations can appear as tool nodes in actor graphs, with return values availab - **Attachment scoping tests**: Tests verify correct resolution across direct, project-scoped, and plan-scoped attachments. - **Failure handling tests**: BDD scenarios exercise the full failure sequence: fix → revalidate → retry limit → strategy revision → escalation → terminal failure. - **Wrapping tests**: Tests verify that wrapped tool transforms correctly interpret tool output and that inheritance rules are applied. - -## Related ADRs - -| ADR | Title | Relationship | -|-----|-------|-------------| -| [ADR-006](ADR-006-plan-lifecycle.md) | Plan Lifecycle | Validations gate phase transitions and can trigger phase reversion | -| [ADR-011](ADR-011-tool-system.md) | Tool System | Validations are a specialized Tool subtype inheriting the tool lifecycle | -| [ADR-012](ADR-012-skill-system.md) | Skill System | Validation tools can be composed into skills alongside regular tools | -| [ADR-016](ADR-016-invariant-system.md) | Invariant System | Invariant enforcement uses validation tools as its execution mechanism | - -## Acceptance - -### Votes For - -| Voter | Comment | -|-------|---------| -| Jeffrey Phillips Freeman | Modeling validation as a Tool subtype with structured pass/fail keeps the system uniform and composable | - -**Total: 1** - -### Votes Against - -| Voter | Comment | -|-------|---------| - -**Total: 0** - -### Abstentions - -| Voter | Comment | -|-------|---------| - -**Total: 0** diff --git a/docs/adr/ADR-014-context-management-acms.md b/docs/adr/ADR-014-context-management-acms.md index a2d2bc0d5..28a453c5b 100644 --- a/docs/adr/ADR-014-context-management-acms.md +++ b/docs/adr/ADR-014-context-management-acms.md @@ -1,17 +1,52 @@ -# ADR-014: Context Management (ACMS) - -**Status:** Accepted -**Date:** 2026-02-16 -**Supersedes:** None -**Author(s):** Jeffrey Phillips Freeman -**Approver(s):** Jeffrey Phillips Freeman - +--- +adr_number: 14 +title: Context Management (ACMS) +status_history: +- - '2026-02-16' + - Proposed + - Jeffrey Phillips Freeman +- - '2026-02-16' + - Accepted + - Jeffrey Phillips Freeman +tier: 3 +authors: +- Jeffrey Phillips Freeman +superseded_by: null +related_adrs: +- number: 6 + title: Plan Lifecycle + relationship: Context is assembled and refreshed at each plan phase transition +- number: 8 + title: Resource System + relationship: Resources are indexed by the Unified Knowledge Ontology for context retrieval +- number: 9 + title: Project Model + relationship: Projects configure context retrieval strategies and index scopes +- number: 10 + title: Actor and Agent Architecture + relationship: Actors consume assembled context to inform their decisions +acceptance: + votes_for: + - voter: Jeffrey Phillips Freeman + comment: A pipeline-based context assembly system keeps retrieval strategies composable and tunable per project + votes_against: [] + abstentions: [] +--- ## Context LLM context windows are finite and expensive. Plans operating on large codebases cannot load everything into context — they must selectively retrieve the most relevant information. The system needs a context management mechanism that can index project resources into a queryable knowledge base, retrieve relevant fragments using multiple strategies (keyword, semantic, graph), assemble those fragments within a token budget, and present them coherently to the actor. A naive approach (load everything, or load files by name) fails at scale. The system needs a principled architecture for context retrieval, scoring, deduplication, budget packing, and tiered retention. +## Decision Drivers + +- LLM context windows are finite and expensive; naive "load everything" fails at scale +- Multiple retrieval strategies (keyword, semantic, graph) capture complementary facets of relevance +- Context assembly must respect a hard token budget derived from the model's context window +- Fragments need progressive detail depth so budget-constrained assemblies degrade gracefully rather than omitting content entirely +- Context must be refreshed at each plan phase transition with up-to-date retrieval results +- The pipeline must be pluggable so projects can customize retrieval strategies and scoring weights + ## Decision CleverAgents implements the **Adaptive Context Management System (ACMS)**, built on two foundations: the **Unified Knowledge Ontology (UKO)** for indexing and the **Context Retrieval Pipeline (CRP)** for assembly. The ACMS uses a 10-component pipeline that transforms raw retrieval results into a budget-constrained, coherently ordered context window. @@ -114,36 +149,3 @@ Child plans inherit a compressed "skeleton" of their parent's context. The Skele - **Strategy integration tests**: Tests verify that each retrieval strategy returns correctly structured results. - **Depth fallback tests**: Tests verify that fragments are downgraded to shallower depths when budget is insufficient for full depth. - **Configuration tests**: Tests verify that custom pipeline components and strategy registrations are loaded and invoked correctly. - -## Related ADRs - -| ADR | Title | Relationship | -|-----|-------|-------------| -| [ADR-006](ADR-006-plan-lifecycle.md) | Plan Lifecycle | Context is assembled and refreshed at each plan phase transition | -| [ADR-008](ADR-008-resource-system.md) | Resource System | Resources are indexed by the Unified Knowledge Ontology for context retrieval | -| [ADR-009](ADR-009-project-model.md) | Project Model | Projects configure context retrieval strategies and index scopes | -| [ADR-010](ADR-010-actor-and-agent-architecture.md) | Actor and Agent Architecture | Actors consume assembled context to inform their decisions | - -## Acceptance - -### Votes For - -| Voter | Comment | -|-------|---------| -| Jeffrey Phillips Freeman | A pipeline-based context assembly system keeps retrieval strategies composable and tunable per project | - -**Total: 1** - -### Votes Against - -| Voter | Comment | -|-------|---------| - -**Total: 0** - -### Abstentions - -| Voter | Comment | -|-------|---------| - -**Total: 0** diff --git a/docs/adr/ADR-015-sandbox-and-checkpoint.md b/docs/adr/ADR-015-sandbox-and-checkpoint.md index 9904cf0a4..2694baf80 100644 --- a/docs/adr/ADR-015-sandbox-and-checkpoint.md +++ b/docs/adr/ADR-015-sandbox-and-checkpoint.md @@ -1,15 +1,61 @@ -# ADR-015: Sandbox and Checkpoint - -**Status:** Accepted -**Date:** 2026-02-16 -**Supersedes:** None -**Author(s):** Jeffrey Phillips Freeman -**Approver(s):** Jeffrey Phillips Freeman - +--- +adr_number: 15 +title: Sandbox and Checkpoint +status_history: +- - '2026-02-16' + - Proposed + - Jeffrey Phillips Freeman +- - '2026-02-16' + - Accepted + - Jeffrey Phillips Freeman +tier: 3 +authors: +- Jeffrey Phillips Freeman +superseded_by: null +related_adrs: +- number: 6 + title: Plan Lifecycle + relationship: Sandboxes are created per-plan and destroyed on plan completion or reversion +- number: 8 + title: Resource System + relationship: Sandbox strategy is determined by resource type (git_worktree, filesystem_copy, etc.) +- number: 11 + title: Tool System + relationship: Tool invocations create checkpoints for granular rollback +- number: 28 + title: Agent Skills Standard (AgentSkills.io) + relationship: Sub-tool-calls within Agent Skill execution are individually checkpointed +- number: 29 + title: Model Context Protocol (MCP) Adoption + relationship: MCP tool execution must respect sandbox boundaries via path rewriting +- number: 35 + title: Decision Tree Rollback and Replay + relationship: Decision-aligned checkpoints extend the checkpoint system for coordinated rollback during Execute-phase corrections +- number: 36 + title: Resource DAG Operational Semantics + relationship: Formalizes sandbox boundaries as a DAG property with the sandbox boundary algebra +- number: 38 + title: Cross-Mechanism Sandbox Coordination + relationship: Extends sandbox coordination to cross-mechanism scenarios with coherence and write-then-sync +acceptance: + votes_for: + - voter: Jeffrey Phillips Freeman + comment: Lazy sandboxing with per-resource-type strategies avoids unnecessary overhead while keeping changes reversible + votes_against: [] + abstentions: [] +--- ## Context Plans modify project resources — source code, configuration files, databases — during the Execute phase. These modifications must be isolated from the real project until they are reviewed and approved during Apply. If execution fails partway through, the system must be able to roll back to a known-good state. Different resource types require different isolation mechanisms (git worktrees for source code, filesystem copies for non-git directories, transaction rollback for databases). +## Decision Drivers + +- Execute-phase modifications must be isolated from real project resources until reviewed and approved during Apply +- Different resource types require different isolation mechanisms (git worktrees, filesystem copies, database transactions) +- Fine-grained rollback to individual tool invocations is needed rather than reverting entire phases +- Sandboxing overhead should be avoided for resources the plan never touches (lazy over eager) +- Concurrent plans must not interfere with each other's sandboxed state + ## Decision CleverAgents uses **per-plan sandboxes** with **lazy sandboxing** (resources sandboxed only when first accessed) and **five isolation strategies** selected per resource type. Checkpointing is integrated at the tool level — each tool declares whether it supports checkpoints, and the system creates checkpoints before write operations to enable fine-grained rollback. @@ -117,40 +163,3 @@ Plans can require checkpoints via the `require_checkpoints` flag. If enabled, on - **Checkpoint tests**: Tests verify checkpoint creation, rollback to specific checkpoints, and pruning behavior. - **Lazy sandbox tests**: Tests verify that sandbox creation is deferred until first resource access and handles creation failures gracefully. - **Cleanup tests**: Tests verify that sandbox cleanup occurs at the correct lifecycle point (on_apply, on_terminal, manual). - -## Related ADRs - -| ADR | Title | Relationship | -|-----|-------|-------------| -| [ADR-006](ADR-006-plan-lifecycle.md) | Plan Lifecycle | Sandboxes are created per-plan and destroyed on plan completion or reversion | -| [ADR-008](ADR-008-resource-system.md) | Resource System | Sandbox strategy is determined by resource type (git_worktree, filesystem_copy, etc.) | -| [ADR-011](ADR-011-tool-system.md) | Tool System | Tool invocations create checkpoints for granular rollback | -| [ADR-028](ADR-028-agent-skills-standard.md) | Agent Skills Standard (AgentSkills.io) | Sub-tool-calls within Agent Skill execution are individually checkpointed | -| [ADR-029](ADR-029-model-context-protocol.md) | Model Context Protocol (MCP) Adoption | MCP tool execution must respect sandbox boundaries via path rewriting | -| [ADR-035](ADR-035-decision-tree-rollback-and-replay.md) | Decision Tree Rollback and Replay | Decision-aligned checkpoints extend the checkpoint system for coordinated rollback during Execute-phase corrections | -| [ADR-036](ADR-036-resource-dag-operational-semantics.md) | Resource DAG Operational Semantics | Formalizes sandbox boundaries as a DAG property with the sandbox boundary algebra | -| [ADR-038](ADR-038-cross-mechanism-sandbox-coordination.md) | Cross-Mechanism Sandbox Coordination | Extends sandbox coordination to cross-mechanism scenarios with coherence and write-then-sync | - -## Acceptance - -### Votes For - -| Voter | Comment | -|-------|---------| -| Jeffrey Phillips Freeman | Lazy sandboxing with per-resource-type strategies avoids unnecessary overhead while keeping changes reversible | - -**Total: 1** - -### Votes Against - -| Voter | Comment | -|-------|---------| - -**Total: 0** - -### Abstentions - -| Voter | Comment | -|-------|---------| - -**Total: 0** diff --git a/docs/adr/ADR-016-invariant-system.md b/docs/adr/ADR-016-invariant-system.md index b84093373..73e5c82c4 100644 --- a/docs/adr/ADR-016-invariant-system.md +++ b/docs/adr/ADR-016-invariant-system.md @@ -1,15 +1,52 @@ -# ADR-016: Invariant System - -**Status:** Accepted -**Date:** 2026-02-16 -**Supersedes:** None -**Author(s):** Jeffrey Phillips Freeman -**Approver(s):** Jeffrey Phillips Freeman - +--- +adr_number: 16 +title: Invariant System +status_history: +- - '2026-02-16' + - Proposed + - Jeffrey Phillips Freeman +- - '2026-02-16' + - Accepted + - Jeffrey Phillips Freeman +tier: 3 +authors: +- Jeffrey Phillips Freeman +superseded_by: null +related_adrs: +- number: 6 + title: Plan Lifecycle + relationship: Invariants are reconciled at Strategize entry and enforced throughout the lifecycle +- number: 7 + title: Decision Tree and Correction + relationship: Enforced invariants are recorded as `invariant_enforced` decision nodes +- number: 9 + title: Project Model + relationship: Projects define project-scoped invariants that constrain all child plans +- number: 17 + title: Automation Profiles + relationship: Invariant violations interact with automation profile thresholds for escalation +- number: 33 + title: Decision Recording Protocol + relationship: Invariant Reconciliation Actor creates `invariant_enforced` decisions via the `record_decision` tool +acceptance: + votes_for: + - voter: Jeffrey Phillips Freeman + comment: Four-scope invariants with precedence and reconciliation give us layered constraint enforcement + votes_against: [] + abstentions: [] +--- ## Context When AI systems make autonomous decisions, they must operate within defined boundaries. A strategy actor choosing an implementation approach must respect project-wide coding standards. An execution actor modifying files must respect API compatibility requirements. These constraints — invariants — may be defined at different scopes (global, project, action, plan) and may conflict with each other. The system needs a structured mechanism for declaring, scoping, resolving conflicts, and enforcing invariants across the plan lifecycle. +## Decision Drivers + +- Autonomous AI decisions must operate within declared boundaries (coding standards, API compatibility, etc.) +- Constraints originate at different scopes — system-wide standards vs. project-specific rules vs. plan-specific overrides +- Conflicting invariants across scopes need a deterministic, predictable resolution mechanism +- Invariants must be visible in the decision tree so they can be corrected, audited, and visualized like any other decision +- Child plans must inherit parent constraints without manual propagation + ## Decision CleverAgents implements an **invariant system** with four scopes (global, project, action, plan), a precedence-based resolution chain, an **Invariant Reconciliation Actor** that resolves conflicts, and explicit recording of enforced invariants as `invariant_enforced` decision nodes in the plan's decision tree. Invariants flow through the hierarchy — child plans inherit the effective invariant set of their parent. @@ -107,37 +144,3 @@ Invariants are correctable like any other decision: - **Inheritance tests**: Tests verify that child plans inherit the parent's effective invariant set and that child-level additions are correctly reconciled. - **Correction tests**: BDD scenarios verify that correcting an invariant invalidates downstream decisions and that adding/removing invariants triggers re-strategization. - **Reconciliation determinism**: Tests verify that the Invariant Reconciliation Actor produces identical output for identical inputs. - -## Related ADRs - -| ADR | Title | Relationship | -|-----|-------|-------------| -| [ADR-006](ADR-006-plan-lifecycle.md) | Plan Lifecycle | Invariants are reconciled at Strategize entry and enforced throughout the lifecycle | -| [ADR-007](ADR-007-decision-tree-and-correction.md) | Decision Tree and Correction | Enforced invariants are recorded as `invariant_enforced` decision nodes | -| [ADR-009](ADR-009-project-model.md) | Project Model | Projects define project-scoped invariants that constrain all child plans | -| [ADR-017](ADR-017-automation-profiles.md) | Automation Profiles | Invariant violations interact with automation profile thresholds for escalation | -| [ADR-033](ADR-033-decision-recording-protocol.md) | Decision Recording Protocol | Invariant Reconciliation Actor creates `invariant_enforced` decisions via the `record_decision` tool | - -## Acceptance - -### Votes For - -| Voter | Comment | -|-------|---------| -| Jeffrey Phillips Freeman | Four-scope invariants with precedence and reconciliation give us layered constraint enforcement | - -**Total: 1** - -### Votes Against - -| Voter | Comment | -|-------|---------| - -**Total: 0** - -### Abstentions - -| Voter | Comment | -|-------|---------| - -**Total: 0** diff --git a/docs/adr/ADR-017-automation-profiles.md b/docs/adr/ADR-017-automation-profiles.md index acbe62105..cd800ff08 100644 --- a/docs/adr/ADR-017-automation-profiles.md +++ b/docs/adr/ADR-017-automation-profiles.md @@ -1,15 +1,50 @@ -# ADR-017: Automation Profiles - -**Status:** Accepted -**Date:** 2026-02-16 -**Supersedes:** None -**Author(s):** Jeffrey Phillips Freeman -**Approver(s):** Jeffrey Phillips Freeman - +--- +adr_number: 17 +title: Automation Profiles +status_history: +- - '2026-02-16' + - Proposed + - Jeffrey Phillips Freeman +- - '2026-02-16' + - Accepted + - Jeffrey Phillips Freeman +tier: 3 +authors: +- Jeffrey Phillips Freeman +superseded_by: null +related_adrs: +- number: 6 + title: Plan Lifecycle + relationship: Profiles control which lifecycle phase transitions require human approval +- number: 7 + title: Decision Tree and Correction + relationship: Confidence thresholds determine which decisions require human intervention +- number: 16 + title: Invariant System + relationship: Invariant violation escalation is governed by the active automation profile +- number: 41 + title: Safety Profile Extraction + relationship: Safety constraints are extracted into a composed SafetyProfile sub-model within AutomationProfile +acceptance: + votes_for: + - voter: Jeffrey Phillips Freeman + comment: Named profiles with confidence thresholds provide a clean spectrum from full manual to full autonomous control + votes_against: [] + abstentions: [] +--- ## Context Different tasks require different levels of autonomy. A trusted refactoring in a well-tested codebase can run fully automatically, while a production infrastructure change requires human approval at every step. The system needs a configurable mechanism that controls which phase transitions happen automatically, which decisions require human input, and what safety constraints (sandboxing, checkpoints, approval gates) are enforced — without requiring code changes. +## Decision Drivers + +- Different tasks require fundamentally different autonomy levels (trusted refactoring vs. production infrastructure changes) +- Phase transitions, decision-making, and safety constraints must be configurable without code changes +- The system needs a spectrum from fully manual to fully autonomous, not just a binary auto/manual toggle +- Confidence thresholds should gate transitions so high-confidence operations auto-proceed while uncertain ones prompt the user +- The effective profile must be locked at plan creation to prevent mid-execution behavioral changes +- Common use cases (CI pipelines, supervised mode, manual review) should have sensible built-in presets + ## Decision CleverAgents uses **automation profiles** — named configuration bundles that control autonomy thresholds across the plan lifecycle. Eight built-in profiles span the spectrum from fully manual to fully autonomous. Custom profiles can be created. The effective profile for a plan is resolved via a precedence chain (plan > action > project > global) and is locked to the plan at `plan use` time. @@ -118,36 +153,3 @@ Custom automation profiles are registered via YAML configuration (`agents automa - **Safety constraint tests**: Tests verify that `require_sandbox` and `require_checkpoints` correctly reject non-compliant configurations and tools. - **Built-in profile tests**: Tests verify that all eight built-in profiles produce the expected behavior for standard plan lifecycles. - **BDD scenarios**: Behave features exercise plans under different profiles including transitions between manual approval, auto-proceed, and confidence-gated decisions. - -## Related ADRs - -| ADR | Title | Relationship | -|-----|-------|-------------| -| [ADR-006](ADR-006-plan-lifecycle.md) | Plan Lifecycle | Profiles control which lifecycle phase transitions require human approval | -| [ADR-007](ADR-007-decision-tree-and-correction.md) | Decision Tree and Correction | Confidence thresholds determine which decisions require human intervention | -| [ADR-016](ADR-016-invariant-system.md) | Invariant System | Invariant violation escalation is governed by the active automation profile | -| [ADR-041](ADR-041-safety-profile-extraction.md) | Safety Profile Extraction | Safety constraints are extracted into a composed SafetyProfile sub-model within AutomationProfile | - -## Acceptance - -### Votes For - -| Voter | Comment | -|-------|---------| -| Jeffrey Phillips Freeman | Named profiles with confidence thresholds provide a clean spectrum from full manual to full autonomous control | - -**Total: 1** - -### Votes Against - -| Voter | Comment | -|-------|---------| - -**Total: 0** - -### Abstentions - -| Voter | Comment | -|-------|---------| - -**Total: 0** diff --git a/docs/adr/ADR-018-semantic-error-prevention.md b/docs/adr/ADR-018-semantic-error-prevention.md index 3a1d4abe6..8c2663716 100644 --- a/docs/adr/ADR-018-semantic-error-prevention.md +++ b/docs/adr/ADR-018-semantic-error-prevention.md @@ -1,15 +1,52 @@ -# ADR-018: Semantic Error Prevention - -**Status:** Accepted -**Date:** 2026-02-16 -**Supersedes:** None -**Author(s):** Jeffrey Phillips Freeman -**Approver(s):** Jeffrey Phillips Freeman - +--- +adr_number: 18 +title: Semantic Error Prevention +status_history: +- - '2026-02-16' + - Proposed + - Jeffrey Phillips Freeman +- - '2026-02-16' + - Accepted + - Jeffrey Phillips Freeman +tier: 3 +authors: +- Jeffrey Phillips Freeman +superseded_by: null +related_adrs: +- number: 6 + title: Plan Lifecycle + relationship: Error prevention layers operate at different lifecycle phases +- number: 7 + title: Decision Tree and Correction + relationship: Decision-time validation catches errors during tree construction +- number: 13 + title: Validation Abstraction + relationship: Validation tools implement the execution-time semantic guards +- number: 16 + title: Invariant System + relationship: Invariant enforcement is one of the four error prevention layers +- number: 17 + title: Automation Profiles + relationship: Low-confidence decisions are flagged based on automation profile thresholds +acceptance: + votes_for: + - voter: Jeffrey Phillips Freeman + comment: Multiple prevention layers operating at different lifecycle points catch errors progressively earlier + votes_against: [] + abstentions: [] +--- ## Context LLM-driven systems can produce errors that are syntactically valid but semantically wrong — choosing an incompatible library version, applying a pattern that contradicts project conventions, or making a decision that violates an upstream constraint. Traditional testing catches many errors after the fact, but the cost of fixing errors increases dramatically the later they are caught. The system needs multiple layers of error prevention that operate at different points in the lifecycle — from decision time through execution to predictive analysis. +## Decision Drivers + +- LLM-driven systems produce errors that are syntactically valid but semantically wrong (incompatible versions, convention violations) +- The cost of fixing errors increases dramatically the later they are caught in the lifecycle +- Different error types are detectable at different lifecycle points (decision-time, execution-time, post-execution) +- Error prevention must respect automation profile thresholds to ensure appropriate human involvement +- Historical correction data should improve future error detection, not be discarded after each plan + ## Decision CleverAgents implements **four layers of semantic error prevention** that operate progressively through the plan lifecycle: decision-time validation during Strategize, execution-time semantic guards, invariant enforcement across all phases, and predictive error prevention using historical data and pattern matching. @@ -100,37 +137,3 @@ The severity classification depends on the confidence score, the automation prof - **Guard performance tests**: Benchmarks verify that execution-time guards add acceptable latency (targets defined in ASV benchmarks). - **False positive tracking**: Metrics track false positive rates for each layer, enabling tuning. - **Integration tests**: BDD scenarios exercise multi-layer error detection including decision-time validation failure, execution-time guard intervention, invariant violation, and predictive warnings. - -## Related ADRs - -| ADR | Title | Relationship | -|-----|-------|-------------| -| [ADR-006](ADR-006-plan-lifecycle.md) | Plan Lifecycle | Error prevention layers operate at different lifecycle phases | -| [ADR-007](ADR-007-decision-tree-and-correction.md) | Decision Tree and Correction | Decision-time validation catches errors during tree construction | -| [ADR-013](ADR-013-validation-abstraction.md) | Validation Abstraction | Validation tools implement the execution-time semantic guards | -| [ADR-016](ADR-016-invariant-system.md) | Invariant System | Invariant enforcement is one of the four error prevention layers | -| [ADR-017](ADR-017-automation-profiles.md) | Automation Profiles | Low-confidence decisions are flagged based on automation profile thresholds | - -## Acceptance - -### Votes For - -| Voter | Comment | -|-------|---------| -| Jeffrey Phillips Freeman | Multiple prevention layers operating at different lifecycle points catch errors progressively earlier | - -**Total: 1** - -### Votes Against - -| Voter | Comment | -|-------|---------| - -**Total: 0** - -### Abstentions - -| Voter | Comment | -|-------|---------| - -**Total: 0** diff --git a/docs/adr/ADR-019-storage-and-persistence.md b/docs/adr/ADR-019-storage-and-persistence.md index ea580da16..f25ef80b5 100644 --- a/docs/adr/ADR-019-storage-and-persistence.md +++ b/docs/adr/ADR-019-storage-and-persistence.md @@ -1,15 +1,49 @@ -# ADR-019: Storage and Persistence - -**Status:** Accepted -**Date:** 2026-02-16 -**Supersedes:** None -**Author(s):** Jeffrey Phillips Freeman -**Approver(s):** Jeffrey Phillips Freeman - +--- +adr_number: 19 +title: Storage and Persistence +status_history: +- - '2026-02-16' + - Proposed + - Jeffrey Phillips Freeman +- - '2026-02-16' + - Accepted + - Jeffrey Phillips Freeman +tier: 3 +authors: +- Jeffrey Phillips Freeman +superseded_by: null +related_adrs: +- number: 1 + title: Layered Architecture + relationship: Persistence adapters reside in the Infrastructure Layer behind domain ports +- number: 3 + title: Dependency Injection + relationship: Repository implementations are injected via the DI container +- number: 4 + title: Data Validation + relationship: Pydantic models define the schemas that map to SQLAlchemy ORM models +- number: 5 + title: Technical Stack + relationship: SQLAlchemy, SQLite, and PostgreSQL are the chosen persistence technologies +acceptance: + votes_for: + - voter: Jeffrey Phillips Freeman + comment: Repository pattern with Unit of Work and dual-database support covers both local and server deployment cleanly + votes_against: [] + abstentions: [] +--- ## Context CleverAgents must persist a rich data model — plans with hierarchical decision trees, resources with DAG relationships, actors, tools, skills, sessions, invariants, automation profiles, checkpoints, correction attempts, and more. The persistence layer must support local single-user mode (zero-configuration) and server multi-user mode (concurrent access). It must integrate with the layered architecture, supporting repository pattern interfaces in the domain layer and concrete implementations in the infrastructure layer. +## Decision Drivers + +- Local single-user mode requires zero-configuration storage with no external database server +- Server multi-user mode requires concurrent access and connection pooling (PostgreSQL) +- Domain layer code must remain decoupled from persistence mechanics via repository interfaces +- A rich data model (plans, decision trees, resources, actors, sessions, checkpoints) needs version-controlled schema migrations +- Entity IDs must be globally unique and lexicographically sortable by creation time without coordination + ## Decision CleverAgents uses **SQLite** as the primary database for local mode and **SQLAlchemy** as the ORM for database abstraction across all modes. The infrastructure layer implements the **repository pattern** with **Unit of Work** for transactional consistency. **Alembic** manages version-controlled schema migrations. IDs use **ULIDs** for lexicographically sortable, time-ordered identification. @@ -123,36 +157,3 @@ For server mode, the infrastructure layer swaps SQLite for PostgreSQL via the sa - **ULID ordering tests**: Tests verify that ULID-based queries return results in creation-time order. - **Concurrency tests**: Tests verify that concurrent read operations work correctly under WAL mode. - **Backup/restore tests**: Tests verify that backup creation and restoration produce consistent database state. - -## Related ADRs - -| ADR | Title | Relationship | -|-----|-------|-------------| -| [ADR-001](ADR-001-layered-architecture.md) | Layered Architecture | Persistence adapters reside in the Infrastructure Layer behind domain ports | -| [ADR-003](ADR-003-dependency-injection.md) | Dependency Injection | Repository implementations are injected via the DI container | -| [ADR-004](ADR-004-data-validation.md) | Data Validation | Pydantic models define the schemas that map to SQLAlchemy ORM models | -| [ADR-005](ADR-005-technical-stack.md) | Technical Stack | SQLAlchemy, SQLite, and PostgreSQL are the chosen persistence technologies | - -## Acceptance - -### Votes For - -| Voter | Comment | -|-------|---------| -| Jeffrey Phillips Freeman | Repository pattern with Unit of Work and dual-database support covers both local and server deployment cleanly | - -**Total: 1** - -### Votes Against - -| Voter | Comment | -|-------|---------| - -**Total: 0** - -### Abstentions - -| Voter | Comment | -|-------|---------| - -**Total: 0** diff --git a/docs/adr/ADR-020-session-model.md b/docs/adr/ADR-020-session-model.md index 52b91d766..f4e972c5d 100644 --- a/docs/adr/ADR-020-session-model.md +++ b/docs/adr/ADR-020-session-model.md @@ -1,15 +1,49 @@ -# ADR-020: Session Model - -**Status:** Accepted -**Date:** 2026-02-16 -**Supersedes:** None -**Author(s):** Jeffrey Phillips Freeman -**Approver(s):** Jeffrey Phillips Freeman - +--- +adr_number: 20 +title: Session Model +status_history: +- - '2026-02-16' + - Proposed + - Jeffrey Phillips Freeman +- - '2026-02-16' + - Accepted + - Jeffrey Phillips Freeman +tier: 3 +authors: +- Jeffrey Phillips Freeman +superseded_by: null +related_adrs: +- number: 6 + title: Plan Lifecycle + relationship: Plans execute within sessions and inherit session-scoped context +- number: 10 + title: Actor and Agent Architecture + relationship: Sessions bind a user to an orchestrator actor for conversation +- number: 14 + title: Context Management (ACMS) + relationship: Sessions maintain session-scoped context tiers and conversation history +- number: 26 + title: Agent Client Protocol (ACP) + relationship: ACP exposes session lifecycle operations to all clients +acceptance: + votes_for: + - voter: Jeffrey Phillips Freeman + comment: Sessions as persistent conversation threads with cost budgets and context scoping tie the user experience together + votes_against: [] + abstentions: [] +--- ## Context Users interact with CleverAgents through conversations — asking questions, giving instructions, reviewing plan outputs, and providing corrections. These conversations need persistent state: the current orchestrator actor, the conversation history, the active plan context, and accumulated knowledge. The system needs a session abstraction that binds a conversation to an orchestrator actor and provides session-scoped context, budgets, and lifecycle management. +## Decision Drivers + +- Conversations must persist across CLI restarts so users can resume multi-turn interactions +- Each session needs a bound orchestrator actor that provides a consistent conversational personality +- Session-scoped cost budgets must aggregate across all plans within a session to prevent cost overruns +- Accumulated knowledge and conversation history must be available across plan boundaries within a session +- Session lifecycle (create, resume, archive) must be explicitly manageable by users + ## Decision A **session** is a persistent conversation thread that binds a user to an **orchestrator actor** and provides session-scoped context, cost budgets, and conversation history. Sessions are the top-level interactive abstraction — plans are executed within the context of a session. @@ -106,36 +140,3 @@ Plans are executed within sessions. A session may have multiple active plans (se - **Persistence tests**: Tests verify that conversation history survives CLI restarts and is correctly loaded on session resumption. - **Orchestrator binding tests**: Tests verify that the orchestrator actor is correctly bound at creation and that all session interactions route through it. - **Cleanup tests**: Tests verify that session archival correctly marks sessions as inactive without data loss. - -## Related ADRs - -| ADR | Title | Relationship | -|-----|-------|-------------| -| [ADR-006](ADR-006-plan-lifecycle.md) | Plan Lifecycle | Plans execute within sessions and inherit session-scoped context | -| [ADR-010](ADR-010-actor-and-agent-architecture.md) | Actor and Agent Architecture | Sessions bind a user to an orchestrator actor for conversation | -| [ADR-014](ADR-014-context-management-acms.md) | Context Management (ACMS) | Sessions maintain session-scoped context tiers and conversation history | -| [ADR-026](ADR-026-agent-client-protocol.md) | Agent Client Protocol (ACP) | ACP exposes session lifecycle operations to all clients | - -## Acceptance - -### Votes For - -| Voter | Comment | -|-------|---------| -| Jeffrey Phillips Freeman | Sessions as persistent conversation threads with cost budgets and context scoping tie the user experience together | - -**Total: 1** - -### Votes Against - -| Voter | Comment | -|-------|---------| - -**Total: 0** - -### Abstentions - -| Voter | Comment | -|-------|---------| - -**Total: 0** diff --git a/docs/adr/ADR-021-cli-and-output-rendering.md b/docs/adr/ADR-021-cli-and-output-rendering.md index 5bb70e051..e574af82c 100644 --- a/docs/adr/ADR-021-cli-and-output-rendering.md +++ b/docs/adr/ADR-021-cli-and-output-rendering.md @@ -1,15 +1,46 @@ -# ADR-021: CLI and Output Rendering - -**Status:** Accepted -**Date:** 2026-02-16 -**Supersedes:** None -**Author(s):** Jeffrey Phillips Freeman -**Approver(s):** Jeffrey Phillips Freeman - +--- +adr_number: 21 +title: CLI and Output Rendering +status_history: +- - '2026-02-16' + - Proposed + - Jeffrey Phillips Freeman +- - '2026-02-16' + - Accepted + - Jeffrey Phillips Freeman +tier: 4 +authors: +- Jeffrey Phillips Freeman +superseded_by: null +related_adrs: +- number: 1 + title: Layered Architecture + relationship: The CLI resides in the Presentation Layer and calls into Application Layer facades +- number: 5 + title: Technical Stack + relationship: Typer and Rich are the chosen CLI and rendering libraries +- number: 24 + title: Configuration System + relationship: CLI flags participate in the five-tier configuration resolution chain +acceptance: + votes_for: + - voter: Jeffrey Phillips Freeman + comment: The noun-verb command pattern with six output formats covers both human and machine consumers well + votes_against: [] + abstentions: [] +--- ## Context CleverAgents is a CLI-first application. The command-line interface is the primary entry point for all user interaction — creating actions, managing projects, executing plans, configuring the system, and reviewing results. The CLI must support a large number of entity types and operations, provide consistent command structure, and render output in multiple formats (human-readable terminal output, structured JSON/YAML for scripting, plain text for piping). +## Decision Drivers + +- The CLI is the primary entry point for all user interaction and must scale to many entity types and operations +- Output must serve both human consumers (styled terminal) and machine consumers (JSON/YAML for scripting) +- Command structure must be consistent and predictable across a large number of entity types +- Entity definitions must be versionable and reviewable, favoring YAML-first registration over CLI-only creation +- Log output and structured command output must be cleanly separated (stderr vs. stdout) + ## Decision The CLI uses **Typer** (>= 0.9.0) with the `agents ` command pattern. Output rendering supports **six formats** (`rich`, `color`, `table`, `plain`, `json`, `yaml`) selectable via the `--format` flag or `core.format` configuration key. Rich (via Typer's built-in integration) provides styled terminal rendering with panels, tables, trees, syntax highlighting, progress spinners, and markdown. @@ -138,35 +169,3 @@ All presentation surfaces consume the same Application Layer service facades. - **Structured output tests**: Tests verify that `json` and `yaml` outputs are valid, parseable, and contain no non-structured content. - **Stderr separation tests**: Tests verify that `-v` log output goes to stderr and does not appear in stdout when `--format json` is used. - **BDD scenarios**: Behave features exercise CLI workflows end-to-end with various format options. - -## Related ADRs - -| ADR | Title | Relationship | -|-----|-------|-------------| -| [ADR-001](ADR-001-layered-architecture.md) | Layered Architecture | The CLI resides in the Presentation Layer and calls into Application Layer facades | -| [ADR-005](ADR-005-technical-stack.md) | Technical Stack | Typer and Rich are the chosen CLI and rendering libraries | -| [ADR-024](ADR-024-configuration-system.md) | Configuration System | CLI flags participate in the five-tier configuration resolution chain | - -## Acceptance - -### Votes For - -| Voter | Comment | -|-------|---------| -| Jeffrey Phillips Freeman | The noun-verb command pattern with six output formats covers both human and machine consumers well | - -**Total: 1** - -### Votes Against - -| Voter | Comment | -|-------|---------| - -**Total: 0** - -### Abstentions - -| Voter | Comment | -|-------|---------| - -**Total: 0** diff --git a/docs/adr/ADR-022-langchain-langgraph-integration.md b/docs/adr/ADR-022-langchain-langgraph-integration.md index f9315b1e1..947da2a11 100644 --- a/docs/adr/ADR-022-langchain-langgraph-integration.md +++ b/docs/adr/ADR-022-langchain-langgraph-integration.md @@ -1,15 +1,55 @@ -# ADR-022: LangChain/LangGraph Integration - -**Status:** Accepted -**Date:** 2026-02-16 -**Supersedes:** None -**Author(s):** Jeffrey Phillips Freeman -**Approver(s):** Jeffrey Phillips Freeman - +--- +adr_number: 22 +title: LangChain/LangGraph Integration +status_history: +- - '2026-02-16' + - Proposed + - Jeffrey Phillips Freeman +- - '2026-02-16' + - Accepted + - Jeffrey Phillips Freeman +tier: 4 +authors: +- Jeffrey Phillips Freeman +superseded_by: null +related_adrs: +- number: 1 + title: Layered Architecture + relationship: LangChain/LangGraph implementations reside in the Infrastructure Layer +- number: 3 + title: Dependency Injection + relationship: LLM providers and LangGraph components are registered through the DI container +- number: 5 + title: Technical Stack + relationship: LangChain and LangGraph are core stack choices for LLM orchestration +- number: 10 + title: Actor and Agent Architecture + relationship: Actors are implemented as LangGraph StateGraph instances +- number: 29 + title: Model Context Protocol (MCP) Adoption + relationship: MCP SDK is part of the LLM runtime stack; MCPToolAdapter bridges MCP tools to LangGraph tool nodes +- number: 31 + title: Actor Abstraction Definition + relationship: Actors are implemented as LangGraph StateGraph instances; LangGraph is the actor graph runtime +acceptance: + votes_for: + - voter: Jeffrey Phillips Freeman + comment: LangChain for provider abstraction and LangGraph for stateful orchestration are the best fit for our actor model + votes_against: [] + abstentions: [] +--- ## Context CleverAgents must orchestrate LLM interactions across multiple providers (OpenAI, Anthropic, Google, Groq, Together, Cohere, Azure), manage stateful multi-step workflows (plan generation graphs, auto-debug loops), support tool calling, prompt templating, output parsing, and streaming execution. Building these capabilities from scratch would be a massive engineering effort and would not benefit from the rapidly evolving LLM ecosystem. The system needs a provider-agnostic abstraction layer and a stateful workflow orchestration framework. +## Decision Drivers + +- Must support 6+ LLM providers (OpenAI, Anthropic, Google, Groq, Together, Cohere) without provider-specific code in the application layer +- Actors require stateful multi-step workflows with conditional routing, checkpointing, and streaming execution +- Building provider abstraction, tool calling, prompt templating, and output parsing from scratch is prohibitively expensive +- Actor graphs need checkpointing for resume-after-interruption and decision replay +- Reactive event streams must bridge with synchronous graph execution for concurrent plan coordination + ## Decision CleverAgents uses **LangChain** (>= 0.2.14) as the provider-agnostic LLM abstraction layer and **LangGraph** (transitive dependency) for stateful workflow orchestration. LangChain provides the `BaseLanguageModel` protocol for swappable providers, while LangGraph provides `StateGraph` with conditional edges, checkpointing, and streaming execution. **RxPY** (>= 3.2.0) bridges reactive event streams with LangGraph state graphs. @@ -103,38 +143,3 @@ LangChain Community provides `FakeListLLM` and `FakeEmbeddings` for testing with - **Checkpoint tests**: Tests verify that LangGraph checkpoints can be saved, loaded, and used for decision replay. - **Mock provider tests**: Tests verify that `FakeListLLM` and `FakeEmbeddings` produce deterministic results suitable for unit and integration testing. - **RxPY integration tests**: Tests verify that reactive streams correctly bridge with LangGraph execution and that backpressure is managed under concurrent load. - -## Related ADRs - -| ADR | Title | Relationship | -|-----|-------|-------------| -| [ADR-001](ADR-001-layered-architecture.md) | Layered Architecture | LangChain/LangGraph implementations reside in the Infrastructure Layer | -| [ADR-003](ADR-003-dependency-injection.md) | Dependency Injection | LLM providers and LangGraph components are registered through the DI container | -| [ADR-005](ADR-005-technical-stack.md) | Technical Stack | LangChain and LangGraph are core stack choices for LLM orchestration | -| [ADR-010](ADR-010-actor-and-agent-architecture.md) | Actor and Agent Architecture | Actors are implemented as LangGraph StateGraph instances | -| [ADR-029](ADR-029-model-context-protocol.md) | Model Context Protocol (MCP) Adoption | MCP SDK is part of the LLM runtime stack; MCPToolAdapter bridges MCP tools to LangGraph tool nodes | -| [ADR-031](ADR-031-actor-abstraction-definition.md) | Actor Abstraction Definition | Actors are implemented as LangGraph StateGraph instances; LangGraph is the actor graph runtime | - -## Acceptance - -### Votes For - -| Voter | Comment | -|-------|---------| -| Jeffrey Phillips Freeman | LangChain for provider abstraction and LangGraph for stateful orchestration are the best fit for our actor model | - -**Total: 1** - -### Votes Against - -| Voter | Comment | -|-------|---------| - -**Total: 0** - -### Abstentions - -| Voter | Comment | -|-------|---------| - -**Total: 0** diff --git a/docs/adr/ADR-023-server-mode.md b/docs/adr/ADR-023-server-mode.md index e9e48958b..3b9afd8e1 100644 --- a/docs/adr/ADR-023-server-mode.md +++ b/docs/adr/ADR-023-server-mode.md @@ -1,15 +1,53 @@ -# ADR-023: Server Mode - -**Status:** Accepted -**Date:** 2026-02-16 -**Supersedes:** None -**Author(s):** Jeffrey Phillips Freeman -**Approver(s):** Jeffrey Phillips Freeman - +--- +adr_number: 23 +title: Server Mode +status_history: +- - '2026-02-16' + - Proposed + - Jeffrey Phillips Freeman +- - '2026-02-16' + - Accepted + - Jeffrey Phillips Freeman +tier: 4 +authors: +- Jeffrey Phillips Freeman +superseded_by: null +related_adrs: +- number: 1 + title: Layered Architecture + relationship: Both deployment modes share Domain and Application layers, differing only in Presentation and Infrastructure +- number: 2 + title: Namespace System + relationship: Server mode introduces server-prefixed namespaces for multi-server entity resolution +- number: 5 + title: Technical Stack + relationship: FastAPI, uvicorn, and Helm/Kubernetes are the server mode stack choices +- number: 19 + title: Storage and Persistence + relationship: Server mode uses PostgreSQL instead of SQLite for multi-user persistence +- number: 26 + title: Agent Client Protocol (ACP) + relationship: ACP is the client-server contract implemented by the REST API in server mode; its transport duality (in-process facade for local, HTTPS + JSON for server) is the mechanism that keeps both + modes behaviorally identical +acceptance: + votes_for: + - voter: Jeffrey Phillips Freeman + comment: Sharing Domain and Application layers across both modes maximizes code reuse and behavioral consistency + votes_against: [] + abstentions: [] +--- ## Context CleverAgents starts as a single-user local CLI tool, but the specification envisions a collaborative multi-user deployment where teams share entity definitions, execute plans on shared infrastructure, and collaborate on projects. The system needs a server deployment mode that enables this without requiring a separate codebase — the same domain and application layers must support both local and server modes. +## Decision Drivers + +- The same domain and application logic must run identically in both single-user local and multi-user server deployments +- Teams need to share entity definitions, execute plans on shared infrastructure, and collaborate without maintaining separate codebases +- Local mode must work fully offline with zero server dependency +- Client and server must share namespaces and resolve names identically regardless of deployment mode +- Infrastructure concerns (database, sandbox, transport) must be swappable without touching domain or application code + ## Decision CleverAgents supports two deployment modes that share the same Domain and Application layers. **Local mode** is a single-process CLI application with SQLite storage. **Server mode** is a multi-user service where the CLI acts as a thin client communicating with a remote server over HTTPS. The Infrastructure Layer provides swappable implementations for each mode, enabled by the hexagonal architecture (ADR-001). @@ -118,37 +156,3 @@ The key architectural enabler is the hexagonal pattern (ADR-001): - **Offline functionality tests**: Tests verify that local mode works completely without network access. - **Sync tests**: Integration tests verify entity sync behavior including auto-sync, manual sync, and conflict handling. - **Authentication tests**: Tests verify that server API calls require valid tokens and that unauthenticated requests are rejected. - -## Related ADRs - -| ADR | Title | Relationship | -|-----|-------|-------------| -| [ADR-001](ADR-001-layered-architecture.md) | Layered Architecture | Both deployment modes share Domain and Application layers, differing only in Presentation and Infrastructure | -| [ADR-002](ADR-002-namespace-system.md) | Namespace System | Server mode introduces server-prefixed namespaces for multi-server entity resolution | -| [ADR-005](ADR-005-technical-stack.md) | Technical Stack | FastAPI, uvicorn, and Helm/Kubernetes are the server mode stack choices | -| [ADR-019](ADR-019-storage-and-persistence.md) | Storage and Persistence | Server mode uses PostgreSQL instead of SQLite for multi-user persistence | -| [ADR-026](ADR-026-agent-client-protocol.md) | Agent Client Protocol (ACP) | ACP is the client-server contract implemented by the REST API in server mode; its transport duality (in-process facade for local, HTTPS + JSON for server) is the mechanism that keeps both modes behaviorally identical | - -## Acceptance - -### Votes For - -| Voter | Comment | -|-------|---------| -| Jeffrey Phillips Freeman | Sharing Domain and Application layers across both modes maximizes code reuse and behavioral consistency | - -**Total: 1** - -### Votes Against - -| Voter | Comment | -|-------|---------| - -**Total: 0** - -### Abstentions - -| Voter | Comment | -|-------|---------| - -**Total: 0** diff --git a/docs/adr/ADR-024-configuration-system.md b/docs/adr/ADR-024-configuration-system.md index 3dddf1680..680f29e47 100644 --- a/docs/adr/ADR-024-configuration-system.md +++ b/docs/adr/ADR-024-configuration-system.md @@ -1,15 +1,50 @@ -# ADR-024: Configuration System - -**Status:** Accepted -**Date:** 2026-02-16 -**Supersedes:** None -**Author(s):** Jeffrey Phillips Freeman -**Approver(s):** Jeffrey Phillips Freeman - +--- +adr_number: 24 +title: Configuration System +status_history: +- - '2026-02-16' + - Proposed + - Jeffrey Phillips Freeman +- - '2026-02-16' + - Accepted + - Jeffrey Phillips Freeman +tier: 4 +authors: +- Jeffrey Phillips Freeman +superseded_by: null +related_adrs: +- number: 4 + title: Data Validation + relationship: Pydantic Settings validates and loads configuration values +- number: 5 + title: Technical Stack + relationship: TOML and YAML are the chosen configuration file formats +- number: 9 + title: Project Model + relationship: Projects define project-scoped configuration overrides in the resolution chain +- number: 17 + title: Automation Profiles + relationship: Automation profiles are selected and configured through the configuration system +acceptance: + votes_for: + - voter: Jeffrey Phillips Freeman + comment: Dual-format configuration with a five-tier resolution chain covers all override scenarios cleanly + votes_against: [] + abstentions: [] +--- ## Context CleverAgents has a large number of configurable settings — output format, log level, sandbox strategy, context budgets, provider credentials, index backends, and more. These settings must be manageable through multiple channels (CLI flags, environment variables, configuration files) with a clear precedence order. Entity definitions (actors, tools, skills, actions, resource types) also need a configuration format. The system needs a configuration architecture that supports hierarchical keys, project-scoped overrides, environment variable interpolation, and a clean separation between global system settings and entity definitions. +## Decision Drivers + +- Settings span many domains (output format, log level, sandbox strategy, credentials, context budgets) and must be manageable through CLI flags, environment variables, and files with clear precedence +- Entity definitions (actors, tools, skills, actions) require a structured format capable of expressing complex nested configurations +- Projects need scoped overrides so different teams or codebases can customize behavior without modifying global settings +- The system must function out of the box with zero configuration via sensible defaults +- Provider credentials require ecosystem-compatible environment variable names (e.g., `OPENAI_API_KEY`) while system settings use a consistent prefix +- Hierarchical dot-path keys must map naturally to the configuration file format's native structure + ## Decision CleverAgents uses a **dual-format configuration system**: **TOML** for global system configuration (managed via `agents config` CLI) with **dot-path hierarchical keys**, and **YAML** for entity configuration files (actors, tools, skills, actions, resource types, automation profiles, context views). A five-tier resolution chain determines the effective value for each setting: CLI flag > environment variable > project-scoped config > global config file > built-in default. @@ -138,36 +173,3 @@ Default behavior requires zero configuration. The system ships with sensible def - **YAML validation tests**: Tests verify that entity YAML files are validated completely and that invalid configurations are rejected with actionable error messages. - **Credential safety tests**: Tests verify that provider credential keys are masked in `agents config list` output and never appear in log output. - **Environment interpolation tests**: Tests verify that `${ENV_VAR}` syntax is correctly resolved in YAML entity files. - -## Related ADRs - -| ADR | Title | Relationship | -|-----|-------|-------------| -| [ADR-004](ADR-004-data-validation.md) | Data Validation | Pydantic Settings validates and loads configuration values | -| [ADR-005](ADR-005-technical-stack.md) | Technical Stack | TOML and YAML are the chosen configuration file formats | -| [ADR-009](ADR-009-project-model.md) | Project Model | Projects define project-scoped configuration overrides in the resolution chain | -| [ADR-017](ADR-017-automation-profiles.md) | Automation Profiles | Automation profiles are selected and configured through the configuration system | - -## Acceptance - -### Votes For - -| Voter | Comment | -|-------|---------| -| Jeffrey Phillips Freeman | Dual-format configuration with a five-tier resolution chain covers all override scenarios cleanly | - -**Total: 1** - -### Votes Against - -| Voter | Comment | -|-------|---------| - -**Total: 0** - -### Abstentions - -| Voter | Comment | -|-------|---------| - -**Total: 0** diff --git a/docs/adr/ADR-025-observability-and-logging.md b/docs/adr/ADR-025-observability-and-logging.md index da5e017bf..093cf22aa 100644 --- a/docs/adr/ADR-025-observability-and-logging.md +++ b/docs/adr/ADR-025-observability-and-logging.md @@ -1,15 +1,46 @@ -# ADR-025: Observability and Logging - -**Status:** Accepted -**Date:** 2026-02-16 -**Supersedes:** None -**Author(s):** Jeffrey Phillips Freeman -**Approver(s):** Jeffrey Phillips Freeman - +--- +adr_number: 25 +title: Observability and Logging +status_history: +- - '2026-02-16' + - Proposed + - Jeffrey Phillips Freeman +- - '2026-02-16' + - Accepted + - Jeffrey Phillips Freeman +tier: 4 +authors: +- Jeffrey Phillips Freeman +superseded_by: null +related_adrs: +- number: 1 + title: Layered Architecture + relationship: Logging is a cross-cutting concern handled through the event bus in the Application Layer +- number: 5 + title: Technical Stack + relationship: structlog is the chosen structured logging library +- number: 24 + title: Configuration System + relationship: Log verbosity levels are controlled through the configuration system and CLI flags +acceptance: + votes_for: + - voter: Jeffrey Phillips Freeman + comment: Structured JSON logging with context binding gives us the observability needed for debugging LLM-driven workflows + votes_against: [] + abstentions: [] +--- ## Context CleverAgents orchestrates complex, multi-step AI workflows involving LLM calls, tool invocations, plan hierarchies, and concurrent execution. When something goes wrong — a plan fails, a tool produces unexpected output, an LLM makes a bad decision — the operator needs to trace the chain of events, understand the context, and identify the root cause. Traditional unstructured logging is insufficient for correlating events across plan hierarchies, actor invocations, and tool calls. +## Decision Drivers + +- Multi-step AI workflows (LLM calls, tool invocations, plan hierarchies, concurrent execution) require correlated tracing across nested scopes to diagnose failures +- Log events must carry contextual identifiers (plan_id, actor_name, decision_id, tool_name) for structured querying and filtering +- Log output must not contaminate structured command output on stdout; logs and results must flow through separate streams +- LLM-specific observability (token usage, latency, cost) is needed but must remain optional and not create a hard dependency +- Default verbosity must be minimal (FATAL-only) with intuitive CLI-flag escalation for debugging + ## Decision CleverAgents uses **structlog** (>= 24.4.0) for structured JSON logging with context binding. Every log event carries contextual identifiers (`plan_id`, `decision_id`, `actor_name`, `tool_name`) that enable correlation across the plan lifecycle. Optional **LangSmith** integration provides LLM-specific observability (tracing, token usage, latency, cost). @@ -130,35 +161,3 @@ Metrics are exposed through structured log events and are available for performa - **Stderr separation tests**: Tests verify that log output goes to stderr and does not appear in stdout regardless of verbosity level. - **Retention tests**: Tests verify that log file cleanup correctly removes files older than the configured retention period. - **LangSmith opt-in tests**: Tests verify that the system functions correctly without LangSmith configured and that enabling LangSmith produces the expected traces. - -## Related ADRs - -| ADR | Title | Relationship | -|-----|-------|-------------| -| [ADR-001](ADR-001-layered-architecture.md) | Layered Architecture | Logging is a cross-cutting concern handled through the event bus in the Application Layer | -| [ADR-005](ADR-005-technical-stack.md) | Technical Stack | structlog is the chosen structured logging library | -| [ADR-024](ADR-024-configuration-system.md) | Configuration System | Log verbosity levels are controlled through the configuration system and CLI flags | - -## Acceptance - -### Votes For - -| Voter | Comment | -|-------|---------| -| Jeffrey Phillips Freeman | Structured JSON logging with context binding gives us the observability needed for debugging LLM-driven workflows | - -**Total: 1** - -### Votes Against - -| Voter | Comment | -|-------|---------| - -**Total: 0** - -### Abstentions - -| Voter | Comment | -|-------|---------| - -**Total: 0** diff --git a/docs/adr/ADR-026-agent-client-protocol.md b/docs/adr/ADR-026-agent-client-protocol.md index f860cae40..786d76b68 100644 --- a/docs/adr/ADR-026-agent-client-protocol.md +++ b/docs/adr/ADR-026-agent-client-protocol.md @@ -1,15 +1,58 @@ -# ADR-026: Agent Client Protocol (ACP) - -**Status:** Accepted -**Date:** 2026-02-17 -**Supersedes:** None -**Author(s):** Jeffrey Phillips Freeman -**Approver(s):** Jeffrey Phillips Freeman - +--- +adr_number: 26 +title: Agent Client Protocol (ACP) +status_history: +- - '2026-02-17' + - Proposed + - Jeffrey Phillips Freeman +- - '2026-02-17' + - Accepted + - Jeffrey Phillips Freeman +tier: 4 +authors: +- Jeffrey Phillips Freeman +superseded_by: null +related_adrs: +- number: 1 + title: Layered Architecture + relationship: ACP defines the fundamental boundary between the Presentation and Application layers in the four-layer architecture +- number: 6 + title: Plan Lifecycle + relationship: ACP's plan operation group exposes the full plan lifecycle (use, execute, apply, cancel, correct, rollback) to all clients +- number: 20 + title: Session Model + relationship: ACP defines the session lifecycle operations (create, tell, export, import) exposed to clients +- number: 21 + title: CLI and Output Rendering + relationship: Every CLI command maps 1:1 to an ACP operation; the CLI is a thin rendering layer over ACP +- number: 23 + title: Server Mode + relationship: ACP is the client-server contract implemented by the REST API in server mode; the transport duality (local facade vs HTTPS) is the mechanism that keeps both modes behaviorally identical +- number: 25 + title: Observability and Logging + relationship: ACP event streaming delivers structured log events and plan state changes to subscribed clients +- number: 27 + title: Language Server Protocol (LSP) Integration + relationship: LSP servers are Infrastructure-layer components attached to actors; the IDE plugin (Presentation layer) communicates through ACP independently of LSP +acceptance: + votes_for: + - voter: Jeffrey Phillips Freeman + comment: ACP provides the standardized agent-to-agent communication layer needed for multi-actor orchestration + votes_against: [] + abstentions: [] +--- ## Context CleverAgents is accessed through multiple presentation-layer clients — CLI, TUI, Web, and an IDE plugin — and can operate in both local (single-process) and server (multi-user HTTPS) modes. Without a shared, versioned contract between clients and the backend, each client would require bespoke integration code that drifts from the core domain model, making interoperability fragile and third-party client development impractical. The architecture needs a single protocol surface that all clients rely on regardless of deployment mode. +## Decision Drivers + +- Multiple presentation-layer clients (CLI, TUI, Web, IDE plugin) must share a single, versioned contract to avoid bespoke integration code that drifts from the core domain model +- Local (in-process) and server (HTTPS) deployment modes must expose identical operational semantics to all clients +- Third-party client development must be practical without knowledge of internal domain or infrastructure services +- Long-running operations (plan execution, tool invocations) require real-time event streaming with causal ordering guarantees +- The protocol must support backward-compatible evolution so existing clients are not broken by new features + ## Decision CleverAgents adopts the **Agent Client Protocol (ACP)** as the versioned contract governing all client-to-backend communication. ACP defines canonical operations for sessions, plans, registries, context, and event streaming. In local mode ACP maps to in-process service facade calls; in server mode it is implemented by the REST API over HTTPS. @@ -203,39 +246,3 @@ Each ACP operation group maps to an Application-layer service. The complete oper - **Authentication tests**: Verify token enforcement and namespace authorization in server mode. - **Streaming tests**: Ensure event ordering and schema compliance for SSE event payloads. - **Bypass detection**: Architecture tests verify that no Presentation-layer module imports from the Infrastructure layer directly. - -## Related ADRs - -| ADR | Title | Relationship | -|-----|-------|-------------| -| [ADR-001](ADR-001-layered-architecture.md) | Layered Architecture | ACP defines the fundamental boundary between the Presentation and Application layers in the four-layer architecture | -| [ADR-006](ADR-006-plan-lifecycle.md) | Plan Lifecycle | ACP's plan operation group exposes the full plan lifecycle (use, execute, apply, cancel, correct, rollback) to all clients | -| [ADR-020](ADR-020-session-model.md) | Session Model | ACP defines the session lifecycle operations (create, tell, export, import) exposed to clients | -| [ADR-021](ADR-021-cli-and-output-rendering.md) | CLI and Output Rendering | Every CLI command maps 1:1 to an ACP operation; the CLI is a thin rendering layer over ACP | -| [ADR-023](ADR-023-server-mode.md) | Server Mode | ACP is the client-server contract implemented by the REST API in server mode; the transport duality (local facade vs HTTPS) is the mechanism that keeps both modes behaviorally identical | -| [ADR-025](ADR-025-observability-and-logging.md) | Observability and Logging | ACP event streaming delivers structured log events and plan state changes to subscribed clients | -| [ADR-027](ADR-027-language-server-protocol.md) | Language Server Protocol (LSP) Integration | LSP servers are Infrastructure-layer components attached to actors; the IDE plugin (Presentation layer) communicates through ACP independently of LSP | - -## Acceptance - -### Votes For - -| Voter | Comment | -|-------|---------| -| Jeffrey Phillips Freeman | ACP provides the standardized agent-to-agent communication layer needed for multi-actor orchestration | - -**Total: 1** - -### Votes Against - -| Voter | Comment | -|-------|---------| - -**Total: 0** - -### Abstentions - -| Voter | Comment | -|-------|---------| - -**Total: 0** diff --git a/docs/adr/ADR-027-language-server-protocol.md b/docs/adr/ADR-027-language-server-protocol.md index 444c00ff6..8e4096a4e 100644 --- a/docs/adr/ADR-027-language-server-protocol.md +++ b/docs/adr/ADR-027-language-server-protocol.md @@ -1,11 +1,55 @@ -# ADR-027: Language Server Protocol (LSP) Integration - -**Status:** Accepted -**Date:** 2026-02-20 -**Supersedes:** None -**Author(s):** Jeffrey Phillips Freeman -**Approver(s):** Jeffrey Phillips Freeman - +--- +adr_number: 27 +title: Language Server Protocol (LSP) Integration +status_history: +- - '2026-02-20' + - Proposed + - Jeffrey Phillips Freeman +- - '2026-02-20' + - Accepted + - Jeffrey Phillips Freeman +tier: 4 +authors: +- Jeffrey Phillips Freeman +superseded_by: null +related_adrs: +- number: 1 + title: Layered Architecture + relationship: The LSP Runtime resides in the Infrastructure layer; LSP tools are exposed to actors through the Domain layer's tool abstractions +- number: 8 + title: Resource System + relationship: Resources provide the workspace roots for LSP servers and the language discovery inputs for auto-binding +- number: 10 + title: Actor and Agent Architecture + relationship: Actors declare LSP bindings in their YAML configuration; LSP tools participate as capabilities in actor graph nodes +- number: 11 + title: Tool System + relationship: LSP capabilities are exposed as tools through the `LSPToolAdapter`, following the same adapter pattern as MCP +- number: 12 + title: Skill System + relationship: LSP tools complement skill-provided tools in the actor's merged tool surface +- number: 14 + title: Context Management (ACMS) + relationship: LSP context enrichment injects diagnostics and type information into the ACMS hot context +- number: 29 + title: Model Context Protocol (MCP) Adoption + relationship: MCP and LSP follow analogous adapter patterns; both bridge standard protocol servers into the tool system +- number: 31 + title: Actor Abstraction Definition + relationship: Actors acquire language intelligence through LSP bindings alongside tool capabilities through skills +- number: 32 + title: Jinja2 YAML Template Preprocessing + relationship: Jinja2 templates enable dynamic LSP binding resolution in actor YAML files +- number: 40 + title: LSP Resource Types + relationship: ADR-027 defines CleverAgents as an LSP server; ADR-040 defines external LSP servers as resources in the DAG +acceptance: + votes_for: + - voter: Jeffrey Phillips Freeman + comment: Giving actors the same language intelligence that human developers use in IDEs is a force multiplier for code quality — and leveraging the LSP ecosystem avoids reinventing mature tooling + votes_against: [] + abstentions: [] +--- ## Context Actors in CleverAgents that perform software development tasks — writing code, refactoring, reviewing, debugging — operate on source code as raw text. Without semantic understanding of the code they manipulate, actors lack the ability to resolve types, navigate symbol definitions, discover references, identify compilation errors, or understand the structural relationships within a codebase. Human developers gain these capabilities through IDE features powered by language servers. Actors need the same language intelligence to work effectively. @@ -14,6 +58,14 @@ Building bespoke code analysis for each programming language would be prohibitiv CleverAgents should leverage this ecosystem directly, giving actors the same rich language intelligence that human developers enjoy — but integrated into the agent's reasoning loop and tool-calling pipeline rather than into an IDE. +## Decision Drivers + +- Actors performing software development tasks need semantic code understanding (type resolution, symbol navigation, diagnostics) beyond raw text manipulation +- Building bespoke code analysis per language is prohibitively expensive; the LSP ecosystem already provides production-quality servers for virtually every mainstream language +- Language intelligence must integrate into the actor's reasoning loop and tool-calling pipeline, not into an IDE presentation layer +- Actors must be able to work across multiple programming languages without per-language configuration when possible +- LSP capabilities must be available both as explicit tools (on-demand queries) and as automatic context enrichment (injected diagnostics and type information) + ## Decision CleverAgents adopts LSP as the standard protocol for attaching **language intelligence capabilities** to actors and agents. LSP servers are registered in a global **LSP Registry** (namespaced like all other entities), and bound to specific actor graph nodes via YAML configuration. LSP capabilities are exposed to actors as **tools** (via an `LSPToolAdapter`) and as **context enrichment** (automatic injection of diagnostics and type information into the actor's ACMS context). This integration lives in the **Infrastructure layer**, not the Presentation layer — LSP serves the AI agents, not human users in editors. @@ -386,42 +438,3 @@ Both adapters follow the same architectural pattern: a standard protocol server - **Lifecycle tests**: Verify server startup/shutdown, shared instance reference counting, crash recovery and re-synchronization, and sandbox workspace mapping. - **Context enrichment tests**: Confirm that diagnostic injection respects context budgets, handles empty diagnostics, and correctly annotates files in hot context. - **Integration tests**: End-to-end tests where an actor with LSP bindings performs code analysis tasks (find errors, navigate definitions, complete code) and produces correct results using LSP tools. - -## Related ADRs - -| ADR | Title | Relationship | -|-----|-------|-------------| -| [ADR-001](ADR-001-layered-architecture.md) | Layered Architecture | The LSP Runtime resides in the Infrastructure layer; LSP tools are exposed to actors through the Domain layer's tool abstractions | -| [ADR-008](ADR-008-resource-system.md) | Resource System | Resources provide the workspace roots for LSP servers and the language discovery inputs for auto-binding | -| [ADR-010](ADR-010-actor-and-agent-architecture.md) | Actor and Agent Architecture | Actors declare LSP bindings in their YAML configuration; LSP tools participate as capabilities in actor graph nodes | -| [ADR-011](ADR-011-tool-system.md) | Tool System | LSP capabilities are exposed as tools through the `LSPToolAdapter`, following the same adapter pattern as MCP | -| [ADR-012](ADR-012-skill-system.md) | Skill System | LSP tools complement skill-provided tools in the actor's merged tool surface | -| [ADR-014](ADR-014-context-management-acms.md) | Context Management (ACMS) | LSP context enrichment injects diagnostics and type information into the ACMS hot context | -| [ADR-029](ADR-029-model-context-protocol.md) | Model Context Protocol (MCP) Adoption | MCP and LSP follow analogous adapter patterns; both bridge standard protocol servers into the tool system | -| [ADR-031](ADR-031-actor-abstraction-definition.md) | Actor Abstraction Definition | Actors acquire language intelligence through LSP bindings alongside tool capabilities through skills | -| [ADR-032](ADR-032-jinja2-yaml-template-preprocessing.md) | Jinja2 YAML Template Preprocessing | Jinja2 templates enable dynamic LSP binding resolution in actor YAML files | -| [ADR-040](ADR-040-lsp-resource-types.md) | LSP Resource Types | ADR-027 defines CleverAgents as an LSP server; ADR-040 defines external LSP servers as resources in the DAG | - -## Acceptance - -### Votes For - -| Voter | Comment | -|-------|---------| -| Jeffrey Phillips Freeman | Giving actors the same language intelligence that human developers use in IDEs is a force multiplier for code quality — and leveraging the LSP ecosystem avoids reinventing mature tooling | - -**Total: 1** - -### Votes Against - -| Voter | Comment | -|-------|---------| - -**Total: 0** - -### Abstentions - -| Voter | Comment | -|-------|---------| - -**Total: 0** diff --git a/docs/adr/ADR-028-agent-skills-standard.md b/docs/adr/ADR-028-agent-skills-standard.md index ac55ac416..0eae918fb 100644 --- a/docs/adr/ADR-028-agent-skills-standard.md +++ b/docs/adr/ADR-028-agent-skills-standard.md @@ -1,15 +1,58 @@ -# ADR-028: Agent Skills Standard (AgentSkills.io) - -**Status:** Accepted -**Date:** 2026-02-17 -**Supersedes:** None -**Author(s):** Jeffrey Phillips Freeman -**Approver(s):** Jeffrey Phillips Freeman - +--- +adr_number: 28 +title: Agent Skills Standard (AgentSkills.io) +status_history: +- - '2026-02-17' + - Proposed + - Jeffrey Phillips Freeman +- - '2026-02-17' + - Accepted + - Jeffrey Phillips Freeman +tier: 4 +authors: +- Jeffrey Phillips Freeman +superseded_by: null +related_adrs: +- number: 10 + title: Actor and Agent Architecture + relationship: Agent Skills appear as tool nodes in actor graphs +- number: 11 + title: Tool System + relationship: Agent Skills are a tool source integrated into the Tool Registry +- number: 12 + title: Skill System + relationship: Agent Skills are exposed and composed within skills +- number: 15 + title: Sandbox and Checkpoint + relationship: Sub-tool-calls within skill execution are individually checkpointed +- number: 25 + title: Observability and Logging + relationship: Multi-step skill execution requires structured tracing +- number: 29 + title: Model Context Protocol (MCP) Adoption + relationship: Agent Skills commonly orchestrate MCP tools within workflows +- number: 30 + title: Skill Abstraction Definition + relationship: Agent Skills are one of the four tool sources unified under the skill abstraction +acceptance: + votes_for: + - voter: Jeffrey Phillips Freeman + comment: AgentSkills.io adoption enables a portable skill ecosystem that works across agent frameworks + votes_against: [] + abstentions: [] +--- ## Context CleverAgents needs a portable way to package instruction-driven workflows that go beyond single tool calls. An agent following a deployment checklist, for example, must orchestrate multiple MCP tools, make decisions based on intermediate results, and follow domain-specific best practices — something a single schema-driven tool call cannot express. These workflows should be shareable across teams, compatible with different agent runtimes, and efficient to load (only paying token cost when actually used). A standard format reduces fragmentation and enables a broader ecosystem of reusable skills. +## Decision Drivers + +- Multi-step instruction-driven workflows (e.g., deployment checklists) cannot be expressed as single schema-driven tool calls and need a packaging format +- Skills must be portable across teams and compatible with different agent runtimes to avoid vendor lock-in +- Token cost must be minimized at startup; full instructions should load only when the skill is actually invoked (progressive disclosure) +- Agent Skills must compose naturally with MCP tools, built-in tools, and other tool sources within actor graphs +- A standard format reduces ecosystem fragmentation and enables community sharing of reusable skill definitions + ## Decision CleverAgents adopts the **Agent Skills standard** from [https://AgentSkills.io](https://AgentSkills.io). Skills are authored as `SKILL.md` files with optional `scripts/`, `references/`, and `assets/` directories, and are ingested as a tool source (`agent_skill`) with progressive disclosure. @@ -102,39 +145,3 @@ This composition is a key design principle: Agent Skills extend the agent's *kno - **Registry integration tests**: Validate naming, source tagging (`agent_skill`), and skill-tool composition behavior. - **Sandbox tests**: Confirm that all tool calls made during skill execution respect sandbox and checkpoint requirements. - **Actor graph tests**: Verify that Agent Skill tool nodes activate correctly in actor graphs, load instructions, and produce tracked change sets. - -## Related ADRs - -| ADR | Title | Relationship | -|-----|-------|-------------| -| [ADR-010](ADR-010-actor-and-agent-architecture.md) | Actor and Agent Architecture | Agent Skills appear as tool nodes in actor graphs | -| [ADR-011](ADR-011-tool-system.md) | Tool System | Agent Skills are a tool source integrated into the Tool Registry | -| [ADR-012](ADR-012-skill-system.md) | Skill System | Agent Skills are exposed and composed within skills | -| [ADR-015](ADR-015-sandbox-and-checkpoint.md) | Sandbox and Checkpoint | Sub-tool-calls within skill execution are individually checkpointed | -| [ADR-025](ADR-025-observability-and-logging.md) | Observability and Logging | Multi-step skill execution requires structured tracing | -| [ADR-029](ADR-029-model-context-protocol.md) | Model Context Protocol (MCP) Adoption | Agent Skills commonly orchestrate MCP tools within workflows | -| [ADR-030](ADR-030-skill-abstraction-definition.md) | Skill Abstraction Definition | Agent Skills are one of the four tool sources unified under the skill abstraction | - -## Acceptance - -### Votes For - -| Voter | Comment | -|-------|---------| -| Jeffrey Phillips Freeman | AgentSkills.io adoption enables a portable skill ecosystem that works across agent frameworks | - -**Total: 1** - -### Votes Against - -| Voter | Comment | -|-------|---------| - -**Total: 0** - -### Abstentions - -| Voter | Comment | -|-------|---------| - -**Total: 0** diff --git a/docs/adr/ADR-029-model-context-protocol.md b/docs/adr/ADR-029-model-context-protocol.md index ce4ffcb84..3cea06087 100644 --- a/docs/adr/ADR-029-model-context-protocol.md +++ b/docs/adr/ADR-029-model-context-protocol.md @@ -1,15 +1,55 @@ -# ADR-029: Model Context Protocol (MCP) Adoption - -**Status:** Accepted -**Date:** 2026-02-17 -**Supersedes:** None -**Author(s):** Jeffrey Phillips Freeman -**Approver(s):** Jeffrey Phillips Freeman - +--- +adr_number: 29 +title: Model Context Protocol (MCP) Adoption +status_history: +- - '2026-02-17' + - Proposed + - Jeffrey Phillips Freeman +- - '2026-02-17' + - Accepted + - Jeffrey Phillips Freeman +tier: 4 +authors: +- Jeffrey Phillips Freeman +superseded_by: null +related_adrs: +- number: 11 + title: Tool System + relationship: MCP tools are registered as Tool records and follow the four-stage tool lifecycle +- number: 12 + title: Skill System + relationship: MCP tools are exposed through skills for actor assignment +- number: 15 + title: Sandbox and Checkpoint + relationship: MCP tool execution must respect sandbox boundaries and checkpoint rules +- number: 22 + title: LangChain/LangGraph Integration + relationship: MCP SDK is part of the LLM runtime stack; MCPToolAdapter bridges to LangGraph tool nodes +- number: 28 + title: Agent Skills Standard (AgentSkills.io) + relationship: Agent Skills commonly orchestrate MCP tools within multi-step workflows +- number: 30 + title: Skill Abstraction Definition + relationship: MCP tools are one of the four tool sources unified under the skill abstraction +acceptance: + votes_for: + - voter: Jeffrey Phillips Freeman + comment: MCP provides a proven standard for tool integration that aligns with the broader AI tooling ecosystem + votes_against: [] + abstentions: [] +--- ## Context CleverAgents needs a standard way to discover and invoke external tools without building bespoke integrations for each service. The system also requires that externally hosted tools can be composed into skills and used as nodes in actor graphs while still honoring sandboxing, checkpointing, and change tracking. A vendor-neutral protocol is necessary to keep the tool ecosystem portable and extensible. +## Decision Drivers + +- External tools must be discoverable and invocable through a vendor-neutral protocol to keep the tool ecosystem portable and extensible +- Externally hosted tools must honor sandboxing, checkpointing, and change tracking identically to built-in tools +- Tool capability metadata (read-only vs. write) must be available for safety enforcement, even when the protocol provides limited native metadata +- MCP tools must compose into skills and participate as nodes in actor graphs using the same four-stage lifecycle as all other tools +- Tool lists may change at runtime; the system must dynamically refresh available tools without restarting + ## Decision CleverAgents adopts the **Model Context Protocol (MCP)** as the standard for discovering and invoking external tools. MCP servers are integrated through the `MCPToolAdapter`, which registers MCP tools into the Tool Registry with extended capability metadata, allowing them to be composed into skills and invoked within actor graphs using the same four-stage tool lifecycle as built-in tools. @@ -123,38 +163,3 @@ Phase 4 — Deactivation: - **Sandbox rewrite tests**: Confirm path rewriting for filesystem-based MCP tools in both directions (request and response). - **Notification tests**: Verify tool list refresh on `notifications/tools/list_changed` events with correct registry updates. - **Lifecycle tests**: Verify clean startup and shutdown of MCP server processes across actor activation/deactivation cycles. - -## Related ADRs - -| ADR | Title | Relationship | -|-----|-------|-------------| -| [ADR-011](ADR-011-tool-system.md) | Tool System | MCP tools are registered as Tool records and follow the four-stage tool lifecycle | -| [ADR-012](ADR-012-skill-system.md) | Skill System | MCP tools are exposed through skills for actor assignment | -| [ADR-015](ADR-015-sandbox-and-checkpoint.md) | Sandbox and Checkpoint | MCP tool execution must respect sandbox boundaries and checkpoint rules | -| [ADR-022](ADR-022-langchain-langgraph-integration.md) | LangChain/LangGraph Integration | MCP SDK is part of the LLM runtime stack; MCPToolAdapter bridges to LangGraph tool nodes | -| [ADR-028](ADR-028-agent-skills-standard.md) | Agent Skills Standard (AgentSkills.io) | Agent Skills commonly orchestrate MCP tools within multi-step workflows | -| [ADR-030](ADR-030-skill-abstraction-definition.md) | Skill Abstraction Definition | MCP tools are one of the four tool sources unified under the skill abstraction | - -## Acceptance - -### Votes For - -| Voter | Comment | -|-------|---------| -| Jeffrey Phillips Freeman | MCP provides a proven standard for tool integration that aligns with the broader AI tooling ecosystem | - -**Total: 1** - -### Votes Against - -| Voter | Comment | -|-------|---------| - -**Total: 0** - -### Abstentions - -| Voter | Comment | -|-------|---------| - -**Total: 0** diff --git a/docs/adr/ADR-030-skill-abstraction-definition.md b/docs/adr/ADR-030-skill-abstraction-definition.md index d8fb65920..5840a72cb 100644 --- a/docs/adr/ADR-030-skill-abstraction-definition.md +++ b/docs/adr/ADR-030-skill-abstraction-definition.md @@ -1,15 +1,52 @@ -# ADR-030: Skill Abstraction Definition - -**Status:** Accepted -**Date:** 2026-02-17 -**Supersedes:** None -**Author(s):** Jeffrey Phillips Freeman -**Approver(s):** Jeffrey Phillips Freeman - +--- +adr_number: 30 +title: Skill Abstraction Definition +status_history: +- - '2026-02-17' + - Proposed + - Jeffrey Phillips Freeman +- - '2026-02-17' + - Accepted + - Jeffrey Phillips Freeman +tier: 4 +authors: +- Jeffrey Phillips Freeman +superseded_by: null +related_adrs: +- number: 10 + title: Actor and Agent Architecture + relationship: Actors reference skills to acquire tool capabilities; skills are the binding mechanism +- number: 11 + title: Tool System + relationship: Tools are the atomic operations that skills collect and present to actors +- number: 12 + title: Skill System + relationship: 'Implements the skill abstraction: composition, inclusion, registry, and flattening' +- number: 28 + title: Agent Skills Standard (AgentSkills.io) + relationship: Agent Skills are one of the four tool sources unified under the skill abstraction +- number: 29 + title: Model Context Protocol (MCP) Adoption + relationship: MCP tools are one of the four tool sources unified under the skill abstraction +acceptance: + votes_for: + - voter: Jeffrey Phillips Freeman + comment: Formalizing skills as YAML-configured tool bundles with context injection gives actors composable capabilities + votes_against: [] + abstentions: [] +--- ## Context CleverAgents integrates tools from four heterogeneous sources — MCP servers, Agent Skills (AgentSkills.io) folders, built-in tool groups, and custom Python implementations. Without a unifying abstraction, actors would need to understand each source's discovery mechanism, lifecycle, and metadata format individually. The system needs a single, well-defined concept that bridges the gap between individual tools (which are atomic, independently registered operations) and actors (which need coherent bundles of capabilities to perform their roles). The term "skill" is used throughout the specification, CLI, and configuration but its precise definition — what it is, what it is not, and how it relates to the four tool sources — must be formalized as an architectural commitment. +## Decision Drivers + +- Four heterogeneous tool sources (MCP servers, Agent Skills, built-ins, custom Python) must converge into a uniform interface so actors do not need source-specific integration logic +- Actors need coherent bundles of capabilities rather than individual tool references to keep configurations readable and auditable +- Common tool sets must be definable once and reusable across multiple actors via hierarchical composition (DRY principle) +- The boundary between tools (atomic operations) and skills (capability containers) must be formally defined to prevent conceptual confusion +- New tool sources must be addable in the future without changing actor binding or configuration models + ## Decision CleverAgents defines a **skill** as a **composable, namespaced collection of tools** that serves as the unit of capability assignment to actors. A skill is not a tool; it is a container that assembles tools from any combination of the four supported sources into a coherent, reusable bundle. Actors never reference individual tools directly for capability assignment — they reference skills, and through skills gain access to a flattened set of tools. @@ -138,37 +175,3 @@ This binding is the only path through which actors acquire tool capabilities. Th - **Actor binding tests**: Verify that actor activation resolves all skill references and produces the correct merged tool surface. - **Source uniformity tests**: Confirm that tools from all four sources are indistinguishable after flattening (same `ToolRecord` interface, same lifecycle). - **Registry consistency tests**: Validate that skill registration fails gracefully when referenced tools or included skills do not exist. - -## Related ADRs - -| ADR | Title | Relationship | -|-----|-------|-------------| -| [ADR-010](ADR-010-actor-and-agent-architecture.md) | Actor and Agent Architecture | Actors reference skills to acquire tool capabilities; skills are the binding mechanism | -| [ADR-011](ADR-011-tool-system.md) | Tool System | Tools are the atomic operations that skills collect and present to actors | -| [ADR-012](ADR-012-skill-system.md) | Skill System | Implements the skill abstraction: composition, inclusion, registry, and flattening | -| [ADR-028](ADR-028-agent-skills-standard.md) | Agent Skills Standard (AgentSkills.io) | Agent Skills are one of the four tool sources unified under the skill abstraction | -| [ADR-029](ADR-029-model-context-protocol.md) | Model Context Protocol (MCP) Adoption | MCP tools are one of the four tool sources unified under the skill abstraction | - -## Acceptance - -### Votes For - -| Voter | Comment | -|-------|---------| -| Jeffrey Phillips Freeman | Formalizing skills as YAML-configured tool bundles with context injection gives actors composable capabilities | - -**Total: 1** - -### Votes Against - -| Voter | Comment | -|-------|---------| - -**Total: 0** - -### Abstentions - -| Voter | Comment | -|-------|---------| - -**Total: 0** diff --git a/docs/adr/ADR-031-actor-abstraction-definition.md b/docs/adr/ADR-031-actor-abstraction-definition.md index db4fe4d2e..50fbc44f8 100644 --- a/docs/adr/ADR-031-actor-abstraction-definition.md +++ b/docs/adr/ADR-031-actor-abstraction-definition.md @@ -1,15 +1,64 @@ -# ADR-031: Actor Abstraction Definition - -**Status:** Accepted -**Date:** 2026-02-17 -**Supersedes:** None -**Author(s):** Jeffrey Phillips Freeman -**Approver(s):** Jeffrey Phillips Freeman - +--- +adr_number: 31 +title: Actor Abstraction Definition +status_history: +- - '2026-02-17' + - Proposed + - Jeffrey Phillips Freeman +- - '2026-02-17' + - Accepted + - Jeffrey Phillips Freeman +tier: 4 +authors: +- Jeffrey Phillips Freeman +superseded_by: null +related_adrs: +- number: 10 + title: Actor and Agent Architecture + relationship: Defines the actor implementation model (LangGraph StateGraph), role specialization, and graph construction +- number: 11 + title: Tool System + relationship: Tools serve as atomic execution nodes within actor graphs alongside actor nodes +- number: 12 + title: Skill System + relationship: Skills are the mechanism through which actors acquire tool capabilities +- number: 22 + title: LangChain/LangGraph Integration + relationship: Actors are implemented as LangGraph StateGraph instances; LangGraph is the graph runtime +- number: 28 + title: Agent Skills Standard (AgentSkills.io) + relationship: Agent Skills appear as tool nodes in actor graphs and extend actor knowledge +- number: 29 + title: Model Context Protocol (MCP) Adoption + relationship: MCP tools appear as tool nodes in actor graphs via skill composition +- number: 30 + title: Skill Abstraction Definition + relationship: Skills are the unit of capability assignment to actors; the skill-actor binding model +- number: 32 + title: Jinja2 YAML Template Preprocessing + relationship: Defines how actor YAML files are preprocessed with Jinja2 templates and environment variable interpolation before parsing +- number: 27 + title: Language Server Protocol (LSP) Integration + relationship: Actors acquire language intelligence through LSP servers; the `lsp` config field is the second capability acquisition mechanism alongside skills +acceptance: + votes_for: + - voter: Jeffrey Phillips Freeman + comment: Unifying agents, workflows, and pipelines under the actor-as-graph abstraction eliminates conceptual fragmentation + votes_against: [] + abstentions: [] +--- ## Context CleverAgents needs a single abstraction that covers everything from a simple LLM wrapper answering questions to a complex multi-stage pipeline orchestrating dozens of sub-agents and tool calls. The system must support hierarchical composition (graphs containing graphs), role specialization (strategy, execution, estimation, invariant), and uniform treatment of all conversational participants. Without a formal definition of what an "actor" is, the boundary between actors, agents, graphs, and workflows becomes ambiguous — leading to inconsistent configuration, unclear composition rules, and conceptual fragmentation in both documentation and implementation. This ADR formalizes the actor abstraction as an architectural commitment. +## Decision Drivers + +- A single abstraction must cover everything from simple LLM wrappers to complex multi-stage pipelines without requiring separate concepts for "agent," "workflow," and "orchestrator" +- Actors must support hierarchical composition (graphs containing graphs) with no depth limit for orchestrator-of-orchestrators patterns +- The boundary between actors (conversational units) and agents (LLM-backed reasoning entities) must be formally defined to preserve precision +- All conversational participants must maintain a uniform text-in/text-out contract regardless of internal complexity +- Capability acquisition must be declarative and go exclusively through skills (for tools) and LSP bindings (for language intelligence) + ## Decision CleverAgents defines an **actor** as a **YAML-configured conversational unit** that generalizes "agent" into "anything conversational." An actor can represent a single LLM node, a composed graph of actors and tool nodes, or any text-in/text-out system. Every custom actor is implemented as a graph (a LangGraph StateGraph), and graphs can compose and contain other actors — enabling hierarchical orchestration without a separate composition model. @@ -177,41 +226,3 @@ This dual acquisition model — tools through skills, language intelligence thro - **Role binding tests**: Validate that actions correctly bind strategy, execution, estimation, and invariant roles to registered actors. - **Capability binding tests**: Confirm that actor activation resolves skill references and produces the correct merged tool surface. - **Conversational contract tests**: Verify that all actors (simple and composite) accept text input and produce text output regardless of internal graph complexity. - -## Related ADRs - -| ADR | Title | Relationship | -|-----|-------|-------------| -| [ADR-010](ADR-010-actor-and-agent-architecture.md) | Actor and Agent Architecture | Defines the actor implementation model (LangGraph StateGraph), role specialization, and graph construction | -| [ADR-011](ADR-011-tool-system.md) | Tool System | Tools serve as atomic execution nodes within actor graphs alongside actor nodes | -| [ADR-012](ADR-012-skill-system.md) | Skill System | Skills are the mechanism through which actors acquire tool capabilities | -| [ADR-022](ADR-022-langchain-langgraph-integration.md) | LangChain/LangGraph Integration | Actors are implemented as LangGraph StateGraph instances; LangGraph is the graph runtime | -| [ADR-028](ADR-028-agent-skills-standard.md) | Agent Skills Standard (AgentSkills.io) | Agent Skills appear as tool nodes in actor graphs and extend actor knowledge | -| [ADR-029](ADR-029-model-context-protocol.md) | Model Context Protocol (MCP) Adoption | MCP tools appear as tool nodes in actor graphs via skill composition | -| [ADR-030](ADR-030-skill-abstraction-definition.md) | Skill Abstraction Definition | Skills are the unit of capability assignment to actors; the skill-actor binding model | -| [ADR-032](ADR-032-jinja2-yaml-template-preprocessing.md) | Jinja2 YAML Template Preprocessing | Defines how actor YAML files are preprocessed with Jinja2 templates and environment variable interpolation before parsing | -| [ADR-027](ADR-027-language-server-protocol.md) | Language Server Protocol (LSP) Integration | Actors acquire language intelligence through LSP servers; the `lsp` config field is the second capability acquisition mechanism alongside skills | - -## Acceptance - -### Votes For - -| Voter | Comment | -|-------|---------| -| Jeffrey Phillips Freeman | Unifying agents, workflows, and pipelines under the actor-as-graph abstraction eliminates conceptual fragmentation | - -**Total: 1** - -### Votes Against - -| Voter | Comment | -|-------|---------| - -**Total: 0** - -### Abstentions - -| Voter | Comment | -|-------|---------| - -**Total: 0** diff --git a/docs/adr/ADR-032-jinja2-yaml-template-preprocessing.md b/docs/adr/ADR-032-jinja2-yaml-template-preprocessing.md index 4eccd10a3..7432f53fa 100644 --- a/docs/adr/ADR-032-jinja2-yaml-template-preprocessing.md +++ b/docs/adr/ADR-032-jinja2-yaml-template-preprocessing.md @@ -1,11 +1,37 @@ -# ADR-032: Jinja2 YAML Template Preprocessing - -**Status:** Accepted -**Date:** 2026-02-19 -**Supersedes:** None -**Author(s):** Jeffrey Phillips Freeman -**Approver(s):** Jeffrey Phillips Freeman - +--- +adr_number: 32 +title: Jinja2 YAML Template Preprocessing +status_history: +- - '2026-02-19' + - Proposed + - Jeffrey Phillips Freeman +- - '2026-02-19' + - Accepted + - Jeffrey Phillips Freeman +tier: 4 +authors: +- Jeffrey Phillips Freeman +superseded_by: null +related_adrs: +- number: 10 + title: Actor and Agent Architecture + relationship: Defines the actor configuration model that this ADR's template engine processes +- number: 24 + title: Configuration System + relationship: Defines the overall configuration approach; this ADR extends it with Jinja2 preprocessing for actor YAML files +- number: 31 + title: Actor Abstraction Definition + relationship: Defines what an actor is; this ADR defines how actor YAML files are preprocessed before validation +- number: 5 + title: Technical Stack + relationship: Jinja2 is added as a required dependency in the technical stack +acceptance: + votes_for: + - voter: Jeffrey Phillips Freeman + comment: Two-phase Jinja2 + env var preprocessing provides the right balance of power and safety for declarative actor configurations + votes_against: [] + abstentions: [] +--- ## Context CleverAgents actor configuration files are written in YAML and define complex multi-actor workflows with system prompts, routing logic, and shared context. Many real-world configurations require dynamic content in system prompts — for example, a brainstorming actor needs to reference paper requirements collected during a prior discovery stage, or a vetting actor needs to conditionally change its behavior based on whether auto-finish mode is active. @@ -16,6 +42,15 @@ Furthermore, actor configurations frequently need environment variable substitut The v2 system already used Jinja2 templating in its reactive configuration files. Preserving and formalizing this capability ensures backward compatibility and provides a proven, well-understood solution for dynamic YAML content. +## Decision Drivers + +- Actor configurations require dynamic content in system prompts (e.g., context-dependent instructions, conditional behavior) that static YAML cannot express +- The declarative YAML-only philosophy must be preserved; authors should not need to write Python code for dynamic configurations +- Template-time logic (conditionals, loops, variable expansion) and runtime configuration (environment variables) must be cleanly separated into distinct phases +- Jinja2 templates in `system_prompt` fields must survive file loading and be preserved for runtime evaluation when actor context becomes available +- Template execution must be sandboxed to prevent arbitrary code execution or filesystem access from user-provided configuration files +- Backward compatibility with v2 configurations that already use Jinja2 templating must be maintained + ## Decision CleverAgents adopts a **two-phase YAML processing pipeline** for actor configuration files: @@ -175,36 +210,3 @@ Environment variable interpolation is applied recursively to all nested dictiona - **Post-processing tests**: Verify that rendered YAML with blank lines, multi-colon lines, and indentation issues is correctly fixed. - **Filter and built-in tests**: Verify that all custom filters (`yaml`, `indent`, `sum`, `selectattr`) and exposed built-ins (`range`, `abs`, `round`, `len`, `min`, `max`, `sum`) work correctly in template expressions. - **BDD feature coverage**: `actor_config_coverage.feature`, `actor_config_new_coverage.feature`, and `yaml_template_engine_coverage.feature` provide end-to-end coverage of the two-phase pipeline. - -## Related ADRs - -| ADR | Title | Relationship | -|-----|-------|-------------| -| [ADR-010](ADR-010-actor-and-agent-architecture.md) | Actor and Agent Architecture | Defines the actor configuration model that this ADR's template engine processes | -| [ADR-024](ADR-024-configuration-system.md) | Configuration System | Defines the overall configuration approach; this ADR extends it with Jinja2 preprocessing for actor YAML files | -| [ADR-031](ADR-031-actor-abstraction-definition.md) | Actor Abstraction Definition | Defines what an actor is; this ADR defines how actor YAML files are preprocessed before validation | -| [ADR-005](ADR-005-technical-stack.md) | Technical Stack | Jinja2 is added as a required dependency in the technical stack | - -## Acceptance - -### Votes For - -| Voter | Comment | -|-------|---------| -| Jeffrey Phillips Freeman | Two-phase Jinja2 + env var preprocessing provides the right balance of power and safety for declarative actor configurations | - -**Total: 1** - -### Votes Against - -| Voter | Comment | -|-------|---------| - -**Total: 0** - -### Abstentions - -| Voter | Comment | -|-------|---------| - -**Total: 0** diff --git a/docs/adr/ADR-033-decision-recording-protocol.md b/docs/adr/ADR-033-decision-recording-protocol.md index f4dda6fb0..e0664e397 100644 --- a/docs/adr/ADR-033-decision-recording-protocol.md +++ b/docs/adr/ADR-033-decision-recording-protocol.md @@ -1,17 +1,63 @@ -# ADR-033: Decision Recording Protocol - -**Status:** Accepted -**Date:** 2026-02-20 -**Supersedes:** None -**Author(s):** Jeffrey Phillips Freeman -**Approver(s):** Jeffrey Phillips Freeman - +--- +adr_number: 33 +title: Decision Recording Protocol +status_history: +- - '2026-02-20' + - Proposed + - Jeffrey Phillips Freeman +- - '2026-02-20' + - Accepted + - Jeffrey Phillips Freeman +tier: 2 +authors: +- Jeffrey Phillips Freeman +superseded_by: null +related_adrs: +- number: 6 + title: Plan Lifecycle + relationship: Defines the phases in which decisions are recorded +- number: 7 + title: Decision Tree and Correction + relationship: Defines the decision record structure and types that this protocol populates +- number: 10 + title: Actor and Agent Architecture + relationship: Actors are the entities that call `record_decision` +- number: 11 + title: Tool System + relationship: '`record_decision` is a built-in tool following the tool system conventions' +- number: 16 + title: Invariant System + relationship: Invariant Reconciliation Actor uses `record_decision` to record enforced invariants +- number: 17 + title: Automation Profiles + relationship: Confidence thresholds gate `record_decision` calls +- number: 34 + title: Decision Tree Versioning and History + relationship: Recorded decisions form the versioned tree structure +- number: 35 + title: Decision Tree Rollback and Replay + relationship: Context snapshots captured during recording enable rollback and replay +acceptance: + votes_for: + - voter: Jeffrey Phillips Freeman + comment: Tool-based decision recording with auto-captured context snapshots provides explicit, auditable, replayable decision creation + votes_against: [] + abstentions: [] +--- ## Context ADR-007 defines eleven decision types, the decision record data model, and the correction mechanism. ADR-006 defines the plan lifecycle phases in which decisions are created. However, neither ADR describes the *protocol* by which actors mechanically create decision records during plan execution. The specification states that "the strategy actor produces the initial decision tree" and that "the execution actor may create additional decisions," but does not specify how an actor identifies a choice point, emits a decision record, captures the context snapshot, or interacts with the automation profile's confidence threshold. Without a defined recording protocol, implementers must invent their own mechanism for decision creation, leading to inconsistent recording, missing context snapshots, and unreliable correction replay. +## Decision Drivers + +- Every decision made during plan execution must be explicitly recorded with type, rationale, and context snapshot to enable auditing and correction replay +- The recording mechanism must integrate naturally with the existing tool-based architecture, providing clear interception points for automation profile gating and context capture +- Context snapshots (LangGraph checkpoint, hot context hash, relevant resources) must be captured automatically at recording time without requiring actor cooperation +- Decision recording must be uniform across all actor roles (strategy, execution, invariant reconciliation) using a single tool interface +- Confidence thresholds from automation profiles must gate decision persistence, pausing for human review when confidence is below the threshold + ## Decision Actors record decisions by calling a **built-in `record_decision` tool**. The system prompt for each actor role (strategy, execution, invariant reconciliation) instructs the actor to call this tool whenever it identifies a choice point. Decision types are partitioned into three creation categories: **actor-recorded** (strategy and execution actors call `record_decision`), **reconciliation-actor-recorded** (the Invariant Reconciliation Actor calls `record_decision` for enforced invariants), and **system-created** (the plan lifecycle engine creates `prompt_definition` and `user_intervention` decisions automatically). All categories produce identical decision records; only the originator differs. @@ -234,40 +280,3 @@ This makes invariant enforcement an explicit, auditable, correctable part of the - **Automation profile gating tests**: Tests verify that decisions with confidence below the profile threshold pause for user input, and decisions meeting the threshold proceed automatically. - **Invariant recording tests**: Tests verify that the Invariant Reconciliation Actor creates one `invariant_enforced` decision per enforced invariant via `record_decision`. - **Execute checkpoint tests**: Tests verify that `record_decision` calls during Execute trigger checkpoint group creation (coordinated with ADR-035 compliance tests). - -## Related ADRs - -| ADR | Title | Relationship | -|-----|-------|-------------| -| [ADR-006](ADR-006-plan-lifecycle.md) | Plan Lifecycle | Defines the phases in which decisions are recorded | -| [ADR-007](ADR-007-decision-tree-and-correction.md) | Decision Tree and Correction | Defines the decision record structure and types that this protocol populates | -| [ADR-010](ADR-010-actor-and-agent-architecture.md) | Actor and Agent Architecture | Actors are the entities that call `record_decision` | -| [ADR-011](ADR-011-tool-system.md) | Tool System | `record_decision` is a built-in tool following the tool system conventions | -| [ADR-016](ADR-016-invariant-system.md) | Invariant System | Invariant Reconciliation Actor uses `record_decision` to record enforced invariants | -| [ADR-017](ADR-017-automation-profiles.md) | Automation Profiles | Confidence thresholds gate `record_decision` calls | -| [ADR-034](ADR-034-decision-tree-versioning-and-history.md) | Decision Tree Versioning and History | Recorded decisions form the versioned tree structure | -| [ADR-035](ADR-035-decision-tree-rollback-and-replay.md) | Decision Tree Rollback and Replay | Context snapshots captured during recording enable rollback and replay | - -## Acceptance - -### Votes For - -| Voter | Comment | -|-------|---------| -| Jeffrey Phillips Freeman | Tool-based decision recording with auto-captured context snapshots provides explicit, auditable, replayable decision creation | - -**Total: 1** - -### Votes Against - -| Voter | Comment | -|-------|---------| - -**Total: 0** - -### Abstentions - -| Voter | Comment | -|-------|---------| - -**Total: 0** diff --git a/docs/adr/ADR-034-decision-tree-versioning-and-history.md b/docs/adr/ADR-034-decision-tree-versioning-and-history.md index 5a73d3072..f208020ed 100644 --- a/docs/adr/ADR-034-decision-tree-versioning-and-history.md +++ b/docs/adr/ADR-034-decision-tree-versioning-and-history.md @@ -1,17 +1,55 @@ -# ADR-034: Decision Tree Versioning and History - -**Status:** Accepted -**Date:** 2026-02-20 -**Supersedes:** None -**Author(s):** Jeffrey Phillips Freeman -**Approver(s):** Jeffrey Phillips Freeman - +--- +adr_number: 34 +title: Decision Tree Versioning and History +status_history: +- - '2026-02-20' + - Proposed + - Jeffrey Phillips Freeman +- - '2026-02-20' + - Accepted + - Jeffrey Phillips Freeman +tier: 2 +authors: +- Jeffrey Phillips Freeman +superseded_by: null +related_adrs: +- number: 6 + title: Plan Lifecycle + relationship: Decision trees are built during lifecycle phases; corrections may trigger phase reversion +- number: 7 + title: Decision Tree and Correction + relationship: Defines the decision record structure and `superseded_by` field that this ADR builds upon +- number: 19 + title: Storage and Persistence + relationship: Decision records are stored in SQLite/SQLAlchemy with the repository pattern +- number: 33 + title: Decision Recording Protocol + relationship: Defines how decisions are created; this ADR defines how they are versioned and organized +- number: 35 + title: Decision Tree Rollback and Replay + relationship: Uses the versioned tree structure for rollback target identification and affected subtree computation +acceptance: + votes_for: + - voter: Jeffrey Phillips Freeman + comment: Implicit versioning via superseded_by provides full audit history without schema overhead + votes_against: [] + abstentions: [] +--- ## Context ADR-007 defines the decision record structure including a `superseded_by` field for marking corrected decisions and a `correction_attempts` table for tracking correction history. However, it does not describe how the full decision tree — including old superseded branches that coexist with current active branches — is structured, navigated, or historically reconstructed. The specification refers to `--show-superseded` rendering and decision tree visualization, but the data model for distinguishing "current tree" from "historical tree at a point in time" is implicit rather than explicit. Without a defined versioning model, the system cannot reliably answer questions like: "What did the tree look like before correction N?", "Which decisions were replaced and which survived?", or "How has this plan's strategy evolved across multiple corrections?" +## Decision Drivers + +- Must reconstruct historical states of the decision tree for auditing and debugging ("what did the tree look like before correction N?") +- Version identifiers must be derivable without a central authority, using existing `superseded_by` pointers and `correction_attempts` records +- Superseded decisions must never be deleted — append-only history is required for audit trails and correction comparison +- The structural tree (rendering/navigation) and influence DAG (impact analysis) serve different purposes and must be maintained as separate but overlapping structures +- Cross-plan tree relationships via child plan references must preserve child plan decision records when a parent's `subplan_spawn` is superseded +- Historical reconstruction must be deterministic and reproducible given the same correction attempt identifier + ## Decision The decision tree uses **implicit versioning through `superseded_by` pointers**. The "current tree" is defined as all decisions where `superseded_by IS NULL`. Historical tree states are reconstructable by walking `superseded_by` chains backward from `correction_attempts` records. Old superseded branches are never deleted — they remain in the database alongside current decisions, creating a persistent, append-only history of the tree's evolution. @@ -194,37 +232,3 @@ The `sequence_number` field serves as a global ordering of all decisions within - **Sequence number tests**: Tests verify monotonic ordering, no reuse, and correct gap behavior after corrections. - **Cross-plan reference tests**: Tests verify that superseding a `subplan_spawn` decision correctly flags the child plan for re-execution without modifying the child's decision records. - **Rendering tests**: Tests verify that `plan tree` and `plan tree --show-superseded` produce correct output for trees with zero, one, and multiple corrections. - -## Related ADRs - -| ADR | Title | Relationship | -|-----|-------|-------------| -| [ADR-006](ADR-006-plan-lifecycle.md) | Plan Lifecycle | Decision trees are built during lifecycle phases; corrections may trigger phase reversion | -| [ADR-007](ADR-007-decision-tree-and-correction.md) | Decision Tree and Correction | Defines the decision record structure and `superseded_by` field that this ADR builds upon | -| [ADR-019](ADR-019-storage-and-persistence.md) | Storage and Persistence | Decision records are stored in SQLite/SQLAlchemy with the repository pattern | -| [ADR-033](ADR-033-decision-recording-protocol.md) | Decision Recording Protocol | Defines how decisions are created; this ADR defines how they are versioned and organized | -| [ADR-035](ADR-035-decision-tree-rollback-and-replay.md) | Decision Tree Rollback and Replay | Uses the versioned tree structure for rollback target identification and affected subtree computation | - -## Acceptance - -### Votes For - -| Voter | Comment | -|-------|---------| -| Jeffrey Phillips Freeman | Implicit versioning via superseded_by provides full audit history without schema overhead | - -**Total: 1** - -### Votes Against - -| Voter | Comment | -|-------|---------| - -**Total: 0** - -### Abstentions - -| Voter | Comment | -|-------|---------| - -**Total: 0** diff --git a/docs/adr/ADR-035-decision-tree-rollback-and-replay.md b/docs/adr/ADR-035-decision-tree-rollback-and-replay.md index f1359ad75..c78c5054e 100644 --- a/docs/adr/ADR-035-decision-tree-rollback-and-replay.md +++ b/docs/adr/ADR-035-decision-tree-rollback-and-replay.md @@ -1,11 +1,40 @@ -# ADR-035: Decision Tree Rollback and Replay - -**Status:** Accepted -**Date:** 2026-02-20 -**Supersedes:** None -**Author(s):** Jeffrey Phillips Freeman -**Approver(s):** Jeffrey Phillips Freeman - +--- +adr_number: 35 +title: Decision Tree Rollback and Replay +status_history: +- - '2026-02-20' + - Proposed + - Jeffrey Phillips Freeman +- - '2026-02-20' + - Accepted + - Jeffrey Phillips Freeman +tier: 2 +authors: +- Jeffrey Phillips Freeman +superseded_by: null +related_adrs: +- number: 6 + title: Plan Lifecycle + relationship: Phase reversion interacts with decision correction; corrections may trigger phase changes +- number: 7 + title: Decision Tree and Correction + relationship: Defines the correction model that this ADR provides rollback mechanics for +- number: 15 + title: Sandbox and Checkpoint + relationship: Checkpoint infrastructure that decision-aligned checkpointing builds upon +- number: 33 + title: Decision Recording Protocol + relationship: The `record_decision` tool triggers checkpoint group creation during Execute +- number: 34 + title: Decision Tree Versioning and History + relationship: Superseded branch mechanics used during correction cascading +acceptance: + votes_for: + - voter: Jeffrey Phillips Freeman + comment: Decision-aligned checkpointing with coordinated cross-resource rollback enables fine-grained Execute-phase correction + votes_against: [] + abstentions: [] +--- ## Context ADR-007 defines a high-level 6-step correction flow for reverting decisions, and ADR-034 defines how superseded branches are tracked. However, neither ADR details the mechanics of actually rolling back to an arbitrary decision point — especially during the Execute phase where resources have been modified. The correction model must handle two fundamentally different scenarios: @@ -16,6 +45,15 @@ ADR-007 defines a high-level 6-step correction flow for reverting decisions, and The second scenario is significantly harder. Resource state changes continuously throughout Execute as tools are invoked. Without a mechanism to capture resource state at each decision point, the system cannot roll back to arbitrary decisions during Execute — it can only revert the entire Execute phase back to Strategize, which is expensive and discards all valid work. +## Decision Drivers + +- Mid-Execute corrections require restoring both resource state (sandbox contents) and actor reasoning state to the exact decision point +- Mid-Strategize corrections are read-only and need only reasoning state restoration, not resource rollback +- Without decision-aligned checkpoints, the only Execute-phase recovery option is reverting the entire phase back to Strategize, discarding all valid work +- Rollback must coordinate across multiple sandbox strategies (git worktree, filesystem copy, database savepoints) within a single correction +- Non-rollbackable resources and irreversible side effects (e.g., external API calls) must be explicitly tracked and warned about rather than silently ignored +- Checkpoint overhead must fit within the plan's checkpoint budget, leveraging the fact that decisions are far less frequent than tool calls + ## Decision Rollback operates on **two independent dimensions**: *resource rollback* (undoing sandbox changes via checkpoint restoration) and *reasoning rollback* (restoring actor state from the decision's `context_snapshot.actor_state_ref`). Execute-phase decisions automatically trigger **coordinated checkpoint groups** across all affected sandbox resources, creating a 1:1 mapping between decisions and resource states that enables fine-grained rollback to any Execute-phase decision point. @@ -338,37 +376,3 @@ Decision-aligned checkpoints (SAVEPOINTs) do not significantly worsen the long-r - **Tier detection tests**: Tests verify that the system correctly identifies the available rollback tier and produces appropriate error messages when the requested correction exceeds the available tier. - **Cross-plan cascade tests**: Tests verify that superseding a `subplan_spawn` decision correctly handles child plans in each possible state (not started, in progress, completed, applied). - **Checkpoint pruning priority tests**: Tests verify that decision-linked checkpoints are retained over regular pre-write checkpoints during pruning. - -## Related ADRs - -| ADR | Title | Relationship | -|-----|-------|-------------| -| [ADR-006](ADR-006-plan-lifecycle.md) | Plan Lifecycle | Phase reversion interacts with decision correction; corrections may trigger phase changes | -| [ADR-007](ADR-007-decision-tree-and-correction.md) | Decision Tree and Correction | Defines the correction model that this ADR provides rollback mechanics for | -| [ADR-015](ADR-015-sandbox-and-checkpoint.md) | Sandbox and Checkpoint | Checkpoint infrastructure that decision-aligned checkpointing builds upon | -| [ADR-033](ADR-033-decision-recording-protocol.md) | Decision Recording Protocol | The `record_decision` tool triggers checkpoint group creation during Execute | -| [ADR-034](ADR-034-decision-tree-versioning-and-history.md) | Decision Tree Versioning and History | Superseded branch mechanics used during correction cascading | - -## Acceptance - -### Votes For - -| Voter | Comment | -|-------|---------| -| Jeffrey Phillips Freeman | Decision-aligned checkpointing with coordinated cross-resource rollback enables fine-grained Execute-phase correction | - -**Total: 1** - -### Votes Against - -| Voter | Comment | -|-------|---------| - -**Total: 0** - -### Abstentions - -| Voter | Comment | -|-------|---------| - -**Total: 0** diff --git a/docs/adr/ADR-036-resource-dag-operational-semantics.md b/docs/adr/ADR-036-resource-dag-operational-semantics.md index 52a21259b..b6cdfae82 100644 --- a/docs/adr/ADR-036-resource-dag-operational-semantics.md +++ b/docs/adr/ADR-036-resource-dag-operational-semantics.md @@ -1,17 +1,60 @@ -# ADR-036: Resource DAG Operational Semantics - -**Status:** Accepted -**Date:** 2026-02-21 -**Supersedes:** None -**Author(s):** Jeffrey Phillips Freeman -**Approver(s):** Jeffrey Phillips Freeman - +--- +adr_number: 36 +title: Resource DAG Operational Semantics +status_history: +- - '2026-02-21' + - Proposed + - Jeffrey Phillips Freeman +- - '2026-02-21' + - Accepted + - Jeffrey Phillips Freeman +tier: 3 +authors: +- Jeffrey Phillips Freeman +superseded_by: null +related_adrs: +- number: 8 + title: Resource System + relationship: Defines the DAG's structural rules; this ADR adds operational semantics on top +- number: 11 + title: Tool System + relationship: Tools bind to resources; this ADR defines how reachability extends through the DAG +- number: 15 + title: Sandbox and Checkpoint + relationship: Defines sandbox strategies; this ADR formalizes sandbox boundaries as a DAG property +- number: 37 + title: Tool Reachability and Access Projection + relationship: Extends purposes 1–3 with the full reachability and routing model +- number: 38 + title: Cross-Mechanism Sandbox Coordination + relationship: Extends purpose 5 with coherence, write-then-sync, and lazy virtual materialization +- number: 39 + title: Container and Execution Environment Resource Types + relationship: Defines new resource types that create additional sandbox domains and containment hierarchies +- number: 40 + title: Language Server Protocol Resource Types + relationship: Defines LSP resource types that create cross-mechanism equivalence with filesystem resources +acceptance: + votes_for: + - voter: Jeffrey Phillips Freeman + comment: The ten purposes and sandbox boundary algebra provide the missing operational theory for the resource DAG + votes_against: [] + abstentions: [] +--- ## Context ADR-008 defines the resource DAG's structural rules (acyclicity, type compatibility, unique links, existence constraints) and its role in resource discovery and sandbox ordering. The specification (lines 22660–22911) elaborates the 24 built-in types, virtual/physical equivalence linking, and divergence detection. However, neither document articulates a unified theory of **what the DAG is for at runtime** — what operational questions it answers, what algorithms it supports, and how its structure drives sandbox creation, tool routing, access control propagation, and change coordination across heterogeneous mechanisms. This ADR defines the **operational semantics** of the resource DAG: the purpose-driven theory that connects DAG structure to runtime behavior. +## Decision Drivers + +- The DAG's structural rules (ADR-008) exist but no unified theory connects DAG structure to runtime behavior across subsystems (sandbox, tool routing, access control, auto-discovery) +- Sandbox boundaries must be explicit and queryable — a file cannot be sandboxed in isolation; its containing repository or directory must define the boundary +- Tool reachability, read/write routing, and access control propagation all traverse the DAG differently and need formalized semantics +- Lifecycle operations (creation, commit, rollback, cleanup) require correct topological orderings with direction varying per operation type +- Change propagation through virtual resource equivalence classes must terminate deterministically and not cascade unboundedly + ## Decision The resource DAG serves as the **topology of the system's operational world**. Its structure supports ten distinct operational purposes, organized into three categories: **reachability** (how tools connect to resources), **isolation** (how sandboxing and checkpointing map to DAG positions), and **coordination** (how changes propagate and how equivalent resources stay synchronized). This ADR defines the sandbox boundary algebra and dependency ordering protocols that emerge from these purposes. @@ -175,39 +218,3 @@ Note: The physical-to-virtual relationship uses the standard parent-child edge w - **Dependency ordering tests**: Tests verify correct topological ordering for creation, commit, rollback, and cleanup operations. - **Change propagation tests**: Tests verify that changes to a file trigger ancestor status updates and virtual resource re-evaluation, with cascade termination. - **Access control propagation tests**: Tests verify that `effective_writable(r)` correctly aggregates constraints from all ancestors and project-level read-only flags. - -## Related ADRs - -| ADR | Title | Relationship | -|-----|-------|-------------| -| [ADR-008](ADR-008-resource-system.md) | Resource System | Defines the DAG's structural rules; this ADR adds operational semantics on top | -| [ADR-011](ADR-011-tool-system.md) | Tool System | Tools bind to resources; this ADR defines how reachability extends through the DAG | -| [ADR-015](ADR-015-sandbox-and-checkpoint.md) | Sandbox and Checkpoint | Defines sandbox strategies; this ADR formalizes sandbox boundaries as a DAG property | -| [ADR-037](ADR-037-tool-reachability-and-access-projection.md) | Tool Reachability and Access Projection | Extends purposes 1–3 with the full reachability and routing model | -| [ADR-038](ADR-038-cross-mechanism-sandbox-coordination.md) | Cross-Mechanism Sandbox Coordination | Extends purpose 5 with coherence, write-then-sync, and lazy virtual materialization | -| [ADR-039](ADR-039-container-resource-types.md) | Container and Execution Environment Resource Types | Defines new resource types that create additional sandbox domains and containment hierarchies | -| [ADR-040](ADR-040-lsp-resource-types.md) | Language Server Protocol Resource Types | Defines LSP resource types that create cross-mechanism equivalence with filesystem resources | - -## Acceptance - -### Votes For - -| Voter | Comment | -|-------|---------| -| Jeffrey Phillips Freeman | The ten purposes and sandbox boundary algebra provide the missing operational theory for the resource DAG | - -**Total: 1** - -### Votes Against - -| Voter | Comment | -|-------|---------| - -**Total: 0** - -### Abstentions - -| Voter | Comment | -|-------|---------| - -**Total: 0** diff --git a/docs/adr/ADR-037-tool-reachability-and-access-projection.md b/docs/adr/ADR-037-tool-reachability-and-access-projection.md index 201f11ae1..9f6d5e0b2 100644 --- a/docs/adr/ADR-037-tool-reachability-and-access-projection.md +++ b/docs/adr/ADR-037-tool-reachability-and-access-projection.md @@ -1,11 +1,43 @@ -# ADR-037: Tool Reachability and Access Projection - -**Status:** Accepted -**Date:** 2026-02-21 -**Supersedes:** None -**Author(s):** Jeffrey Phillips Freeman -**Approver(s):** Jeffrey Phillips Freeman - +--- +adr_number: 37 +title: Tool Reachability and Access Projection +status_history: +- - '2026-02-21' + - Proposed + - Jeffrey Phillips Freeman +- - '2026-02-21' + - Accepted + - Jeffrey Phillips Freeman +tier: 3 +authors: +- Jeffrey Phillips Freeman +superseded_by: null +related_adrs: +- number: 8 + title: Resource System + relationship: Resource DAG provides the containment and equivalence structure for reachability +- number: 11 + title: Tool System + relationship: Tools declare resource slots; this ADR extends binding resolution with transitive reachability +- number: 36 + title: Resource DAG Operational Semantics + relationship: Defines purposes 1–3 (reachability, equivalence, routing) that this ADR formalizes +- number: 38 + title: Cross-Mechanism Sandbox Coordination + relationship: Routing decisions must account for cross-mechanism coherence and sandbox coordination +- number: 39 + title: Container and Execution Environment Resource Types + relationship: Container resources create alternative reachability paths through mount hierarchies +- number: 40 + title: LSP Resource Types + relationship: LSP resources are the primary use case for semantically-rich read routing +acceptance: + votes_for: + - voter: Jeffrey Phillips Freeman + comment: Transitive reachability with access projection and read/write routing is the missing link between DAG structure and tool execution + votes_against: [] + abstentions: [] +--- ## Context ADR-011 defines how tools declare resource slots and how the `BindingResolutionService` resolves slots to concrete resources. The specification (lines 20113–20321) details the three binding modes (contextual, static, parameter) and shows resource discovery queries like "What tools can modify this resource?" However, the current model only answers **direct binding** questions — whether a tool's slot type matches a specific resource's type. It does not formalize: @@ -16,6 +48,14 @@ ADR-011 defines how tools declare resource slots and how the `BindingResolutionS 4. **Access projection**: When a tool is bound to an ancestor resource and needs to access a descendant, how is the descendant identified within the ancestor's access space? (e.g., relative path for filesystem, document URI for LSP, SQL query for database). 5. **Read/write routing**: When a virtual resource has multiple physical manifestations, which tool should the system prefer for reads (semantic richness) versus writes (sandbox tracking)? +## Decision Drivers + +- Current binding resolution only answers direct type-match questions; a tool bound to a `git-checkout` implicitly reaches all contained files but this reach is not formalized in the DAG +- Inverse reachability ("what tools can reach this specific file?") requires walking up the containment hierarchy, not just checking direct type matches +- A virtual resource with multiple physical manifestations (git checkout, container mount, LSP document) may be reachable through tools bound to any ancestor chain +- Access projection must translate between namespaces (filesystem paths, LSP document URIs, container-internal paths) when a tool accesses a descendant through an ancestor binding +- Read and write operations benefit from different physical paths — semantic reads through LSP, sandbox-tracked writes through git — requiring explicit routing by richness and sandbox tracking capability + ## Decision CleverAgents formalizes **tool reachability** as a transitive property through the resource DAG's `contains` edges, adds an **access projection** method to the `ResourceHandler` protocol, and defines a **read/write routing** algorithm that selects optimal tools and access paths based on virtual resource equivalence classes. @@ -304,38 +344,3 @@ Steps 1 is performed at tool activation time. Steps 2–4 are performed at execu - **Cross-equivalence tests**: Verify that querying reachability for one physical manifestation returns tools from equivalent manifestations. - **Access projection tests**: Each built-in handler's `project_access` method is tested for correct path computation, sandbox path rewriting, and protocol assignment. - **Routing tests**: Read routing prefers LSP sources over filesystem sources. Write routing uses the canonical write target. - -## Related ADRs - -| ADR | Title | Relationship | -|-----|-------|-------------| -| [ADR-008](ADR-008-resource-system.md) | Resource System | Resource DAG provides the containment and equivalence structure for reachability | -| [ADR-011](ADR-011-tool-system.md) | Tool System | Tools declare resource slots; this ADR extends binding resolution with transitive reachability | -| [ADR-036](ADR-036-resource-dag-operational-semantics.md) | Resource DAG Operational Semantics | Defines purposes 1–3 (reachability, equivalence, routing) that this ADR formalizes | -| [ADR-038](ADR-038-cross-mechanism-sandbox-coordination.md) | Cross-Mechanism Sandbox Coordination | Routing decisions must account for cross-mechanism coherence and sandbox coordination | -| [ADR-039](ADR-039-container-resource-types.md) | Container and Execution Environment Resource Types | Container resources create alternative reachability paths through mount hierarchies | -| [ADR-040](ADR-040-lsp-resource-types.md) | LSP Resource Types | LSP resources are the primary use case for semantically-rich read routing | - -## Acceptance - -### Votes For - -| Voter | Comment | -|-------|---------| -| Jeffrey Phillips Freeman | Transitive reachability with access projection and read/write routing is the missing link between DAG structure and tool execution | - -**Total: 1** - -### Votes Against - -| Voter | Comment | -|-------|---------| - -**Total: 0** - -### Abstentions - -| Voter | Comment | -|-------|---------| - -**Total: 0** diff --git a/docs/adr/ADR-038-cross-mechanism-sandbox-coordination.md b/docs/adr/ADR-038-cross-mechanism-sandbox-coordination.md index ef5d32d35..ff4f28f57 100644 --- a/docs/adr/ADR-038-cross-mechanism-sandbox-coordination.md +++ b/docs/adr/ADR-038-cross-mechanism-sandbox-coordination.md @@ -1,11 +1,43 @@ -# ADR-038: Cross-Mechanism Sandbox Coordination - -**Status:** Accepted -**Date:** 2026-02-21 -**Supersedes:** None -**Author(s):** Jeffrey Phillips Freeman -**Approver(s):** Jeffrey Phillips Freeman - +--- +adr_number: 38 +title: Cross-Mechanism Sandbox Coordination +status_history: +- - '2026-02-21' + - Proposed + - Jeffrey Phillips Freeman +- - '2026-02-21' + - Accepted + - Jeffrey Phillips Freeman +tier: 3 +authors: +- Jeffrey Phillips Freeman +superseded_by: null +related_adrs: +- number: 8 + title: Resource System + relationship: Virtual resources and equivalence linking are defined here; this ADR adds coherence and coordination on top +- number: 15 + title: Sandbox and Checkpoint + relationship: Sandbox strategies and lazy sandboxing; this ADR extends to cross-mechanism coordination at commit time +- number: 36 + title: Resource DAG Operational Semantics + relationship: Defines sandbox boundary algebra; this ADR addresses what happens when boundaries overlap through equivalence +- number: 37 + title: Tool Reachability and Access Projection + relationship: Routing decisions must account for coherence and canonical write targets defined here +- number: 39 + title: Container Resource Types + relationship: Container mounts create the primary cross-mechanism equivalence scenarios +- number: 40 + title: LSP Resource Types + relationship: LSP documents have `cached` coherence with backing filesystem files +acceptance: + votes_for: + - voter: Jeffrey Phillips Freeman + comment: Coherence + write-then-sync + lazy materialization is the right balance between correctness and efficiency for cross-mechanism coordination + votes_against: [] + abstentions: [] +--- ## Context ADR-015 defines per-plan sandboxes with five isolation strategies and lazy sandboxing. ADR-036 formalizes sandbox boundaries as a DAG property. However, when the same virtual resource has physical manifestations in **different sandbox domains** — for example, a file accessible through both a git-checkout sandbox (git_worktree) and a Docker container sandbox (snapshot) — the current design does not address: @@ -15,6 +47,14 @@ ADR-015 defines per-plan sandboxes with five isolation strategies and lazy sandb 3. **What happens when the same virtual resource is written through different domains?** This is a conflict that must be detected and resolved. 4. **When should virtual resource nodes be created and destroyed?** Eagerly creating virtual hubs for every resource wastes storage; never creating them loses equivalence information. +## Decision Drivers + +- The same virtual resource may have physical manifestations in different sandbox domains (e.g., git-checkout sandbox and Docker container snapshot), and writes in one domain are not automatically visible in the other +- Sandbox commit must coordinate across domains so that changes in a git sandbox are reflected in container domains sharing the same virtual resource +- Cross-domain write conflicts (same virtual resource modified through different sandbox domains) must be detected before changes are applied to real resources +- Virtual resource nodes for every physical resource would waste storage; equivalence information is only needed when a second manifestation sharing the same identity is discovered +- The relationship between physical manifestations varies — bind mounts are transparent, LSP buffers are cached, volume copies are independent — and the coordination protocol must account for these differences + ## Decision CleverAgents defines a **coherence property** on physical-to-virtual edges that describes the relationship between a physical resource and its virtual identity, a **write-then-sync** coordination protocol for sandbox commits, **lazy virtual node materialization** for efficient equivalence tracking, and **conflict detection** for cross-domain writes. @@ -266,38 +306,3 @@ The `SandboxManager` is extended to support cross-mechanism coordination: - **Conflict detection tests**: Verify that cross-domain writes to the same virtual resource are detected and resolved according to the configured strategy. - **Lazy materialization tests**: Verify that virtual nodes are created when a second manifestation is discovered, and cleaned up when collapsed back to single manifestation. - **Coherence refresh tests**: Verify that `cached` coherence triggers the correct refresh signal (e.g., LSP notification) and that `transparent` coherence requires no action. - -## Related ADRs - -| ADR | Title | Relationship | -|-----|-------|-------------| -| [ADR-008](ADR-008-resource-system.md) | Resource System | Virtual resources and equivalence linking are defined here; this ADR adds coherence and coordination on top | -| [ADR-015](ADR-015-sandbox-and-checkpoint.md) | Sandbox and Checkpoint | Sandbox strategies and lazy sandboxing; this ADR extends to cross-mechanism coordination at commit time | -| [ADR-036](ADR-036-resource-dag-operational-semantics.md) | Resource DAG Operational Semantics | Defines sandbox boundary algebra; this ADR addresses what happens when boundaries overlap through equivalence | -| [ADR-037](ADR-037-tool-reachability-and-access-projection.md) | Tool Reachability and Access Projection | Routing decisions must account for coherence and canonical write targets defined here | -| [ADR-039](ADR-039-container-resource-types.md) | Container Resource Types | Container mounts create the primary cross-mechanism equivalence scenarios | -| [ADR-040](ADR-040-lsp-resource-types.md) | LSP Resource Types | LSP documents have `cached` coherence with backing filesystem files | - -## Acceptance - -### Votes For - -| Voter | Comment | -|-------|---------| -| Jeffrey Phillips Freeman | Coherence + write-then-sync + lazy materialization is the right balance between correctness and efficiency for cross-mechanism coordination | - -**Total: 1** - -### Votes Against - -| Voter | Comment | -|-------|---------| - -**Total: 0** - -### Abstentions - -| Voter | Comment | -|-------|---------| - -**Total: 0** diff --git a/docs/adr/ADR-039-container-resource-types.md b/docs/adr/ADR-039-container-resource-types.md index d2a9a96f1..fea278aad 100644 --- a/docs/adr/ADR-039-container-resource-types.md +++ b/docs/adr/ADR-039-container-resource-types.md @@ -1,17 +1,57 @@ -# ADR-039: Container and Execution Environment Resource Types - -**Status:** Accepted -**Date:** 2026-02-21 -**Supersedes:** None -**Author(s):** Jeffrey Phillips Freeman -**Approver(s):** Jeffrey Phillips Freeman - +--- +adr_number: 39 +title: Container and Execution Environment Resource Types +status_history: +- - '2026-02-21' + - Proposed + - Jeffrey Phillips Freeman +- - '2026-02-21' + - Accepted + - Jeffrey Phillips Freeman +tier: 4 +authors: +- Jeffrey Phillips Freeman +superseded_by: null +related_adrs: +- number: 8 + title: Resource System + relationship: These types extend the built-in resource type registry +- number: 36 + title: Resource DAG Operational Semantics + relationship: Container types create new sandbox domains subject to the sandbox boundary algebra +- number: 38 + title: Cross-Mechanism Sandbox Coordination + relationship: Container/host equivalence is the primary use case for cross-mechanism coordination +- number: 40 + title: LSP Resource Types + relationship: LSP servers may run inside containers, referencing container executables +- number: 42 + title: Resource Type Inheritance + relationship: Provides the inheritance mechanism enabling subtypes of container-instance (e.g., devcontainer-instance) +- number: 43 + title: Devcontainer Integration and Container-Project Association + relationship: Defines devcontainer-instance as a subtype of container-instance with auto-detection, container-project association patterns, and execution environment routing +acceptance: + votes_for: + - voter: Jeffrey Phillips Freeman + comment: Engine-agnostic container types with executable discovery enable tool dependency resolution and cross-mechanism coordination + votes_against: [] + abstentions: [] +--- ## Context CleverAgents operates on diverse resources — git repositories, filesystems, databases, APIs — but the current 24 built-in resource types do not model containerized environments. Modern development workflows depend heavily on containers for reproducible builds, isolated tool execution, and consistent development environments. Tools, LSP servers, and other executables may be available only inside specific containers. The system needs resource types that represent container engines, images, instances, mounts, volumes, and execution environments so that the resource DAG can reason about tool availability, sandbox coordination across host and container boundaries, and equivalence between host files and container-mounted files. These types must be **engine-agnostic** — representing containers abstractly regardless of whether the underlying engine is Docker, Podman, containerd, LXC/LXD, CRI-O, or another runtime. +## Decision Drivers + +- Modern development workflows depend on containers for reproducible builds and isolated tool execution, but the current 24 built-in resource types cannot model containerized environments +- Tools, LSP servers, and executables may only be available inside specific containers; the system must reason about tool availability across host and container boundaries +- Container types must be engine-agnostic — Docker, Podman, containerd, LXC/LXD, and CRI-O must be supported without structural changes to the DAG +- Bind-mounted files create virtual equivalence between host and container filesystem paths, requiring cross-mechanism sandbox coordination (ADR-038) +- Executable discovery within containers is essential for answering "where can I run this tool?" in heterogeneous environments + ## Decision CleverAgents adds **seven new built-in physical resource types** for modeling containerized environments, plus one type for executable discovery. These types integrate into the existing resource DAG with containment edges, virtual equivalence links (for files accessible through both host and container), and reference edges (for tool/executable dependencies). @@ -265,38 +305,3 @@ The engine-specific details are encapsulated in the resource handler — the res - **Mount equivalence tests**: Bind mount files correctly link to host files through virtual parents with `transparent` coherence. - **Executable discovery tests**: Container exec-env scanning correctly identifies executables and links them to `file` virtual parents when content hashes match host executables. - **Engine abstraction tests**: The same test suite runs against Docker and Podman handlers to verify engine-agnostic behavior. - -## Related ADRs - -| ADR | Title | Relationship | -|-----|-------|-------------| -| [ADR-008](ADR-008-resource-system.md) | Resource System | These types extend the built-in resource type registry | -| [ADR-036](ADR-036-resource-dag-operational-semantics.md) | Resource DAG Operational Semantics | Container types create new sandbox domains subject to the sandbox boundary algebra | -| [ADR-038](ADR-038-cross-mechanism-sandbox-coordination.md) | Cross-Mechanism Sandbox Coordination | Container/host equivalence is the primary use case for cross-mechanism coordination | -| [ADR-040](ADR-040-lsp-resource-types.md) | LSP Resource Types | LSP servers may run inside containers, referencing container executables | -| [ADR-042](ADR-042-resource-type-inheritance.md) | Resource Type Inheritance | Provides the inheritance mechanism enabling subtypes of container-instance (e.g., devcontainer-instance) | -| [ADR-043](ADR-043-devcontainer-integration.md) | Devcontainer Integration and Container-Project Association | Defines devcontainer-instance as a subtype of container-instance with auto-detection, container-project association patterns, and execution environment routing | - -## Acceptance - -### Votes For - -| Voter | Comment | -|-------|---------| -| Jeffrey Phillips Freeman | Engine-agnostic container types with executable discovery enable tool dependency resolution and cross-mechanism coordination | - -**Total: 1** - -### Votes Against - -| Voter | Comment | -|-------|---------| - -**Total: 0** - -### Abstentions - -| Voter | Comment | -|-------|---------| - -**Total: 0** diff --git a/docs/adr/ADR-040-lsp-resource-types.md b/docs/adr/ADR-040-lsp-resource-types.md index 46653d165..be8bed2d6 100644 --- a/docs/adr/ADR-040-lsp-resource-types.md +++ b/docs/adr/ADR-040-lsp-resource-types.md @@ -1,11 +1,46 @@ -# ADR-040: Language Server Protocol Resource Types - -**Status:** Accepted -**Date:** 2026-02-21 -**Supersedes:** None -**Author(s):** Jeffrey Phillips Freeman -**Approver(s):** Jeffrey Phillips Freeman - +--- +adr_number: 40 +title: Language Server Protocol Resource Types +status_history: +- - '2026-02-21' + - Proposed + - Jeffrey Phillips Freeman +- - '2026-02-21' + - Accepted + - Jeffrey Phillips Freeman +tier: 4 +authors: +- Jeffrey Phillips Freeman +superseded_by: null +related_adrs: +- number: 8 + title: Resource System + relationship: These types extend the built-in resource type registry +- number: 27 + title: Language Server Protocol + relationship: ADR-027 defines CleverAgents as an LSP server; this ADR defines external LSP servers as resources +- number: 29 + title: Model Context Protocol (MCP) Adoption + relationship: Analogous integration pattern — MCP tools as external resources with sandbox path rewriting +- number: 36 + title: Resource DAG Operational Semantics + relationship: LSP document equivalence creates cross-mechanism coherence scenarios +- number: 37 + title: Tool Reachability and Access Projection + relationship: LSP documents as preferred read sources in read/write routing +- number: 38 + title: Cross-Mechanism Sandbox Coordination + relationship: '`cached` coherence between LSP documents and filesystem files' +- number: 39 + title: Container and Execution Environment Resource Types + relationship: LSP servers may run inside containers, depending on container executables +acceptance: + votes_for: + - voter: Jeffrey Phillips Freeman + comment: LSP resource types enable semantic read routing and principled sandbox coordination with language servers + votes_against: [] + abstentions: [] +--- ## Context ADR-027 defines an LSP server as a Presentation-layer adapter — CleverAgents exposes plan-aware diagnostics and code actions to IDEs. But the inverse relationship is equally important: external LSP servers (pylsp, typescript-language-server, rust-analyzer, etc.) are **rich read sources** for resources that CleverAgents operates on. An LSP server provides semantic understanding — type information, go-to-definition, find-references, diagnostics, completions — that far exceeds what raw file reading can offer. The resource DAG currently has no way to represent these LSP servers, their workspaces, or their documents as resources, which means the system cannot reason about: @@ -15,6 +50,14 @@ ADR-027 defines an LSP server as a Presentation-layer adapter — CleverAgents e 3. **How LSP documents relate to filesystem files** (they are equivalent physical manifestations of the same virtual file identity, with `cached` coherence). 4. **How to route reads through LSP** for richer semantic access versus raw filesystem reads. +## Decision Drivers + +- External LSP servers provide semantic understanding (type info, go-to-definition, diagnostics) that far exceeds raw file reading, but the resource DAG has no way to represent them +- The system must know which LSP servers are available for a given workspace/language and where they run (host, container, remote) +- LSP documents and filesystem files are equivalent physical manifestations of the same virtual file identity, requiring `cached` coherence and cross-mechanism coordination +- Read routing should prefer semantically rich LSP access paths over raw filesystem reads when semantic understanding is needed +- LSP servers read from the real filesystem by default, not from sandboxes; sandbox path rewriting is needed for accurate post-change semantic analysis during plan execution + ## Decision CleverAgents adds **three new built-in physical resource types** for modeling LSP server infrastructure: `lsp-server`, `lsp-workspace`, and `lsp-document`. These integrate into the resource DAG with containment edges (server → workspace → document), reference edges (server → executable dependency, workspace → backing filesystem), and virtual equivalence links (document ↔ filesystem file through shared `file` virtual parent). @@ -189,39 +232,3 @@ This sandbox path rewriting for LSP is analogous to the sandbox path rewriting a - **Coherence tests**: Modifying the backing file through a sandbox write triggers LSP notification and document re-indexing. - **Sandbox path rewriting tests**: LSP workspace root correctly updates to sandbox path when a sandbox is created. - **Executable dependency tests**: LSP server registration correctly resolves executable dependencies through `references` edges. - -## Related ADRs - -| ADR | Title | Relationship | -|-----|-------|-------------| -| [ADR-008](ADR-008-resource-system.md) | Resource System | These types extend the built-in resource type registry | -| [ADR-027](ADR-027-language-server-protocol.md) | Language Server Protocol | ADR-027 defines CleverAgents as an LSP server; this ADR defines external LSP servers as resources | -| [ADR-029](ADR-029-model-context-protocol.md) | Model Context Protocol (MCP) Adoption | Analogous integration pattern — MCP tools as external resources with sandbox path rewriting | -| [ADR-036](ADR-036-resource-dag-operational-semantics.md) | Resource DAG Operational Semantics | LSP document equivalence creates cross-mechanism coherence scenarios | -| [ADR-037](ADR-037-tool-reachability-and-access-projection.md) | Tool Reachability and Access Projection | LSP documents as preferred read sources in read/write routing | -| [ADR-038](ADR-038-cross-mechanism-sandbox-coordination.md) | Cross-Mechanism Sandbox Coordination | `cached` coherence between LSP documents and filesystem files | -| [ADR-039](ADR-039-container-resource-types.md) | Container and Execution Environment Resource Types | LSP servers may run inside containers, depending on container executables | - -## Acceptance - -### Votes For - -| Voter | Comment | -|-------|---------| -| Jeffrey Phillips Freeman | LSP resource types enable semantic read routing and principled sandbox coordination with language servers | - -**Total: 1** - -### Votes Against - -| Voter | Comment | -|-------|---------| - -**Total: 0** - -### Abstentions - -| Voter | Comment | -|-------|---------| - -**Total: 0** diff --git a/docs/adr/ADR-041-safety-profile-extraction.md b/docs/adr/ADR-041-safety-profile-extraction.md index 16dbbc970..06d9a42ed 100644 --- a/docs/adr/ADR-041-safety-profile-extraction.md +++ b/docs/adr/ADR-041-safety-profile-extraction.md @@ -1,11 +1,37 @@ -# ADR-041: Safety Profile Extraction - -**Status:** Accepted -**Date:** 2026-02-27 -**Supersedes:** None -**Author(s):** Jeffrey Phillips Freeman -**Approver(s):** Jeffrey Phillips Freeman - +--- +adr_number: 41 +title: Safety Profile Extraction +status_history: +- - '2026-02-27' + - Proposed + - Jeffrey Phillips Freeman +- - '2026-02-27' + - Accepted + - Jeffrey Phillips Freeman +tier: 3 +authors: +- Jeffrey Phillips Freeman +superseded_by: null +related_adrs: +- number: 17 + title: Automation Profiles + relationship: SafetyProfile is composed within AutomationProfile; this ADR refines ADR-017's profile structure +- number: 6 + title: Plan Lifecycle + relationship: Safety constraints gate lifecycle phase execution (sandbox, checkpoints) +- number: 15 + title: Sandbox and Checkpoint + relationship: '`require_sandbox` and `require_checkpoints` flags control sandbox/checkpoint enforcement' +- number: 18 + title: Semantic Error Prevention + relationship: Safety profile constraints are a form of pre-flight guardrail +acceptance: + votes_for: + - voter: Jeffrey Phillips Freeman + comment: Composition eliminates dual authority while preserving standalone safety profile use on Actions + votes_against: [] + abstentions: [] +--- ## Context Issue [#332](https://git.cleverthis.com/cleveragents/cleveragents-core/issues/332) introduced a standalone `SafetyProfile` domain model to capture hard safety constraints (sandbox requirements, checkpoint enforcement, unsafe-tool gating, skill category restrictions, cost/retry limits, and human-approval flags). However, the original specification placed three of these fields (`require_sandbox`, `require_checkpoints`, `allow_unsafe_tools`) directly on the `AutomationProfile` model alongside its 11 confidence thresholds. @@ -14,6 +40,14 @@ Implementing `SafetyProfile` as a separate, parallel model created **overlapping This dual-model overlap was identified during implementation review (see [#332 comment](https://git.cleverthis.com/cleveragents/cleveragents-core/issues/332#issuecomment-43934)). +## Decision Drivers + +- Three safety booleans (`require_sandbox`, `require_checkpoints`, `allow_unsafe_tools`) existed on both `AutomationProfile` and standalone `SafetyProfile`, creating overlapping authority with no spec-defined conflict resolution +- Safety constraints (binary invariants like sandbox enforcement) are fundamentally different from autonomy thresholds (confidence-gated behavior) and should be cleanly separated +- `SafetyProfile` must be usable standalone on Actions for lightweight safety-only configurations without requiring a full automation profile +- New safety-specific fields (cost limits, retry caps, skill category restrictions, human-approval flags) need a dedicated home that does not bloat `AutomationProfile` +- Resolution precedence (plan > action > project > global) must apply to safety constraints identically to automation profiles + ## Decision CleverAgents extracts all safety constraints into a **`SafetyProfile` sub-model** that is **composed** within `AutomationProfile` via a `safety` field. The three previously top-level safety booleans (`require_sandbox`, `require_checkpoints`, `allow_unsafe_tools`) move from `AutomationProfile`'s top level into the composed `SafetyProfile`, which also adds new safety-specific fields (`require_human_approval`, `allowed_skill_categories`, `max_cost_per_plan`, `max_retries_per_step`, `max_total_cost`). @@ -108,36 +142,3 @@ Safety profile resolution follows the same precedence as automation profiles: `p - **Cross-field validation tests**: Tests verify that `max_cost_per_plan > max_total_cost` raises `ValueError`. - **BDD scenarios**: Behave features exercise safety profile parsing, constraint validation, YAML loading, and plan-level resolution. - **Persistence tests**: Tests verify correct JSON serialization/deserialization of the composed `safety` field in the database. - -## Related ADRs - -| ADR | Title | Relationship | -|-----|-------|-------------| -| [ADR-017](ADR-017-automation-profiles.md) | Automation Profiles | SafetyProfile is composed within AutomationProfile; this ADR refines ADR-017's profile structure | -| [ADR-006](ADR-006-plan-lifecycle.md) | Plan Lifecycle | Safety constraints gate lifecycle phase execution (sandbox, checkpoints) | -| [ADR-015](ADR-015-sandbox-and-checkpoint.md) | Sandbox and Checkpoint | `require_sandbox` and `require_checkpoints` flags control sandbox/checkpoint enforcement | -| [ADR-018](ADR-018-semantic-error-prevention.md) | Semantic Error Prevention | Safety profile constraints are a form of pre-flight guardrail | - -## Acceptance - -### Votes For - -| Voter | Comment | -|-------|---------| -| Jeffrey Phillips Freeman | Composition eliminates dual authority while preserving standalone safety profile use on Actions | - -**Total: 1** - -### Votes Against - -| Voter | Comment | -|-------|---------| - -**Total: 0** - -### Abstentions - -| Voter | Comment | -|-------|---------| - -**Total: 0** diff --git a/docs/adr/ADR-042-resource-type-inheritance.md b/docs/adr/ADR-042-resource-type-inheritance.md index a09942171..257118058 100644 --- a/docs/adr/ADR-042-resource-type-inheritance.md +++ b/docs/adr/ADR-042-resource-type-inheritance.md @@ -1,11 +1,43 @@ -# ADR-042: Resource Type Inheritance - -**Status:** Accepted -**Date:** 2026-03-01 -**Supersedes:** None -**Author(s):** Jeffrey Phillips Freeman -**Approver(s):** Jeffrey Phillips Freeman - +--- +adr_number: 42 +title: Resource Type Inheritance +status_history: +- - '2026-03-01' + - Proposed + - Jeffrey Phillips Freeman +- - '2026-03-01' + - Accepted + - Jeffrey Phillips Freeman +tier: 3 +authors: +- Jeffrey Phillips Freeman +superseded_by: null +related_adrs: +- number: 8 + title: Resource System + relationship: Extends the resource type registry with inheritance semantics +- number: 11 + title: Tool System + relationship: Tool resource bindings gain polymorphic subtype matching +- number: 36 + title: Resource DAG Operational Semantics + relationship: DAG queries gain polymorphic type filtering +- number: 37 + title: Tool Reachability and Access Projection + relationship: Reachability computation considers subtype relationships +- number: 39 + title: Container and Execution Environment Resource Types + relationship: Container types are the primary use case for type inheritance +- number: 43 + title: Devcontainer Integration and Container-Project Association + relationship: First concrete subtype (`devcontainer-instance`) built on this mechanism +acceptance: + votes_for: + - voter: Jeffrey Phillips Freeman + comment: Single-inheritance with polymorphic tool binding enables extensible container specialization without duplicating type definitions + votes_against: [] + abstentions: [] +--- ## Context CleverAgents defines resource types as flat, independent definitions — each type declares its own properties, capabilities, child types, sandbox strategy, and handler from scratch. This works well for types that are fundamentally different (e.g., `git-checkout` vs. `fs-directory` vs. `container-instance`), but creates significant problems when types share a core identity with specialized behavior. @@ -16,6 +48,14 @@ Without a type inheritance mechanism, each specialization would need to duplicat The same pattern appears in other parts of the type hierarchy: database types sharing common query interfaces, cloud resource types sharing API access patterns, and document types sharing structural properties. A general-purpose inheritance mechanism addresses all of these cases. +## Decision Drivers + +- Specialized container types (devcontainer, docker-compose, kubernetes pod) share the core identity of `container-instance` but each adds provisioning-specific configuration, discovery, and lifecycle behavior +- Without inheritance, each specialization must duplicate every field from its logical parent, and tools bound to the parent type cannot work with specialized types +- Tool bindings, auto-discovery child type matching, and DAG queries must be polymorphic — referencing a parent type must automatically include all subtypes +- The pattern applies beyond containers: databases, cloud resources, and document types all exhibit shared-base-with-specialization relationships +- Inheritance must be simple (single-parent) and bounded in depth to prevent pathological hierarchies and ensure resolution performance + ## Decision CleverAgents introduces **single-inheritance resource type specialization** via an `inherits` field on resource type definitions. A subtype inherits all properties, capabilities, child type constraints, sandbox strategy, and handler behavior from its parent type, and can selectively override or extend any inherited field. Tool bindings, auto-discovery child type matching, and DAG queries that reference a parent type automatically include all subtypes — this is the core polymorphism guarantee. @@ -219,38 +259,3 @@ Potential future applications of type inheritance include: - **Cycle detection tests**: Circular `inherits` chains are rejected at registration time. - **Depth limit tests**: Chains exceeding 5 levels are rejected. - **Parent removal tests**: Attempting to remove a type with registered subtypes fails with a descriptive error. - -## Related ADRs - -| ADR | Title | Relationship | -|-----|-------|-------------| -| [ADR-008](ADR-008-resource-system.md) | Resource System | Extends the resource type registry with inheritance semantics | -| [ADR-011](ADR-011-tool-system.md) | Tool System | Tool resource bindings gain polymorphic subtype matching | -| [ADR-036](ADR-036-resource-dag-operational-semantics.md) | Resource DAG Operational Semantics | DAG queries gain polymorphic type filtering | -| [ADR-037](ADR-037-tool-reachability-and-access-projection.md) | Tool Reachability and Access Projection | Reachability computation considers subtype relationships | -| [ADR-039](ADR-039-container-resource-types.md) | Container and Execution Environment Resource Types | Container types are the primary use case for type inheritance | -| [ADR-043](ADR-043-devcontainer-integration.md) | Devcontainer Integration and Container-Project Association | First concrete subtype (`devcontainer-instance`) built on this mechanism | - -## Acceptance - -### Votes For - -| Voter | Comment | -|-------|---------| -| Jeffrey Phillips Freeman | Single-inheritance with polymorphic tool binding enables extensible container specialization without duplicating type definitions | - -**Total: 1** - -### Votes Against - -| Voter | Comment | -|-------|---------| - -**Total: 0** - -### Abstentions - -| Voter | Comment | -|-------|---------| - -**Total: 0** diff --git a/docs/adr/ADR-043-devcontainer-integration.md b/docs/adr/ADR-043-devcontainer-integration.md index ed910f810..3623a280d 100644 --- a/docs/adr/ADR-043-devcontainer-integration.md +++ b/docs/adr/ADR-043-devcontainer-integration.md @@ -1,11 +1,46 @@ -# ADR-043: Devcontainer Integration and Container-Project Association - -**Status:** Accepted -**Date:** 2026-03-01 -**Supersedes:** None -**Author(s):** Jeffrey Phillips Freeman -**Approver(s):** Jeffrey Phillips Freeman - +--- +adr_number: 43 +title: Devcontainer Integration and Container-Project Association +status_history: +- - '2026-03-01' + - Proposed + - Jeffrey Phillips Freeman +- - '2026-03-01' + - Accepted + - Jeffrey Phillips Freeman +tier: 4 +authors: +- Jeffrey Phillips Freeman +superseded_by: null +related_adrs: +- number: 8 + title: Resource System + relationship: Devcontainer-instance extends the built-in resource type registry +- number: 9 + title: Project Model + relationship: Execution environment routing adds configuration to the project model +- number: 15 + title: Sandbox and Checkpoint + relationship: Devcontainer sandbox coordination builds on the sandbox model +- number: 36 + title: Resource DAG Operational Semantics + relationship: Devcontainer instances create new sandbox domains in the DAG +- number: 38 + title: Cross-Mechanism Sandbox Coordination + relationship: Devcontainer bind mounts are a key use case for cross-mechanism coordination +- number: 39 + title: Container and Execution Environment Resource Types + relationship: Devcontainer-instance inherits from container-instance defined here +- number: 42 + title: Resource Type Inheritance + relationship: Provides the inheritance mechanism that devcontainer-instance uses +acceptance: + votes_for: + - voter: Jeffrey Phillips Freeman + comment: Auto-detected devcontainers with lazy activation and precedence-based routing enable seamless container integration without disrupting existing workflows + votes_against: [] + abstentions: [] +--- ## Context Modern software development increasingly relies on containerized development environments for reproducibility, isolation, and consistency. The [Development Containers Specification](https://containers.dev) (devcontainers) has emerged as a widely adopted standard for defining these environments via a `.devcontainer/devcontainer.json` configuration file. IDEs (VS Code, IntelliJ), cloud development environments (GitHub Codespaces, Gitpod), and CI systems recognize this standard. @@ -18,6 +53,14 @@ CleverAgents already models containers as first-class resources (ADR-039) and su Without these capabilities, users must manually configure container environments outside of CleverAgents and ensure tools execute in the right context — losing the system's ability to reason about execution environments, sandbox coordination, and tool dependency resolution. +## Decision Drivers + +- The devcontainer specification (`.devcontainer/devcontainer.json`) is widely adopted by IDEs and cloud environments, and projects containing it should be auto-detected without manual container configuration +- Three distinct container-project association patterns exist (auto-detected devcontainer, explicit mount, remote clone) and all must be expressible through the resource linking model +- Execution environment routing must resolve deterministically when multiple containers and devcontainers coexist, with clear precedence (plan > project > auto-detected > fallback > host) +- Devcontainer builds can be slow; containers should not be built at discovery time but lazily activated on first plan execution, consistent with the system's lazy sandboxing philosophy +- Monorepos with per-service devcontainer configurations require nearest-ancestor resolution to select the correct container for each file path + ## Decision CleverAgents introduces: @@ -415,39 +458,3 @@ During plan execution inside a devcontainer: - **Priority override tests**: `priority: override` correctly overrides auto-detected devcontainers; `priority: fallback` correctly defers to them. - **Sandbox coordination tests**: Bind-mounted devcontainer files have `transparent` coherence; volume-mounted files have `independent` coherence. - **Type inheritance tests**: `devcontainer-instance` is correctly recognized as a subtype of `container-instance` by tool bindings, auto-discovery, and DAG queries. - -## Related ADRs - -| ADR | Title | Relationship | -|-----|-------|-------------| -| [ADR-008](ADR-008-resource-system.md) | Resource System | Devcontainer-instance extends the built-in resource type registry | -| [ADR-009](ADR-009-project-model.md) | Project Model | Execution environment routing adds configuration to the project model | -| [ADR-015](ADR-015-sandbox-and-checkpoint.md) | Sandbox and Checkpoint | Devcontainer sandbox coordination builds on the sandbox model | -| [ADR-036](ADR-036-resource-dag-operational-semantics.md) | Resource DAG Operational Semantics | Devcontainer instances create new sandbox domains in the DAG | -| [ADR-038](ADR-038-cross-mechanism-sandbox-coordination.md) | Cross-Mechanism Sandbox Coordination | Devcontainer bind mounts are a key use case for cross-mechanism coordination | -| [ADR-039](ADR-039-container-resource-types.md) | Container and Execution Environment Resource Types | Devcontainer-instance inherits from container-instance defined here | -| [ADR-042](ADR-042-resource-type-inheritance.md) | Resource Type Inheritance | Provides the inheritance mechanism that devcontainer-instance uses | - -## Acceptance - -### Votes For - -| Voter | Comment | -|-------|---------| -| Jeffrey Phillips Freeman | Auto-detected devcontainers with lazy activation and precedence-based routing enable seamless container integration without disrupting existing workflows | - -**Total: 1** - -### Votes Against - -| Voter | Comment | -|-------|---------| - -**Total: 0** - -### Abstentions - -| Voter | Comment | -|-------|---------| - -**Total: 0** diff --git a/docs/adr/img/adr-workflow.png b/docs/adr/img/adr-workflow.png new file mode 100644 index 0000000000000000000000000000000000000000..ff14ec75e8a64ee3e6f0df36fe680703a341a849 GIT binary patch literal 10767 zcmaL7byOTp@GgwI26ul1Pn}dJo=*%A`A@k4|!<`4G-9p zRaB6M<~s8EIt;gE0LOQXL0U)?LtdJBx^M-vIh%YF%?Gm|T6%@?=Azbm-**3|eEjzC zt0W~QxyAfO17am=&77APv;%|2#@*SvkI}<1%po3x)pPc6ze2vZ;+;;SwEuYalI@H{ zP5b|702;&yXgf}lfLY~6gEa+aic7yXxA;IITxe58?Ci{X?E!&vg#CA(l8_L1eeGgu zW<~8p6duHYbs0e~E@{D%_wc#Nl_-qP)F}TD1Lg)u|3{h_b!YqkJ z@I?gYg7tGReLl>PykHuPlE+Uu`}2y~I9|zoE^YVt+jNTJroC|&L#a~>oc4(+<#$hf zraRX#MM>fte^6twSW&n`A|tHq*~A-~EVk~P*lIOL9pUutwFaGtk~v_b;wcwwrh=cU zPO*J+8`6*Fa3}nJp)=+9B6_p$uBa6rb0Kqwu~e^t3Z)4usS#vuBq}8+HY)*-)rbfP z8wXSQjZV90Ol3;~NT<-DXc!IVQaI6CPl0d*jhVN)oz8CqXLYz=2u4TrBETY&_RLf( ztslB@?Z-PQam(^W1t+osQtZ(VzPg!gdsBUGA16}p7q(qtXZp^Ro%4uqefaasbstYz z<`rM7HM^v?{=VWpAyvl(>{mL2&J9o8b0wjeG3Py_XCGe1n8?wV?>OVOi;<>3&@sIE zw$H!!Tjr_J89(ar;DEjDf9>ns^&_oVh<2c9_L+6d-$Qz&V{jibinal>TVhNx*jK}c z5~)>W>!Y4TKfhvlI6E=vJY4Tsd`n5`?_3=RQ@BH4iV}{UsJBkM`1+YEyyue$G(6V$ zNN$tV_tCEWZu*|Qbq$^^6Pck}U9tABTYcWRS|CZ-yd;fmp)b;uux`mSA+i4@jEdurI;~p_J%I#+zIjb|f~lB=)JomX`+x zE@`4Cx3siyJ66IFH{#*qCamhTdHqqkhz9}8Q@cJdd}D>bj6n zTS!$bfDsG_WR0R9bt}UGwRnHA&#YNf16xLZo2C8Pv2LOkydDKCC?>J$!A>xA}YlPX}6VjhhN4&G2)Q<0aVtD#-Qk zRW=108yhc`>(!N%OXgYv>Lba3_R?2-V^iNH;7vTAzr=lg2VdNCk5}~h94)v~)(EW% zmdO>zhi5$WhA$56Zvm%QLZH$-WW>}^Sg}idYq9Qw#vA7o&~!D?^==Y7#qf{mN$XmB zy9)XHe#9);=fdxTCKHmj!W;4Rbl%^!e%T+tYzsP_i!zGbi|#N;*RKWm>c{1kg1?s7 zHQAGHpJ#0yC{uNrS>oUxSl0=2bN`HC{{j(qjCoxp7n6^VkELiWZ}CZPahi_v8yXs# z%IHn1ow=qRc~8id9MU5-m+Q`>Ps7ibhbs%L#+G@nI9v%p@K^nf>y))0`#DeZKzM(+ znrAy=4EOwvC|?X_Jbm-Ma_dhme7OCEl#1x-{@j_{>O3;UnR?|m^Y3-1IDqF^-aHYq z4(L?J>Q~{jyP!xHW)_tEy#G-xi{`6(#?Zk^LbNT`7lnN*PBn#`Wv!3>v||AXANlhC zy`jfp%**Wx!ou`$cPiT2^E@NR&3fgsYHDA>s8UBY3H%M%&xsx6J5`lmWNN2CAJ}oR z^gT`{E+e({kBBKEHOG$CDP5+-~WuPXfs==BG!ez89rFjL@#gStc#ikNeRoH({e;vQ0EJ}dg zCY_Q6l|4*SX$+MCnc=@rIyn7rA^kAQbMI1*vM??1dd>LX;u__;yfdwhj78pvEA66v zk)aN~X^=6&?96i+n8Rhs)QtS!{FQC(sM9`l=W@M9%E52EHnI`^vU_`b6*wd}^3-|W zaU`!Jp{nz{!yGtt}oP<@A z4JB#m-6*1Dv-~nPM#V(sT^%>aOJ>!+?pKHfc~h0?1D)T>{{DV8WL(X+|K?<8!!%{p z>5@6vEiWpP$pv#@T&|0nt~H9W36O#;p-K4>o)g~@^EtE&R2X2E-ET&nj(tjIu3-QG56*gyp+mvt#UoS_)Ub)8uf%DB~O#p z)&?CQdJCEBFX-5z(-#>X{Sm5@<#F0^OgR>ts3_(0^D{*ECnF%}f55a2$T7d#Dzigb zhC9)b`NeRJQWUGVI(U;?UzCst1^lWF{{rV?dY&NvV$*D~I2r3p~ehIhvejq4n3?AVzKP}by`7nm~2uN2mK zk)?I1E`ocT)z@@@XIOJ%UmuEGf7SNplaI82G+i{@ts{S8q01sVLL;`_bO_mKFVlaDrVx>tL4{CxR_H#YkaQpNItw1*LN;Uk9wDs3g91{q1g-#jezdAv@Z zhe0W~+19xe=X@TbqdiMU@6czY`s=ti z3ZcjqPJ7M^9G~Gxpl#7v3p=qZ8Ah*j!Y3TtAINNWSxL|}5pmKMY&WB!Buc^WxWR^# z&||z|zrRziE?`t@$!5u8&b)>;A^WS+hQs@Y#Y4auHsuzJH&u+oiDu1G6>)LMyXy0y z9I=29jy|I>hPH|4oAzZFm1`!n$67zCiuz-e5ga+989e90TR8}TeG&*++02jX-OqAW zIfyg){SmLatuN!w<9*tNkNw)5HgWP9&AWH8U8*F*Lqh^PJ3F;TW8Zk&$`IxH<|!2mZWO5r?V3**VWb+v1OZS~--I+5S`JRL;X*r6A1cst560O%K6 zt$5+(a+i;OcgktQhee&ux}vN{`zL07^NJh&zhf6Xr%_Mm`94qocqTs0Sg+6Qnm3H; zR&(hrZ5zn1_{g>8uGH^sNV@SbdSsbYhdAAl8Ou$R&rz?Aez)>SV#C)Kf1&SNwG(;s zg||Q8?*Y|=s9?)369-6DQ}`L4YvDBZcN=miwjfBf3CGzzt`DQZHSKxu#mMuDOvUsC z+h#7NC;K~d+H!kj^=j$io+;QiQ-B&6F{crm*gv3o*b(fRfC+y3WnZ@Rm(XCAw2EI4 zZB1*TKg--Ld2KheNmu)JGxLMaU;E%1TgEd1Nkl!b} z48=mTDW3Ag6w|*$A!Oj;ZKGxL(>-f3uhh`KN ze=R3@Mv-CjguQI>39&1KgSz0^&T%Ts!{RfnN`n9m$wS-C(c1>7zK-p?hoDf~4GyEJoW!x$tp6-o2G$;d*%~wu9@uF_D zY2PXgy2F%buZh*wHWfLSyK^G}Hs?17ac}XXr1Id`nS<$?C|%msX0tN1tL$zWOq(BQ z28+%)mdfrrstk`p!fvB6Hu|J9hn*yKOh!PtMBhRisYL`ZQ_C_%j|L6z9BN=)TOwJH z`keXVl_f;3N!LgX%b+Pcwmptr7C?2agJ(N(Y>4wv2M}iNTZ(-S)4_rH-G!{ThwGX0ogGF`@izBb5mrT zT#$3Wif8PI=*cYpVuH&42J76*yhErLmZ%k*ruY`zB|sq_fClLli=8aIP&AHhP#>s6 z^2}2hA2~{fm3YtHzLpy2CAHLLs0sgR33216V#bAcM=GwppdMCo`d_VDD@Y8Qy)6my^T9XTykaJosFg69myRq9}&-@);o-BMKq+= z9Mf{CMvR0#yV8FJ_kfOdt&S{yof&Rc+1MyxmcY5MvqdZjP>{tHZA}%nzeRU~C|n0v zS?*hxh*cm4HhpMW!1p=Iod5?Hp4t#kw<<-BmtLL5HN^DT?o_?|(a2xDY5=HFHNHeI z-T~%Bg@;3rTs=w}0#Fd?eBYq(u^#jdi|NJv&HSuUqao6Q#jZ1(rLYf8e|VAcwm;)0 zx+adKLYLCsxI?wr$M6g)Ea_D2U2fW{dBeWc4&iXeX?jfojehn8D!)eV^z`&lE?dQK zJQ5xrcl48Dj1KA17%S9M2@QCQqroZAg`UDfn7@YIT&yglYnC8TRMVb0x$6RQA5TN- zzg1^+(Fht5atQj~LF&5VRK1V=Zjw)ILw=yE*VbcJT`EkgC;{02lt}VURhhv$H=c>- zJ|8Jcz`*&+!B#g1<4b<+y0_!0k4(ECuDkH zY+#NuM{6}Qsvem0iX_+e=?g_W)NXV3W>K{9@+Rh=GF-^WD0eaS_#uFuc3?H zhSb!8Q;)lySa64k<-|5z4vxcJcwJ|br~&^^Q=++{i?fQrh@-vO7)&9Ki*WS!?-lxQ zf7Tnz)CeKnU~ur*1g4gQo_ z`OVYMimw7RE?MH)VnnH*V|a6m2wwZG&v{nHB-=M9qpD7$3mgeId#c4)V$gTxzP;XG z@EoK1}0fIKm7N)_HxbCAW2#zJD5S z-EFl3qKzN=NU>zML~s|0^?3`qZORV*JUFpwL$B9j+O;6W!@~o>-Ez}jwLAYgoTZbH zPR8OsbyITlke8S5XXq{)>3=c5?o+>q(h!2!J%ZtStLjr+SnTy{;lMriE*dI#AMarj z-0CbDH&OqXA5?il!2Z8|85ddg@YcDNv?QqV#vj5%Nx3&_|ETi2;uZmwpg|07OIbRWG7=CqL z3>1gILa>dlU>uy4G}CN5{HmH_T!(KZe~z3@;W(e4>DB5;o;8}dD1?Pvyz3xAwyyWMFQPsd8I zja(2<$W%bm(L!U%mAK(^*1d&qonP9m5Ayal8Pi(l2A=1Lgy`gkSQ^D*-(eKj*K$GT zGlaJ18lLCqvd1xX>;M7hJq!>CG)xWC0yIU=N=)owZ(_EH z({UdrJK9_AYSwl7QJm;h?!&}X6uGr2i`%KZ*XRy~X1QDh0k)m$YHBgMX;HGJv$VXt z$s}Xm1+?>7m;KG24%POAT1$c?WMnNM^OZi=1U)5Ca-eX;U@m9AsRagKiXk)ufZ-uk z3>{J#8cjG3foA(!JEEi3DHL)gLc6i9SEt6StZP|w@&ZNT2xnxyJ)a7Xy=fx`H>*r) zxWkO+6cZa#ccb7hGyd$DG6)39^UPHtJI%u1FYWXK(q*pB&)@Pn_d?TKjh+9}%y)BR z-NU6y!)H`DEsFTd1+ef)3P`vD_-+brg^gHB%}%>f7e`fQ!R)}M_DT_zVvRi|Z6(n} z3RN&Md2&`1=$}2>`kHlhJm=&Se6hh`a02XONAKK6g!6E5X{t+JB+C{H9z)E4jw8!4prxFr4@l=W zb7ko$v?Y%J$R5o%)z#I`Q1P?@*q@-Bu@zPhO^J>N%fh%L1mj7a9H3sW100$HUjkJ7 zdg3A@PDz{kYaiV=Is+5MrQNz}Zyu;G9PJepM#-Tp$kr<(m-j)z;Qh!Z_m&a1fRC(_ zDI)G7!#_eOIn(O0g#1BNSIK|?_R$u%(>pNY80{Yu#l=LCJm28m?jevRn0($slx;_zc{9sk_q~vnO>Bt0C zfHs}6GHkE%i4E?q5K09F{VR7ZCW%3{F(4qh!z34#a&h4J*YyqOtAT@VF`E8jFjc-; z{q&FNg7iw?h(HC)4bNIABx<{JJt(=j|968Lcli_BK)XM~&wms03^k%^)7OSy<%;Hb zB+Z4bV@etqef|C835&OnL#2-|-yn}~#icdkOas_zpgA9!4Et2|ZPJ99g@uDgu?Cro z;3xK`9rB1ln!)d%uySy*-6KEy)r<}YM+{>?O#pBw?DF>evX&$vl(4N=XFW@Q@$$b7 zu9^)^r7Y7sHmt~LV#BZIpuZh zX1Ygn<*Bn3pIRotw$sC5<^PR^UmzLs=1ap@Gp#5J@|c`J+5E0_ZVPeg+ia^#YwiSx zK@~u<&^x9|K_MYJX6E8aPUyW@%e_&d+N#o6gIwEe1DwOlxv`|YfY$BBAMgFlNk^v} zlX$<|a-w9LWDoeBq8$|0OJ7#h>SGO+Uvcq78%Su5Fm?E#S)|-`+KfngtobSBm#8R- zBD~DeYJYzs(Y>;udzz;koLWULl2wK9ZDDGlKjSVzHV0>j+F7!%Hd;_9QVgy=xpVp! zZ~b`Mkd?vXSdP&Y$gUn!S%0A{7cM@&%g7F^c}m3TJLv2S_4P>Ojt)fnPp_`5{L1z^ zWWEyRTjrUP1g-r<$*EY4o8GVN-XMrrN|@Lxrb&P#G?9HYF53F_rOtz{M0V|TK&*Ra zO04rGYvSB?AxG!sm}SA6dBBB@0R-PYWqXctZKa8~xZH1iy<+HaZ-*3;`_Q}?@#wko z&TM?^Hq4DUDy^%0gV}Ff@eV0x%rLwMb*Pas`y$@sjY#;doNpc6fW>uZUR!!YCQyh6 z%VE?T=V7c;E)rlMff98bY!EEiZD{6m(a>fvU3vR6O3CcXLy5l(_sVuQqPL3tkYrtp^jU7ceX%`S3*VpiacfGh5uIkHJH&09j= z!Zw)X;o6oGJyg=T5=W9Y)b@91-QJ-stzGVD>Dyrv(F3{Jd<2@B`(WQL9m|2pe#=D< z$owP9q8a}gd89MC{Z@M@`o?b7tx)bK{cBG%U_4|0Q=6vzWO+{1Otmtd_ntOn3Q{tw z{ZQNwgqZWzX(H)dp4T3sMrO{pNsw%$sftop9aVPoY9GbRm$ zJzmt&y+kryr9u&c`bmYh!cH1T6vB!BmxtbuQ=ME4m-32mlXFnK?X`X!GKT7E%(y`V6se%liQBzmGVi5>+=s`~`60sNN zgVveDlqo->4I=(%u|&ta^pgsYB<6-tx}dgPjAgoWvJ3?PncO9xnZ9VR5%2wO{7`rI zB~BvDBbP3PmW>tJpGqf|_sX!VwJel)p04-s!8}8U6B>gOf`1;LmpKO}x^rYc1#P@} zW^L`3ad$j~2>i5D@s!-$M<;Ta-ZMaC$aTa9@XOkc*GT>KeaEGw8ED;W>cP`Y#pb%) zZE|qrSeYNLbc7aaWff#pR^#Qik0Y1BL;#SL{{Mro0|j2VvC@7#ePTw>c$rsyw&O+x_) zi0RW?y%vaxJ5@;*^hf^g=uT6;7_Fjx4N^G1zJd;CZj#Qggcs8ZDViDt674Hz;sRm0 z5)#Y;0376h;Ge!%tP+Y0#K?6(aIO-Nl1XQI2=`sJ36dhkSLEKUeY_GSeyvI4hBzn= zww143E(9SoCAJ_@exnYNjqUElBBl4Q#u|w7ShvMvK{8*7BnMptwjiF^n^LwQ%@o5g z+6{i6|2+fuNKr>$3EIWn)fd_zGFah#aXl#FlkwBGvE;#e=6;Y!&!isLMb~^{J#C$f z4V%!PdYeu=u5Z~P=!oeQzBL28g1`9mP?kBgx|)@RpFr`|WF;#r%X?>UubzP9_Ih$s zWt;fehi|#Is%WyMho;O+2+0BHhY(A*oNE?7F!_PcGTlGV#buImA>Py@SK@p4;NHkZ zpIj9KADVv5F2Li)pUOdYp2cS;LFA5mjHJCTxX(WOKy-&@R9Bc3Pbp+OaIoHTu~39E z%7ypTTh*4WNZVvCu{2g}gj&?+krV@i z%z(YnI1QTbejNDgSyF0Iu$a7|avfEQWyG%;pcfahpEyDf8u7Ik^`n^v)ilBQAo>cX z#FMJ;(&rsl&aI9$h9=dbkgKZ7*d7P^;1XF9UcOyd1KJvHLuf!BK>f{d4_63B%0tqG zfYLVUvlQADF<$c+h|1C=D7X`_KFfDSb|HIFNS)wFIl6u_s zO`1B8%jGR?hGSHI&ieb?L?}$hp=`Rx zXLf%nEII<*c8wZ^fh4n!QAdtZ{0=llj#o39;3-_A=8dJBY?+mj=0+DaYpOfVzfP_G~edfEd5QX z%Mv7NWhM>8!^wW@f#gTlxpLX>P8>0>gSCT259UR1QajS3vzWPx!KiZc<9&w=`i_D! z(W3<>cUNEEvozjA=g=W%wGraqs`wN6twG14Od83cMW{&cJ6ota4 z_05fE-QGRsJUtn>Y(b*QG^Y<3Kx{3T91-XpK9*UD{~9x2T@D^FXM#L5WYN z>g2HC<1#Qne|MP@tfA};e+ozv$KB@@6^$9S(4(8KB`Vp8Y9#dFvHVg0TokL6mWIAFD&$GUekF=b+sB3})IkS-lxbYZUPp81&z+lb|qa zDpWG??3z%bC^RkvFRAdo*}v)Xzf6VF1K1*hVfcUM78tc~$Wdf=0_>^q03A9#eSJSn zySy2wg`P4qGbOX|=UEtQ#OC@Ne=4%*%hdgcd!a?}SJpXOR4>AJKvV)a_d#m9C_S%8ZFpwGYb zpgc}#%{ZkLdC*}fF|l>Wl>Ubrs$9YRQS6zfQuEhz0c>pS3|$5&CcY_Z+@)qw&u}aH zu*~?umgofig;*L3(inF-oXpZ+S)UTyu;P+3k}rUh{K4#Wa5sc+QGT%-D{AmL$&})D z_}Bl9;a7=LR779phMz39^+7TDf4ds~&mD{Z<$%%}u>aCB=x#C?5Hzz6PlRq4_`. | +| `title` | string | yes | Human-readable title. Combined with `adr_number` to produce the H1 heading automatically — do **not** add an `# H1` line in the markdown body. | +| `status_history` | list | yes | Chronological list of status transitions. Each entry is a tuple of `[date, status]` or `[date, status, person(s)]`. See [Status Lifecycle](#status-lifecycle) for valid statuses. | +| `tier` | integer | yes | Architectural tier (1–4). See [Tier System](#tier-system). | +| `authors` | list of strings | no | Contributors who authored or substantially edited the ADR. | +| `superseded_by` | integer | no | ADR number of the decision that replaces this one. Only meaningful when the current status is `Superseded`. Renders as a link in the page header. | +| `related_adrs` | list of objects | no | Cross-references to other ADRs. Each entry has `number` (int), `title` (string), and `relationship` (string). The build system generates the Related ADRs table from this data. | +| `acceptance` | object | no | Governance voting record. Contains `votes_for`, `votes_against`, and `abstentions` — each a list of objects with `voter` (string) and `comment` (string). The build system generates the Acceptance section from this data. | -### Content Sections +Example front-matter: -#### Context +```yaml +--- +adr_number: 17 +title: "Automation Profiles" +status_history: + - ["2026-02-16", "Draft", "Jeffrey Phillips Freeman"] + - ["2026-02-16", "Proposed", "Jeffrey Phillips Freeman"] + - ["2026-02-16", "Accepted", "Jeffrey Phillips Freeman"] +tier: 3 +authors: ["Jeffrey Phillips Freeman"] +superseded_by: +related_adrs: + - number: 6 + title: "Plan Lifecycle" + relationship: "Profiles control which lifecycle phase transitions require human approval" + - number: 7 + title: "Decision Tree and Correction" + relationship: "Confidence thresholds determine which decisions require human intervention" +acceptance: + votes_for: + - voter: "Jeffrey Phillips Freeman " + comment: "Named profiles with confidence thresholds provide a clean spectrum from full manual to full autonomous control" + votes_against: [] + abstentions: [] +--- +``` + +The build system reads this front-matter to automatically generate: + +- The page **H1 title** (e.g., "ADR-017: Automation Profiles") +- A **subtitle header** showing tier, drafted date, current status with date, and authors +- A **status timeline** in the sidebar (desktop) or at the end of the article (mobile) +- The **Related ADRs** table with links, titles, and relationship descriptions +- The **Acceptance** section with voting tallies +- The **inventory tables** on this page + +## Status Lifecycle + +Each ADR progresses through a lifecycle tracked by the `status_history` front-matter field. The following diagram shows the valid state transitions: + +![ADR status workflow](img/adr-workflow.png) + +The following statuses are recognized: + +| Status | Meaning | What may change | +|--------|---------|-----------------| +| **Draft** | The ADR is being written. It captures initial thinking but has not yet been formally proposed for review. Draft ADRs may be incomplete or contain open questions. | Everything. All content sections, front-matter fields, and structural decisions are open for revision. The only field that must not change is `adr_number`. | +| **Proposed** | The ADR is content-complete and has been submitted for review and voting. Reviewers evaluate the decision, its rationale, and its design. Discussion may surface clarifications, but the substantive content should be stable. | Content is mostly frozen. Only metadata changes are expected: votes are recorded in `acceptance`, minor wording clarifications may be applied, and `status_history` is updated. A Proposed ADR must resolve to either **Accepted** or **Rejected** — it cannot move back to Draft or skip to any other status. | +| **Accepted** | The ADR has been reviewed, voted on, and approved. It represents a binding architectural commitment that the project will follow. Implementation should conform to what the ADR specifies. | The ADR is immutable in substance. Only `related_adrs` may be updated as new ADRs are added that reference this one. If the decision needs material change, a new ADR should supersede it rather than editing the accepted text. | +| **Rejected** | The ADR was proposed but not accepted after review. The reasoning is preserved for historical reference so the same ground is not relitigated without new information. | The ADR is immutable. It remains in the record as evidence that the option was considered and declined. | +| **Superseded** | A previously accepted ADR that has been replaced by a newer decision. The `superseded_by` field links to the replacing ADR. The original remains in the record for historical context. | Only the `superseded_by` field and `status_history` are updated when this transition occurs. | +| **Deprecated** | A previously accepted ADR that is no longer relevant — the feature, component, or concern it addressed has been removed or is no longer applicable. Unlike Superseded, there is no replacement decision. | Only `status_history` is updated when this transition occurs. | + +### Transition rules + +- **Draft → Proposed** is the only way out of Draft. The author(s) must ensure all content sections are complete before proposing. +- **Proposed → Accepted** or **Proposed → Rejected** are the only valid transitions from Proposed. Voting determines the outcome. +- **Accepted → Superseded** occurs when a new ADR explicitly replaces this one. +- **Accepted → Deprecated** occurs when the decision is no longer applicable and no replacement is needed. +- There is no path back from Accepted, Rejected, Superseded, or Deprecated to an earlier status. If a rejected idea is revisited, a new ADR should be created. + +The `status_history` field records every transition as a `[date, status]` or `[date, status, person]` tuple, forming a complete audit trail. The most recent entry determines the ADR's current status. + +## Tier System + +ADRs are organized into four tiers that reflect their architectural scope and the breadth of their impact on the system: + +| Tier | Name | Scope | +|------|------|-------| +| **1** | Foundational | Structural and technological foundation upon which all other decisions rest. Changes here cascade across the entire system. | +| **2** | Core Domain | Domain model — the entities, lifecycles, and relationships that constitute the system's core logic. | +| **3** | Infrastructure and Behavior | Cross-cutting behavioral systems and infrastructure concerns that support the domain model. | +| **4** | Integration and Operations | External integrations, operational interfaces, and deployment concerns at the system boundary. | + +Lower-numbered tiers are more foundational: a Tier 1 change is likely to affect decisions at every other tier, while a Tier 4 change is typically self-contained. + +## Content Sections + +After the front-matter, each ADR contains the following standard sections. Authors may add sub-sections within any section to further organize complex material (e.g., `### Sequence Diagrams` under Design, or `### Option A: Event Sourcing` under Alternatives Considered). The standard sections themselves should not be removed or reordered. + +### Context Describes the problem, situation, or forces that motivated the decision. This section explains *why* the ADR exists — what technical challenge, scaling concern, or design tension required an explicit architectural choice. It should give a reader who is unfamiliar with the project enough background to understand the decision without reading the full specification. -#### Decision +### Decision Drivers + +A short bulleted list of the key forces, requirements, and priorities that shaped the decision. Decision drivers are the specific, concrete factors that the decision must satisfy or balance — things like "must support offline operation," "latency under 100ms," or "must not break the existing REST API contract." Where Context tells the story, Decision Drivers distil it into a scannable checklist that reviewers can evaluate the decision against. This section corresponds to MADR's "Decision Drivers" and ensures the prioritized forces are explicit rather than buried in narrative. + +### Decision States the architectural choice that was made, written in declarative form (e.g., "CleverAgents adopts X"). This is the core commitment of the ADR — a concise, authoritative statement of what was decided. Implementation details belong in Design; this section focuses on the *what*, not the *how*. -#### Design +### Design Provides the structural details that realize the decision: components, interfaces, data models, patterns, protocols, and interaction flows. This is typically the longest section of an ADR and may include sub-headings, diagrams, and code-level specifics. The Design section should give an implementer enough information to build the feature correctly without inventing architectural choices on their own. -#### Constraints +### Constraints Lists the explicit rules and restrictions the decision imposes on the codebase. Constraints are enforceable invariants — statements like "module X must never import from module Y" or "all domain models must use Pydantic strict mode." They serve as guardrails that CI checks, linters, and code review can verify mechanically. -#### Consequences +### Consequences Documents the outcomes of the decision, organized into three categories: **Positive** (benefits gained), **Negative** (trade-offs accepted), and **Risks** (potential future problems). Honest accounting of trade-offs is essential — an ADR that lists only positive consequences is incomplete. This section helps future readers understand whether the decision's assumptions still hold. -#### Alternatives Considered +### Alternatives Considered -Describes other options that were evaluated and explains why they were not chosen. Each alternative should include enough detail for a reader to understand the rejected approach and the reasoning behind the rejection. When the decision is directly prescribed by the specification with no practical alternatives, this section may read "None — specification-driven requirement." +Describes other options that were evaluated and explains why they were not chosen. Each alternative should include enough detail for a reader to understand the rejected approach and the reasoning behind the rejection. Where practical, include a brief summary of the pros and cons for each option so that readers can understand the trade-off analysis that led to the final choice. When the decision is directly prescribed by the specification with no practical alternatives, this section may read "None — specification-driven requirement." -#### Compliance +### Compliance Specifies how adherence to the decision is verified in practice. This includes CI checks, linting rules, architecture tests, code review expectations, and any other enforcement mechanisms. A decision without a compliance strategy is aspirational rather than architectural — this section ensures every ADR is backed by concrete verification. -#### Related ADRs +### Related ADRs -A table of cross-references to other ADRs that interact with this decision. Each entry includes a link to the related ADR, its title, and a brief description of the relationship (e.g., "Provides the persistence layer used by this system" or "Defines the validation strategy referenced in the Constraints section"). Cross-references are maintained in both directions — when a new ADR references an existing one, the existing ADR's Related ADRs table is updated as well. This is always the second-to-last section. +A table of cross-references to other ADRs that interact with this decision. Each entry includes a link to the related ADR, its title, and a brief description of the relationship. Cross-references are maintained in both directions — when a new ADR references an existing one, the existing ADR's `related_adrs` front-matter is updated as well. This section is **generated automatically** from the `related_adrs` front-matter field — do not write it by hand in the markdown body. It is always the second-to-last section. -#### Acceptance +### Acceptance -Records the governance process for the ADR. Contains three sub-tables — **Votes For**, **Votes Against**, and **Abstentions** — each listing the voter's identity, an optional comment, and a total count. The Acceptance section is populated during the review process: votes are cast, recorded, and once the outcome is determined the ADR's status is updated to `Accepted` (or remains `Proposed` if rejected). This is always the last section of every ADR. +Records the governance process for the ADR. Contains three sub-tables — **Votes For**, **Votes Against**, and **Abstentions** — each listing the voter's identity, an optional comment, and a total count. This section is **generated automatically** from the `acceptance` front-matter field — do not write it by hand in the markdown body. It is always the last section of every ADR. ## ADR Inventory -### Tier 1 — Foundational + -These ADRs establish the structural and technological foundation upon which all other decisions rest. +## ADR Timeline -| ADR | Title | Summary | -|-----|-------|---------| -| [ADR-001](ADR-001-layered-architecture.md) | Layered Architecture | Four-layer architecture with hexagonal ports/adapters, CQRS, and event-driven patterns. | -| [ADR-002](ADR-002-namespace-system.md) | Namespace System | Universal `[[server:]namespace/]name` naming for all entities. | -| [ADR-003](ADR-003-dependency-injection.md) | Dependency Injection | `dependency-injector` DeclarativeContainer for all service wiring. | -| [ADR-004](ADR-004-data-validation.md) | Data Validation | Pydantic V2 strict mode for all domain models and configuration objects. | -| [ADR-005](ADR-005-technical-stack.md) | Technical Stack | Python 3.13, Typer, LangChain/LangGraph, SQLAlchemy, and supporting libraries. | +A unified chronological view of every status transition across all architecture decisions. -### Tier 2 — Core Domain - -These ADRs define the domain model — the entities, lifecycles, and relationships that constitute the system's core logic. - -| ADR | Title | Summary | -|-----|-------|---------| -| [ADR-006](ADR-006-plan-lifecycle.md) | Plan Lifecycle | Action, Strategize, Execute, Apply phases with states and reversion rules. | -| [ADR-007](ADR-007-decision-tree-and-correction.md) | Decision Tree and Correction | Eleven decision types, persistent decision graph, unified correction mechanism. | -| [ADR-008](ADR-008-resource-system.md) | Resource System | Typed resources with DAG relationships, registry, and sandbox strategies. | -| [ADR-009](ADR-009-project-model.md) | Project Model | Named scope linking resources, context configuration, and invariants. | -| [ADR-010](ADR-010-actor-and-agent-architecture.md) | Actor and Agent Architecture | Actor-as-graph via LangGraph, hierarchical composition, role-based specialization. | -| [ADR-011](ADR-011-tool-system.md) | Tool System | Four-stage lifecycle, dual role, adapter layer, resource bindings. | -| [ADR-012](ADR-012-skill-system.md) | Skill System | Composable tool collections with hierarchical inclusion and flattening. | -| [ADR-013](ADR-013-validation-abstraction.md) | Validation Abstraction | Tool subtype with structured pass/fail, attachment scoping, and gating semantics. | -| [ADR-033](ADR-033-decision-recording-protocol.md) | Decision Recording Protocol | Tool-based `record_decision` mechanism, system vs. actor creation classification, context snapshot capture. | -| [ADR-034](ADR-034-decision-tree-versioning-and-history.md) | Decision Tree Versioning and History | Dual structure (structural tree + influence DAG), implicit versioning via `superseded_by`, historical reconstruction. | -| [ADR-035](ADR-035-decision-tree-rollback-and-replay.md) | Decision Tree Rollback and Replay | Mid-Strategize replay, Execute-phase decision-aligned checkpoints, three rollback tiers, cross-plan cascading. | - -### Tier 3 — Infrastructure and Behavior - -These ADRs govern cross-cutting behavioral systems and infrastructure concerns. - -| ADR | Title | Summary | -|-----|-------|---------| -| [ADR-014](ADR-014-context-management-acms.md) | Context Management (ACMS) | Unified Knowledge Ontology, Context Retrieval Pipeline, 10-component assembly pipeline. | -| [ADR-015](ADR-015-sandbox-and-checkpoint.md) | Sandbox and Checkpoint | Five isolation strategies, lazy sandboxing, checkpoint/restore per tool. | -| [ADR-016](ADR-016-invariant-system.md) | Invariant System | Four scopes with precedence, reconciliation actor, and child plan inheritance. | -| [ADR-017](ADR-017-automation-profiles.md) | Automation Profiles | Confidence thresholds controlling autonomy across eight built-in profiles. Composes a SafetyProfile sub-model (ADR-041). | -| [ADR-018](ADR-018-semantic-error-prevention.md) | Semantic Error Prevention | Four prevention layers from decision-time validation to predictive guards. | -| [ADR-041](ADR-041-safety-profile-extraction.md) | Safety Profile Extraction | Safety constraints extracted into a composed SafetyProfile sub-model within AutomationProfile. | -| [ADR-019](ADR-019-storage-and-persistence.md) | Storage and Persistence | SQLite/SQLAlchemy with repository pattern, Unit of Work, and Alembic migrations. | -| [ADR-020](ADR-020-session-model.md) | Session Model | Conversation threads with orchestrator binding and session-scoped context. | -| [ADR-036](ADR-036-resource-dag-operational-semantics.md) | Resource DAG Operational Semantics | Ten operational purposes of the resource DAG with sandbox boundary algebra, checkpoint boundaries, and dependency ordering. | -| [ADR-037](ADR-037-tool-reachability-and-access-projection.md) | Tool Reachability and Access Projection | Forward, inverse, and cross-equivalence reachability with AccessProjection protocol and read/write routing. | -| [ADR-038](ADR-038-cross-mechanism-sandbox-coordination.md) | Cross-Mechanism Sandbox Coordination | Coherence properties, write-then-sync protocol, conflict resolution, and lazy virtual node materialization. | -| [ADR-042](ADR-042-resource-type-inheritance.md) | Resource Type Inheritance | Single-inheritance `inherits` field on resource type definitions with polymorphic tool binding, auto-discovery, and DAG queries. | - -### Tier 4 — Integration and Operations - -These ADRs address external integrations, operational interfaces, and deployment concerns. - -| ADR | Title | Summary | -|-----|-------|---------| -| [ADR-021](ADR-021-cli-and-output-rendering.md) | CLI and Output Rendering | Typer-based `agents ` pattern with six output formats. | -| [ADR-022](ADR-022-langchain-langgraph-integration.md) | LangChain/LangGraph Integration | Provider-agnostic LLM abstraction with StateGraph orchestration. | -| [ADR-023](ADR-023-server-mode.md) | Server Mode | Client/server deployment with shared namespaces and remote execution. | -| [ADR-024](ADR-024-configuration-system.md) | Configuration System | TOML global config with dot-path keys, YAML entity config, resolution chain. | -| [ADR-025](ADR-025-observability-and-logging.md) | Observability and Logging | structlog JSON output with context binding, optional LangSmith tracing. | -| [ADR-026](ADR-026-agent-client-protocol.md) | Agent Client Protocol (ACP) | Versioned client-server contract for sessions, plans, registries, and event streaming. | -| [ADR-027](ADR-027-language-server-protocol.md) | Language Server Protocol (LSP) Integration | Actor-attached language intelligence via LSP servers registered in the LSP Registry. | -| [ADR-028](ADR-028-agent-skills-standard.md) | Agent Skills Standard (AgentSkills.io) | SKILL.md-based progressive disclosure skills integrated as tool sources and actor graph nodes. | -| [ADR-029](ADR-029-model-context-protocol.md) | Model Context Protocol (MCP) Adoption | MCP tool discovery, registry integration, skill composition, and actor-graph usage. | -| [ADR-030](ADR-030-skill-abstraction-definition.md) | Skill Abstraction Definition | Canonical definition of a skill as a composable collection of tools from four sources (MCP, Agent Skills, built-in, custom). | -| [ADR-031](ADR-031-actor-abstraction-definition.md) | Actor Abstraction Definition | Canonical definition of an actor as anything conversational — single LLM, composed graph, or hierarchical orchestrator. | -| [ADR-032](ADR-032-jinja2-yaml-template-preprocessing.md) | Jinja2 YAML Template Preprocessing | Two-phase YAML processing: sandboxed Jinja2 template rendering followed by environment variable interpolation with type coercion. | -| [ADR-039](ADR-039-container-resource-types.md) | Container and Execution Environment Resource Types | Seven engine-agnostic container resource types plus executable discovery for tool/LSP dependency resolution. | -| [ADR-040](ADR-040-lsp-resource-types.md) | LSP Resource Types | Three LSP resource types (lsp-server, lsp-workspace, lsp-document) for language intelligence integration. | -| [ADR-043](ADR-043-devcontainer-integration.md) | Devcontainer Integration and Container-Project Association | Auto-detected devcontainer-instance subtype, container-project association patterns, and execution environment routing with precedence. | + ## Creating a New ADR 1. Assign the next sequential number (e.g., `ADR-044`). 2. Create a file named `ADR-0NN-.md` in this directory. -3. Copy the template structure from any existing ADR. -4. Fill in the metadata table with `Status: Proposed`, the current date, author(s), and leave approver(s) blank. -5. Add the Related ADRs table with links, titles, and relationship descriptions. -6. Leave the Acceptance section with empty voting tables — votes are recorded during the review process. -7. Fill in all content sections (Context through Compliance). Every section is required — use "N/A" only if genuinely not applicable. -8. Add the new ADR to the inventory table above and to the `nav` section in `mkdocs.yml`. -9. Cross-reference related ADRs in both directions (update existing ADRs' Related ADRs tables). -10. Once voting concludes and the ADR is accepted, update `Status` to `Accepted`, record all votes, and add the approver(s). +3. Copy the front-matter and section structure from any existing ADR. +4. Set the front-matter fields: + - `adr_number`: the assigned number (integer) + - `title`: a concise descriptive title + - `status_history`: initialize with a single `["YYYY-MM-DD", "Draft", "Your Name"]` entry + - `tier`: the appropriate tier (1–4) + - `authors`: list of author names + - `superseded_by`: leave empty (or omit) + - `related_adrs`: list of related ADR entries (each with `number`, `title`, `relationship`) + - `acceptance`: initialize with empty `votes_for: []`, `votes_against: []`, `abstentions: []` +5. Do **not** add an `# H1` heading in the markdown body — the build system generates it from `adr_number` and `title`. +6. Do **not** write `## Related ADRs` or `## Acceptance` sections in the markdown body — both are generated from front-matter. +7. Fill in all content sections (Context, Decision Drivers, Decision, Design, Constraints, Consequences, Alternatives Considered, Compliance). Every section is required — use "N/A" only if genuinely not applicable. +8. Add the new ADR to the `nav` section in `mkdocs.yml`. The inventory table on this page is generated automatically. +9. Cross-reference related ADRs in both directions (update existing ADRs' `related_adrs` front-matter). +10. Once voting concludes and the ADR is accepted, add a new `["YYYY-MM-DD", "Accepted", "Approver Name"]` entry to `status_history` and record votes in the `acceptance` front-matter field. diff --git a/docs/javascripts/adr-page.js b/docs/javascripts/adr-page.js new file mode 100644 index 000000000..3dbf72620 --- /dev/null +++ b/docs/javascripts/adr-page.js @@ -0,0 +1,84 @@ +/** + * ADR Page — timeline placement + * + * On ADR pages the build hook embeds a hidden `.adr-timeline` element in the + * page content. + * + * Desktop (>= 76.25em) — move the timeline into the left sidebar, replacing + * the integrated Table of Contents. + * Mobile (< 76.25em) — leave the navigation drawer alone; instead show + * the timeline at the end of the article body. + * + * Compatible with Material for MkDocs instant-loading (SPA navigation). + */ + +var _adrDesktopQuery = window.matchMedia("(min-width: 76.25em)"); + +document$.subscribe(function () { + var timeline = document.querySelector(".md-content .adr-timeline"); + + if (!timeline) { + // Not an ADR page — clean up any leftover state from a previous page. + document.body.classList.remove("adr-page"); + return; + } + + document.body.classList.add("adr-page"); + + if (_adrDesktopQuery.matches) { + _placeInSidebar(timeline); + } else { + _placeInContent(timeline); + } +}); + +/* ── Desktop: replace the sidebar TOC with the timeline ──────────────── */ + +function _placeInSidebar(timeline) { + var sidebarInner = document.querySelector( + ".md-sidebar--primary .md-sidebar__inner" + ); + if (!sidebarInner) return; + + var nav = document.createElement("nav"); + nav.className = "md-nav md-nav--primary adr-sidebar-timeline"; + nav.setAttribute("data-md-level", "0"); + + var title = document.createElement("label"); + title.className = "md-nav__title adr-timeline-title"; + title.textContent = "Status History"; + + var clone = timeline.cloneNode(true); + clone.style.display = ""; + + nav.appendChild(title); + nav.appendChild(clone); + + sidebarInner.innerHTML = ""; + sidebarInner.appendChild(nav); + + // Remove the hidden source element from the content area. + timeline.parentNode.removeChild(timeline); +} + +/* ── Mobile: append the timeline at the end of the article ───────────── */ + +function _placeInContent(timeline) { + var article = document.querySelector(".md-content__inner"); + if (!article) return; + + // Build a wrapper with a heading so it reads as a distinct section. + var wrapper = document.createElement("div"); + wrapper.className = "adr-timeline-mobile"; + + var heading = document.createElement("h2"); + heading.textContent = "Status History"; + heading.id = "status-history"; + wrapper.appendChild(heading); + + // Move (not clone) the timeline into the wrapper and make it visible. + timeline.style.display = ""; + wrapper.appendChild(timeline); + + article.appendChild(wrapper); +} diff --git a/docs/stylesheets/extra.css b/docs/stylesheets/extra.css index 154e900ea..93d924677 100644 --- a/docs/stylesheets/extra.css +++ b/docs/stylesheets/extra.css @@ -1,3 +1,48 @@ +/* --- Wider layout: expand page grid + sidebars ------------------------- + * + * Material defaults: .md-grid max-width 61rem, sidebar 12.1rem. + * We widen the grid to 80rem and bump sidebars to ~18rem (~50% wider) + * so the content area has more breathing room on large monitors. + * ----------------------------------------------------------------------- */ + +@media screen and (min-width: 76.25em) { + .md-grid { + max-width: 80rem; + } + + .md-sidebar { + width: 18.1rem; + } + + /* Primary sidebar: match the new width everywhere Material hard-codes + the old 12.1rem value (transforms, offsets, left/right). */ + .md-sidebar--primary { + width: 18.1rem; + } + + /* Material sets padding-right: calc(100% - 11.5rem) on the sidebar + inner wrapper (in @supports ::-webkit-scrollbar) to reserve space + for the scrollbar gutter. 11.5rem = old 12.1rem sidebar − 0.6rem. + Update to 17.5rem = 18.1rem − 0.6rem so content fills the wider + sidebar instead of being squeezed to the old width. */ + .md-sidebar__inner { + padding-right: calc(100% - 17.5rem) !important; + } + + [dir=rtl] .md-sidebar__inner { + padding-left: calc(100% - 17.5rem) !important; + padding-right: 0 !important; + } +} + +/* On slightly smaller desktops (60-76em), use a moderate widening so the + layout doesn't jump straight from 61rem to cramped sidebars. */ +@media screen and (min-width: 60em) and (max-width: 76.1875em) { + .md-grid { + max-width: 72rem; + } +} + .md-typeset .highlight, .md-typeset .highlight pre, .md-typeset .highlight code { @@ -537,3 +582,321 @@ img[alt="Kroki"]:hover { -webkit-mask-image: var(--md-admonition-icon--adr); mask-image: var(--md-admonition-icon--adr); } + +/* ── ADR Page: Custom Header (subtitle style) ────────────────────── */ + +.adr-header { + margin: -0.4rem 0 1.2rem; + font-size: 0.82rem; + font-style: italic; + color: var(--md-default-fg-color--light); + line-height: 1.7; +} + +.adr-header-line { + display: flex; + flex-wrap: wrap; + align-items: baseline; + gap: 0.2rem 0.5rem; +} + +.adr-header-line .adr-label { + color: var(--md-default-fg-color--light); +} + +.adr-header-line .adr-value { + color: var(--md-default-fg-color); +} + +.adr-header-line a { + color: var(--md-typeset-a-color); +} + +.adr-header-line a:hover { + color: var(--md-accent-fg-color); +} + +/* ── ADR SVG Icon (inline, matching log4brains Material icons) ───── */ + +.adr-icon { + display: inline-block; + width: 1em; + height: 1em; + vertical-align: -0.125em; + fill: currentColor; + flex-shrink: 0; +} + +/* ── ADR Status Badge (log4brains MuiChip-outlined style) ────────── */ + +.adr-status-badge { + display: inline-block; + height: 18px; + line-height: 16px; + font-size: 0.74rem; + font-weight: 500; + font-style: normal; /* override when inside the italic header */ + padding: 0 6px; + border: 1px solid currentColor; + border-radius: 9px; + white-space: nowrap; + vertical-align: text-bottom; +} + +/* Status colours (matching log4brains palette) */ +.adr-status-draft { color: #424242; } +.adr-status-proposed { color: #283593; } +.adr-status-accepted { color: #558b2f; } +.adr-status-rejected { color: #d84315; } +.adr-status-deprecated{ color: #6d4c41; } +.adr-status-superseded{ color: #6d4c41; } + +/* Superseded / Deprecated title gets strike-through */ +body.adr-page .md-content h1 { + /* default – no strike-through */ +} +body.adr-page.adr-superseded .md-content h1, +body.adr-page.adr-deprecated .md-content h1 { + text-decoration: line-through; + text-decoration-color: #6d4c41; +} + +/* Dark-mode adjustments */ +[data-md-color-scheme="slate"] .adr-status-draft { color: #bdbdbd; } +[data-md-color-scheme="slate"] .adr-status-proposed { color: #7986cb; } +[data-md-color-scheme="slate"] .adr-status-accepted { color: #81c784; } +[data-md-color-scheme="slate"] .adr-status-rejected { color: #e57373; } +[data-md-color-scheme="slate"] .adr-status-deprecated{ color: #a1887f; } +[data-md-color-scheme="slate"] .adr-status-superseded{ color: #a1887f; } + +/* ── Tier badge ──────────────────────────────────────────────────── */ + +.adr-tier-badge { + display: inline-block; + height: 18px; + line-height: 16px; + font-size: 0.74rem; + font-weight: 500; + font-style: normal; /* override when inside the italic header */ + padding: 0 6px; + border: 1px solid var(--md-default-fg-color--lighter); + border-radius: 9px; + color: var(--md-default-fg-color--light); + white-space: nowrap; +} + +.adr-tier-title { + font-size: 0.8rem; + color: var(--md-default-fg-color--light); +} + +/* ── ADR Timeline (in-page, moved to sidebar by JS) ─────────────── */ + +.adr-timeline { + display: flex; + flex-direction: column; +} + +.adr-timeline-entry { + display: flex; + align-items: flex-start; + min-height: 48px; +} + +/* Left column: date */ +.adr-timeline-date-col { + flex: 0 0 10ch; + text-align: right; + padding-right: 10px; + padding-top: 2px; +} + +.adr-timeline-date { + font-size: 0.72rem; + color: #9e9e9e; + white-space: nowrap; +} + +[data-md-color-scheme="slate"] .adr-timeline-date { + color: #757575; +} + +/* Centre column: dot + vertical connector */ +.adr-timeline-connector { + flex: 0 0 20px; + display: flex; + flex-direction: column; + align-items: center; + align-self: stretch; /* span the full row height so the line fills the gap */ +} + +.adr-timeline-dot { + width: 12px; + height: 12px; + border-radius: 50%; + flex-shrink: 0; + margin-top: 3px; + border: 2px solid currentColor; + background: var(--md-default-bg-color, #fff); + box-sizing: border-box; +} + +/* Dot colours re-use status palette */ +.adr-dot-draft { color: #424242; border-color: #424242; } +.adr-dot-proposed { color: #283593; border-color: #283593; } +.adr-dot-accepted { color: #558b2f; border-color: #558b2f; } +.adr-dot-rejected { color: #d84315; border-color: #d84315; } +.adr-dot-deprecated { color: #6d4c41; border-color: #6d4c41; } +.adr-dot-superseded { color: #6d4c41; border-color: #6d4c41; } + +/* Current (last) entry: filled dot, slightly larger */ +.adr-dot-current { + width: 14px; + height: 14px; + margin-top: 2px; + background: currentColor; +} + +/* Dark-mode dot colours */ +[data-md-color-scheme="slate"] .adr-dot-draft { color: #bdbdbd; border-color: #bdbdbd; } +[data-md-color-scheme="slate"] .adr-dot-proposed { color: #7986cb; border-color: #7986cb; } +[data-md-color-scheme="slate"] .adr-dot-accepted { color: #81c784; border-color: #81c784; } +[data-md-color-scheme="slate"] .adr-dot-rejected { color: #e57373; border-color: #e57373; } +[data-md-color-scheme="slate"] .adr-dot-deprecated { color: #a1887f; border-color: #a1887f; } +[data-md-color-scheme="slate"] .adr-dot-superseded { color: #a1887f; border-color: #a1887f; } + +/* Connector line between dots */ +.adr-timeline-line { + width: 2px; + flex-grow: 1; + min-height: 16px; + background: #e0e0e0; +} + +[data-md-color-scheme="slate"] .adr-timeline-line { + background: #424242; +} + +/* Right column: status + person */ +.adr-timeline-content { + flex: 1 1 auto; + padding-left: 10px; + padding-bottom: 12px; +} + +.adr-timeline-content .adr-status-badge { + display: inline-block; + vertical-align: middle; +} + +.adr-timeline-person { + display: flex; + align-items: center; + gap: 0.3rem; + font-size: 0.72rem; + color: #616161; + margin-top: 3px; +} + +[data-md-color-scheme="slate"] .adr-timeline-person { + color: #9e9e9e; +} + +.adr-timeline-person .adr-icon { + font-size: 0.85em; +} + +/* ── Sidebar timeline wrapper (set by adr-page.js) ──────────────── */ + +.adr-sidebar-timeline { + padding: 0.6rem 0.6rem 1rem; +} + +.adr-timeline-title { + display: block; + font-size: 0.7rem; + font-weight: 700; + text-transform: uppercase; + letter-spacing: 0.05em; + color: var(--md-default-fg-color--light); + padding-bottom: 0.5rem; + margin-bottom: 0.25rem; + border-bottom: 1px solid var(--md-default-fg-color--lightest); +} + +/* When in the sidebar, tighten the timeline dimensions */ +.adr-sidebar-timeline .adr-timeline-date-col { + flex: 0 0 8ch; + padding-right: 6px; +} + +.adr-sidebar-timeline .adr-timeline-entry { + min-height: 40px; +} + +.adr-sidebar-timeline .adr-timeline-content { + padding-left: 8px; + padding-bottom: 10px; +} + +/* ── ADR page: hide the integrated TOC in the left sidebar ───────── */ +/* Desktop only — the JS replaces the sidebar, but in case it hasn't + run yet or on print, also hide the secondary nav (TOC items). */ + +@media screen and (min-width: 76.25em) { + body.adr-page .md-sidebar--primary .md-nav--secondary { + display: none; + } + + /* Ensure the JS-injected timeline overrides the nav-hiding CSS. */ + body.adr-page .md-sidebar--primary .adr-sidebar-timeline { + display: block !important; + } +} + +/* ── ADR page: mobile timeline (appended at end of article by JS) ── */ + +.adr-timeline-mobile { + margin-top: 2.5rem; + padding-top: 1.5rem; + border-top: 1px solid var(--md-default-fg-color--lightest); +} + +/* ── Combined ADR timeline (index page, always visible in body) ──── */ + +.adr-combined-timeline { + display: flex !important; /* override the display:none on .adr-timeline */ + flex-direction: column; + margin-top: 1rem; + margin-bottom: 1.5rem; +} + +/* ADR link row (replaces the person row on individual timelines) */ +.adr-timeline-adr-link { + display: flex; + align-items: center; + gap: 0.3rem; + font-size: 0.72rem; + color: #616161; + margin-top: 3px; +} + +[data-md-color-scheme="slate"] .adr-timeline-adr-link { + color: #9e9e9e; +} + +.adr-timeline-adr-link .adr-icon { + width: 0.85em; + height: 0.85em; + flex-shrink: 0; + fill: currentColor; +} + +.adr-timeline-adr-link a { + color: var(--md-typeset-a-color); + text-decoration: none; +} + +.adr-timeline-adr-link a:hover { + text-decoration: underline; +} diff --git a/hooks/adr_hooks.py b/hooks/adr_hooks.py new file mode 100644 index 000000000..efaa40b1a --- /dev/null +++ b/hooks/adr_hooks.py @@ -0,0 +1,724 @@ +"""MkDocs hook for ADR page custom rendering. + +Injects a custom header (dates, status badge, tier) and a hidden timeline +element into every ADR page. The companion ``adr-page.js`` script moves +the timeline into the left sidebar at runtime. + +Also auto-generates the ADR inventory tables on the ``adr/index.md`` page +by scanning all ADR source files for their YAML front-matter. +""" + +from __future__ import annotations + +import logging +import re +from datetime import date, datetime +from pathlib import Path +from typing import Any + +import yaml + +log = logging.getLogger("mkdocs.hooks.adr") + +# ── status definitions ────────────────────────────────────────────────── + +VALID_STATUSES = { + "draft", + "proposed", + "accepted", + "rejected", + "superseded", + "deprecated", +} + +STATUS_LABELS = { + "draft": "Draft", + "proposed": "Proposed", + "accepted": "Accepted", + "rejected": "Rejected", + "superseded": "Superseded", + "deprecated": "Deprecated", +} + +# ── SVG icons (Material Design, same as log4brains) ──────────────────── + +ICON_CALENDAR = ( + '' +) + +ICON_PERSON = ( + '' +) + +# ── regex to match the old inline metadata block ──────────────────────── + +# Matches lines like: **Status:** Accepted \n**Date:** ... up to the +# blank line before ## Context (or the next heading). +_OLD_META_RE = re.compile( + r"^(\*\*Status:\*\*.*?\n)" # first metadata line + r"((?:\*\*[A-Za-z()]+:\*\*.*?\n)*)" # subsequent metadata lines + r"\s*\n", # trailing blank line + re.MULTILINE, +) + + +# ── helpers ───────────────────────────────────────────────────────────── + + +def _normalise_date(raw: Any) -> str: + """Return a YYYY-MM-DD string from various input types.""" + if isinstance(raw, date): + return raw.isoformat() + if isinstance(raw, datetime): + return raw.date().isoformat() + return str(raw).strip() + + +def _format_date_display(iso: str) -> str: + """Convert '2026-02-16' to 'Feb 16, 2026'.""" + try: + d = datetime.strptime(iso, "%Y-%m-%d") + return d.strftime("%b %d, %Y") + except (ValueError, TypeError): + return iso + + +def _normalise_people(raw: Any) -> str: + """Return a comma-separated string of people from various input.""" + if raw is None: + return "" + if isinstance(raw, list): + return ", ".join(str(p) for p in raw) + return str(raw).strip() + + +def _status_key(status: str) -> str: + """Lowercase status key for CSS class names.""" + return status.strip().lower() + + +def _is_adr_page(page: Any) -> bool: + """Return True if the page is an individual ADR (not the index).""" + src = page.file.src_path # e.g. "adr/ADR-001-layered-architecture.md" + return src.startswith("adr/ADR-") and src.endswith(".md") and "index" not in src + + +def _is_adr_index(page: Any) -> bool: + """Return True if the page is the ADR index page.""" + return page.file.src_path == "adr/index.md" + + +def _extract_adr_number(page: Any) -> str | None: + """Extract '001' from 'adr/ADR-001-layered-architecture.md'.""" + m = re.search(r"ADR-(\d+)", page.file.src_path) + return m.group(1) if m else None + + +# ── HTML builders ─────────────────────────────────────────────────────── + + +def _build_status_badge(status: str, extra_class: str = "") -> str: + key = _status_key(status) + label = STATUS_LABELS.get(key, status) + cls = f"adr-status-badge adr-status-{key}" + if extra_class: + cls += f" {extra_class}" + return f'{label}' + + +def _resolve_adr_link(adr_number: int, files: Any) -> str | None: + """Find the relative URL for an ADR by its number, using the MkDocs files collection.""" + prefix = f"adr/ADR-{adr_number:03d}" + for f in files: + if f.src_path.startswith(prefix) and f.src_path.endswith(".md"): + return f.src_path.replace("adr/", "", 1) # relative to current adr/ dir + return None + + +def _build_header( + earliest_date: str, + last_date: str, + last_status: str, + tier: int | None, + tier_title: str, + superseded_by: int | None, + authors: str, + files: Any, +) -> str: + """Build the subtitle-style header injected after the H1 title. + + Line 1: Tier + Drafted date (earliest entry in status_history) + Line 2: Current status badge + date (+ superseded-by link when applicable) + Line 3: Authors (optional, from explicit front-matter field) + """ + earliest_display = _format_date_display(earliest_date) + last_display = _format_date_display(last_date) + badge = _build_status_badge(last_status) + status_key = _status_key(last_status) + + # ── line 1: tier + drafted date ───────────────────────────────── + tier_part = "" + if tier is not None and tier_title: + tier_part = ( + f'Tier {tier}' + f'{tier_title}' + f' · ' + ) + + line1 = ( + f'
' + f"{tier_part}" + f'Drafted: ' + f'{earliest_display}' + f"
" + ) + + # ── line 2: current status + date (+ superseded-by link) ──────── + superseded_part = "" + if superseded_by is not None and status_key == "superseded": + link = _resolve_adr_link(superseded_by, files) + if link: + superseded_part = ( + f' ' + f'superseded by ' + f'ADR-{superseded_by:03d}' + ) + else: + superseded_part = f' — superseded by ADR-{superseded_by:03d}' + + line2 = ( + f'
' + f'Status: ' + f"{badge}" + f' as of ' + f'{last_display}' + f"{superseded_part}" + f"
" + ) + + # ── line 3: authors (optional) ────────────────────────────────── + line3 = "" + if authors: + line3 = ( + f'
' + f'Authors: ' + f'{authors}' + f"
" + ) + + return ( + f'\n
\n' + f" {line1}\n" + f" {line2}\n" + f" {line3}\n" + f"
\n\n" + ) + + +def _build_timeline(status_history: list) -> str: + """Build the hidden timeline HTML that JS moves into the sidebar.""" + entries_html = [] + total = len(status_history) + + for i, entry in enumerate(status_history): + entry_date = _normalise_date(entry[0]) + entry_status = str(entry[1]).strip() + entry_people = _normalise_people(entry[2] if len(entry) > 2 else None) + status_key = _status_key(entry_status) + date_display = _format_date_display(entry_date) + is_last = i == total - 1 + + dot_cls = f"adr-timeline-dot adr-dot-{status_key}" + if is_last: + dot_cls += " adr-dot-current" + + people_html = "" + if entry_people: + people_html = ( + f'
{ICON_PERSON}{entry_people}
' + ) + + connector_line = '
' if not is_last else "" + + badge = _build_status_badge(entry_status) + + entries_html.append( + f'
\n' + f'
\n' + f' {date_display}\n' + f"
\n" + f'
\n' + f'
\n' + f" {connector_line}\n" + f"
\n" + f'
\n' + f" {badge}\n" + f" {people_html}\n" + f"
\n" + f"
" + ) + + inner = "\n".join(entries_html) + return ( + f'\n\n\n" + ) + + +# ── Generated tail sections (Related ADRs + Acceptance) ──────────────── + +# Regex to strip leftover ## Related ADRs / ## Acceptance from the body +# (defensive — the migration should have removed them already). +_RELATED_SECTION_RE = re.compile(r"\n## Related ADRs\s*\n.*", re.DOTALL) +_ACCEPTANCE_SECTION_RE = re.compile(r"\n## Acceptance\s*\n.*", re.DOTALL) + + +def _build_related_adrs_section( + related_adrs: list[dict], + files: Any, +) -> str: + """Generate the ``## Related ADRs`` markdown section from front-matter. + + Each entry in *related_adrs* has ``number``, ``title``, and + ``relationship``. The ADR link is resolved via the MkDocs *files* + collection so that MkDocs can validate and rewrite the URL. + """ + if not related_adrs: + return "" + + lines = [ + "## Related ADRs", + "", + "| ADR | Title | Relationship |", + "|-----|-------|-------------|", + ] + + for entry in related_adrs: + num = entry.get("number") + title = entry.get("title", "") + relationship = entry.get("relationship", "") + + if num is None: + continue + + # Resolve the file link via the files collection + link_path = _resolve_adr_link(int(num), files) + if link_path: + adr_col = f"[ADR-{int(num):03d}]({link_path})" + else: + adr_col = f"ADR-{int(num):03d}" + + lines.append(f"| {adr_col} | {title} | {relationship} |") + + return "\n".join(lines) + "\n" + + +def _build_acceptance_section(acceptance: dict) -> str: + """Generate the ``## Acceptance`` markdown section from front-matter. + + *acceptance* contains ``votes_for``, ``votes_against``, and + ``abstentions`` — each a list of ``{voter, comment}`` dicts. + """ + if not acceptance: + return "" + + def _votes_table(entries: list[dict]) -> str: + rows = [ + "| Voter | Comment |", + "|-------|---------|", + ] + for e in entries: + voter = e.get("voter", "") + comment = e.get("comment", "") + rows.append(f"| {voter} | {comment} |") + return "\n".join(rows) + + votes_for = acceptance.get("votes_for", []) + votes_against = acceptance.get("votes_against", []) + abstentions = acceptance.get("abstentions", []) + + parts = [ + "## Acceptance", + "", + "### Votes For", + "", + _votes_table(votes_for), + "", + f"**Total: {len(votes_for)}**", + "", + "### Votes Against", + "", + _votes_table(votes_against), + "", + f"**Total: {len(votes_against)}**", + "", + "### Abstentions", + "", + _votes_table(abstentions), + "", + f"**Total: {len(abstentions)}**", + ] + + return "\n".join(parts) + "\n" + + +# ── ADR inventory (for the index page) ───────────────────────────────── + +_INVENTORY_PLACEHOLDER = "" +_TIMELINE_PLACEHOLDER = "" + + +def _collect_adr_inventory(files: Any) -> list[dict]: + """Scan all ADR source files and collect front-matter metadata. + + Returns a list of dicts sorted by ``adr_number``, each containing + ``number``, ``title``, ``tier``, ``status``, ``status_badge`` (HTML), + ``filename``, and ``status_history`` (the raw list of transitions). + """ + adrs: list[dict] = [] + for f in files: + src = f.src_path + if not src.startswith("adr/ADR-") or not src.endswith(".md"): + continue + + try: + content = Path(f.abs_src_path).read_text(encoding="utf-8") + except OSError: + continue + + fm_match = re.match(r"^---\n(.*?)\n---", content, re.DOTALL) + if not fm_match: + continue + + try: + meta = yaml.safe_load(fm_match.group(1)) or {} + except yaml.YAMLError: + continue + + adr_number = meta.get("adr_number") + title = meta.get("title", "") + tier = meta.get("tier") + status_history = meta.get("status_history", []) + + if adr_number is None or not status_history: + continue + + last_status = str(status_history[-1][1]).strip() + + # Relative link from adr/index.md to adr/ADR-NNN-xxx.md + filename = src.replace("adr/", "", 1) + + adrs.append( + { + "number": int(adr_number), + "title": title, + "tier": tier, + "status": last_status, + "status_badge": _build_status_badge(last_status), + "filename": filename, + "status_history": status_history, + } + ) + + adrs.sort(key=lambda a: a["number"]) + return adrs + + +def _generate_inventory_markdown(adrs: list[dict], tiers_config: dict) -> str: + """Generate tier-grouped inventory tables as markdown. + + Each tier produces an ``### Tier N — Title`` sub-heading followed by + the tier description and a table of ADRs with their number (linked), + title, and current status rendered as a coloured badge. + """ + # Group by tier + grouped: dict[int | None, list[dict]] = {} + for adr in adrs: + t = adr.get("tier") + grouped.setdefault(t, []).append(adr) + + sections: list[str] = [] + + def _tier_table(tier_adrs: list[dict]) -> list[str]: + rows = [ + "| ADR | Title | Status |", + "|-----|-------|--------|", + ] + for adr in tier_adrs: + num_str = f"ADR-{adr['number']:03d}" + link = f"[{num_str}]({adr['filename']})" + rows.append(f"| {link} | {adr['title']} | {adr['status_badge']} |") + return rows + + # Emit tiers in numeric order + for tier_num in sorted(t for t in grouped if t is not None): + tier_info = tiers_config.get(tier_num, {}) + tier_title = ( + tier_info.get("title", f"Tier {tier_num}") + if isinstance(tier_info, dict) + else str(tier_info) + ) + tier_desc = ( + tier_info.get("description", "") if isinstance(tier_info, dict) else "" + ) + + lines: list[str] = [f"### Tier {tier_num} — {tier_title}", ""] + if tier_desc: + lines += [tier_desc, ""] + lines += _tier_table(grouped[tier_num]) + sections.append("\n".join(lines)) + + # Handle ADRs without a tier (should not happen, but be defensive) + if None in grouped: + lines = ["### Uncategorized", ""] + lines += _tier_table(grouped[None]) + sections.append("\n".join(lines)) + + return "\n\n".join(sections) + + +# ── SVG icon for ADR link in combined timeline ───────────────────────── + +ICON_ADR = ( + '' +) + + +def _md_to_url(filename: str) -> str: + """Convert ``ADR-001-layered-architecture.md`` to a directory URL. + + MkDocs builds each ``.md`` file into ``/index.html``, so + relative links in raw HTML must use ``/`` rather than the + source ``.md`` extension. + """ + if filename.endswith(".md"): + return filename[:-3] + "/" + return filename + + +def _build_combined_timeline(adrs: list[dict]) -> str: + """Build a unified timeline of every status transition across all ADRs. + + Entries are sorted chronologically (then by ADR number for ties). + Instead of the person column used on individual pages, each entry + shows a clickable link to the originating ADR. + """ + # Flatten every status_history entry with its owning ADR metadata. + flat: list[dict] = [] + for adr in adrs: + num = adr["number"] + title = adr["title"] + url = _md_to_url(adr["filename"]) + label = f"ADR-{num:03d}: {title}" + for entry in adr.get("status_history", []): + entry_date = _normalise_date(entry[0]) + entry_status = str(entry[1]).strip() + flat.append( + { + "date_iso": entry_date, + "status": entry_status, + "adr_number": num, + "adr_label": label, + "adr_url": url, + } + ) + + # Sort chronologically, then by ADR number for same-date entries. + flat.sort(key=lambda e: (e["date_iso"], e["adr_number"])) + + total = len(flat) + entries_html: list[str] = [] + + for i, item in enumerate(flat): + status_key = _status_key(item["status"]) + date_display = _format_date_display(item["date_iso"]) + is_last = i == total - 1 + + dot_cls = f"adr-timeline-dot adr-dot-{status_key}" + if is_last: + dot_cls += " adr-dot-current" + + badge = _build_status_badge(item["status"]) + + adr_link_html = ( + f'" + ) + + connector_line = '
' if not is_last else "" + + entries_html.append( + f'
\n' + f'
\n' + f' {date_display}\n' + f"
\n" + f'
\n' + f'
\n' + f" {connector_line}\n" + f"
\n" + f'
\n' + f" {badge}\n" + f" {adr_link_html}\n" + f"
\n" + f"
" + ) + + inner = "\n".join(entries_html) + return ( + f'\n
\n' + f"{inner}\n" + f"
\n\n" + ) + + +# ── MkDocs hook entry-point ──────────────────────────────────────────── + + +def on_page_markdown( + markdown: str, + page: Any, + config: Any, + files: Any, + **kwargs: Any, +) -> str: + """Transform ADR page markdown. + + - **Index page** (``adr/index.md``): replaces the ```` + placeholder with auto-generated tier-grouped tables. + - **Individual ADR pages**: strips old metadata, injects header + timeline. + """ + # ── ADR index: auto-generate inventory + combined timeline ───── + if _is_adr_index(page): + needs_inventory = _INVENTORY_PLACEHOLDER in markdown + needs_timeline = _TIMELINE_PLACEHOLDER in markdown + + if needs_inventory or needs_timeline: + tiers_config = config.get("extra", {}).get("adr_tiers", {}) + adrs = _collect_adr_inventory(files) + + if needs_inventory: + inventory = _generate_inventory_markdown(adrs, tiers_config) + markdown = markdown.replace(_INVENTORY_PLACEHOLDER, inventory) + + if needs_timeline: + timeline = _build_combined_timeline(adrs) + markdown = markdown.replace(_TIMELINE_PLACEHOLDER, timeline) + + return markdown + + if not _is_adr_page(page): + return markdown + + meta = page.meta or {} + status_history = meta.get("status_history") + + if not status_history or not isinstance(status_history, list): + log.warning( + "ADR %s has no valid status_history in front-matter", page.file.src_path + ) + return markdown + + # ── derive dates and status ───────────────────────────────────── + # Earliest date = first entry in the status history + earliest_date = _normalise_date(status_history[0][0]) + + last_entry = status_history[-1] + last_date = _normalise_date(last_entry[0]) + last_status = str(last_entry[1]).strip() + + # ── authors (explicit optional front-matter field) ────────────── + authors = _normalise_people(meta.get("authors")) + + # ── tier info ─────────────────────────────────────────────────── + tier = meta.get("tier") + tier_title = "" + if tier is not None: + tiers_config = config.get("extra", {}).get("adr_tiers", {}) + tier_info = tiers_config.get(tier, {}) + if isinstance(tier_info, dict): + tier_title = tier_info.get("title", "") + + # ── superseded_by ─────────────────────────────────────────────── + superseded_by = meta.get("superseded_by") + + # ── strip old inline metadata block ───────────────────────────── + markdown = _OLD_META_RE.sub("", markdown, count=1) + + # ── generate the H1 from adr_number + title front-matter ──────── + adr_number = meta.get("adr_number") + adr_title = meta.get("title") + + if adr_number is not None and adr_title: + # Remove any existing H1 line from the markdown body + markdown = re.sub(r"^#\s+.+?\n+", "", markdown, count=1) + generated_h1 = f"# ADR-{int(adr_number):03d}: {adr_title}\n" + else: + # Fallback: keep whatever H1 already exists + generated_h1 = "" + h1_match = re.match(r"(#\s+.+?\n)", markdown) + if h1_match: + generated_h1 = "" # leave it in the markdown + else: + generated_h1 = "" + + # ── build header + timeline ───────────────────────────────────── + header_html = _build_header( + earliest_date, + last_date, + last_status, + tier, + tier_title, + superseded_by, + authors, + files, + ) + timeline_html = _build_timeline(status_history) + + if adr_number is not None and adr_title: + # H1 was stripped; prepend generated H1 + header + timeline + markdown = generated_h1 + "\n" + header_html + timeline_html + markdown + else: + # Insert after the existing H1 line + h1_match = re.match(r"(#\s+.+?\n)", markdown) + if h1_match: + insert_pos = h1_match.end() + markdown = ( + markdown[:insert_pos] + + "\n" + + header_html + + timeline_html + + markdown[insert_pos:] + ) + else: + markdown = header_html + timeline_html + markdown + + # ── generate Related ADRs + Acceptance from front-matter ──────── + # Defensively strip any leftover hand-written sections first. + markdown = _RELATED_SECTION_RE.sub("", markdown) + markdown = _ACCEPTANCE_SECTION_RE.sub("", markdown) + markdown = markdown.rstrip() + "\n" + + related_adrs = meta.get("related_adrs", []) + acceptance = meta.get("acceptance", {}) + + tail_sections: list[str] = [] + + if related_adrs: + tail_sections.append(_build_related_adrs_section(related_adrs, files)) + if acceptance: + tail_sections.append(_build_acceptance_section(acceptance)) + + if tail_sections: + markdown += "\n" + "\n".join(tail_sections) + + return markdown diff --git a/mkdocs.yml b/mkdocs.yml index ac8b57781..c25eb4260 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -87,13 +87,32 @@ theme: icon: material/brightness-4 name: Switch to light mode +hooks: + - hooks/adr_hooks.py + extra_css: - stylesheets/extra.css extra_javascript: + - javascripts/adr-page.js - javascripts/toc-collapse.js - javascripts/diagram-lightbox.js +extra: + adr_tiers: + 1: + title: "Foundational" + description: "Structural and technological foundation upon which all other decisions rest." + 2: + title: "Core Domain" + description: "Domain model — entities, lifecycles, and relationships that constitute core logic." + 3: + title: "Infrastructure and Behavior" + description: "Cross-cutting behavioral systems and infrastructure concerns." + 4: + title: "Integration and Operations" + description: "External integrations, operational interfaces, and deployment concerns." + plugins: - search - gen-files: