Compare commits
8 Commits
d30369e30a
...
65e498fb36
| Author | SHA1 | Date | |
|---|---|---|---|
| 65e498fb36 | |||
| 07c4a70907 | |||
| 53dfd55916 | |||
| 15f4cce238 | |||
| 23345cc5fd | |||
| 260b9b27e9 | |||
| 4b4b1ff1f1 | |||
| eff77973a1 |
53
CLAUDE.md
53
CLAUDE.md
@@ -7,3 +7,56 @@
|
||||
@.claude/rules/stack-and-commands.md
|
||||
@.claude/rules/architecture.md
|
||||
@.claude/rules/repo-boundary.md
|
||||
|
||||
## Installed Agents
|
||||
|
||||
This project includes the following specialized agents:
|
||||
|
||||
### Testing
|
||||
|
||||
- **tdd-workflow**: Expert guidance for the TDD8 workflow methodology, specializing in the comprehensive ISSUE-TEST-RED-GREEN-REFACTOR-DOCUMENT-REFINE-PUBLISH cycle with sophisticated sidequest management and proper test organization.
|
||||
|
||||
Use these agents by referencing them in your Claude Code interactions.
|
||||
|
||||
### Documentation
|
||||
|
||||
- **claude-documentation**: Specialized assistant for Claude and Claude Code documentation, features, and best practices
|
||||
|
||||
### Meta
|
||||
|
||||
- **coach**: Coaching meta-agent that reads all agent memories in a project and synthesises cross-agent briefs and new-agent orientations
|
||||
|
||||
### Code Quality
|
||||
|
||||
- **code-refactoring**: Analyze code structure and quality, identify improvement opportunities, and provide actionable refactoring guidance. Use PROACTIVELY for code quality assessment and improvement.
|
||||
- **datamodel-optimization**: Specialized agent that systematically analyzes, optimizes, and enhances dataclasses, models, and data structures within a codebase. Provides comprehensive datamodel improvements including convenience methods, interface consistency, code reduction, and test alignment.
|
||||
- **optimization**: Meta-agent that analyzes and optimizes other Claude Code subagents based on their performance data, usage patterns, and effectiveness metrics. Use PROACTIVELY for agent ecosystem improvement.
|
||||
- **tooling-optimization**: Meta-agent that analyzes and optimizes repository tooling usage to improve development efficiency
|
||||
|
||||
### Project Management
|
||||
|
||||
- **keepaChangelog**: Specialized assistant for maintaining CHANGELOG.md files following Keep a Changelog format
|
||||
- **keepaContributingfile**: Specialized assistant for maintaining CONTRIBUTING.md files following Keep a Contributing-File V0.0.1 format within the Kaizen Agentic framework
|
||||
- **keepaTodofile**: Specialized assistant for maintaining TODO.md files following Keep a Todofile V0.0.1 format
|
||||
|
||||
### Development Process
|
||||
|
||||
- **priority-evaluation**: Specialized assistant to help evaluate and establish priorities for issues and tasks.
|
||||
- **releaseManager**: Manages software releases, version control, and publication workflows for Python packages
|
||||
- **requirements-engineering**: Specialized agent designed to prevent interface compatibility issues and mock object mismatches by ensuring solid foundation planning before implementation. Based on lessons learned from Issue
|
||||
- **scope-analyst**: Analyze a repository and produce/improve SCOPE.md for rapid orientation
|
||||
- **wisdom-encouragement**: Provides encouraging wisdom and guidance for complex implementation tasks and challenging technical work
|
||||
|
||||
### Infrastructure
|
||||
|
||||
- **setupRepository**: Specialized assistant for setting up new Python repositories following PythonVibes best practices
|
||||
- **sys-medic**: Linux/Kubernetes node health assessment agent — diagnoses process, memory, CPU, disk, network, and kubelet issues with safe, prioritized, evidence-driven guidance
|
||||
|
||||
### Testing
|
||||
|
||||
- **tdd-workflow**: Expert guidance for the TDD8 workflow methodology, specializing in the comprehensive ISSUE-TEST-RED-GREEN-REFACTOR-DOCUMENT-REFINE-PUBLISH cycle with sophisticated sidequest management and proper test organization.
|
||||
- **test-maintenance**: Specialized agent for analyzing and fixing failing tests in the project
|
||||
- **testing-efficiency**: Specialized agent designed to optimize TDD8 workflow test execution, resolve pytest reliability issues, and enhance overall testing efficiency for red-green iterations. Focuses on smart test selection, parallel execution, and agent integration patterns.
|
||||
|
||||
Use these agents by referencing them in your Claude Code interactions.
|
||||
|
||||
|
||||
@@ -71,6 +71,40 @@ For contributing new agents or improving existing ones:
|
||||
- Define explicit scope and authority boundaries
|
||||
- Follow existing agent patterns in `agents/` directory
|
||||
|
||||
#### YAML frontmatter schema
|
||||
|
||||
```yaml
|
||||
---
|
||||
name: <agent-name>
|
||||
description: <one-line description>
|
||||
category: testing | quality | process | infrastructure | release | docs | support | meta
|
||||
memory: enabled # optional; default enabled. Set to disabled for stateless utility agents
|
||||
---
|
||||
```
|
||||
|
||||
#### Session-start protocol (for session-bound agents)
|
||||
|
||||
Agents that do ongoing work across sessions should include a session-start block:
|
||||
|
||||
1. Check for `.kaizen/agents/<name>/memory.md` in the project root
|
||||
2. If present, read it and acknowledge relevant context in the opening brief
|
||||
3. Optionally invoke `kaizen-agentic memory brief <name>` for cross-agent orientation
|
||||
|
||||
Include this block in the agent prompt under a `## Session Start` heading.
|
||||
|
||||
#### Session-close protocol (for session-bound agents)
|
||||
|
||||
At the end of each session the agent should:
|
||||
|
||||
1. Update `## Accumulated Findings`, `## What Worked`, `## Watch Points` as needed
|
||||
2. Append one line to `## Session Log` (format: `YYYY-MM-DD · <summary> · <outcome>`)
|
||||
3. Bump `last_updated` and `session_count` in the frontmatter
|
||||
|
||||
Include this block in the agent prompt under a `## Session Close` heading.
|
||||
|
||||
Agents for which session state is irrelevant (e.g. `keepaTodofile`, `keepaChangelog`)
|
||||
should set `memory: disabled` in their frontmatter and omit these sections.
|
||||
|
||||
## Types of Contributions
|
||||
|
||||
We welcome various types of contributions:
|
||||
|
||||
33
README.md
33
README.md
@@ -1,8 +1,10 @@
|
||||
# Kaizen Agentic
|
||||
|
||||
AI agent development framework embracing continuous improvement through specialized agents and comprehensive development workflows.
|
||||
AI **agency** framework: 18 specialized agents that arrive in your project informed, learn from experience, and improve over time.
|
||||
|
||||
This project embraces the Japanese concept of "kaizen" (continuous improvement) applied to AI agent development. Every coding subagent becomes part of an optimization loop where performance is measured, patterns are analyzed, and specifications are refined over time.
|
||||
kaizen-agentic provides two things: a library of agent instruction sets you deploy into projects, and an **agency framework** that gives those agents persistent memory and coordination. Agents accumulate project-scoped knowledge across sessions. A Coach meta-agent synthesises patterns across the entire fleet and briefs incoming agents on what to know first.
|
||||
|
||||
This project embraces the Japanese concept of "kaizen" (continuous improvement) applied to AI agent development. Every agent becomes part of an optimization loop where performance is measured, patterns are analyzed, and knowledge is carried forward.
|
||||
|
||||
## Quick Start
|
||||
|
||||
@@ -70,14 +72,31 @@ kaizen-agentic install keepaTodofile keepaChangelog tdd-workflow
|
||||
kaizen-agentic status
|
||||
```
|
||||
|
||||
## Agency Framework
|
||||
|
||||
Agents deployed into a project can accumulate **project-scoped memory** — a structured file written at session close and read at session start. A **Coach** meta-agent reads across all agent memories and produces targeted orientation briefs for incoming agents.
|
||||
|
||||
```bash
|
||||
# Scaffold memory for an agent
|
||||
kaizen-agentic memory init sys-medic
|
||||
|
||||
# Brief an incoming agent using all existing project memories
|
||||
kaizen-agentic memory brief tdd-workflow
|
||||
|
||||
# Review an agent's accumulated knowledge
|
||||
kaizen-agentic memory show project-management
|
||||
```
|
||||
|
||||
See [docs/agency-framework.md](docs/agency-framework.md) for the full model.
|
||||
|
||||
## Features
|
||||
|
||||
- **16+ Specialized Agents**: Project management, testing, code quality, documentation
|
||||
- **CLI Tool**: Easy agent installation and management (`kaizen-agentic`)
|
||||
- **18 Specialized Agents**: Project management, testing, code quality, infrastructure, meta
|
||||
- **Agency Framework**: Project-scoped agent memory + Coach meta-agent for cross-agent synthesis
|
||||
- **CLI Tool**: Easy agent installation, management, and memory commands (`kaizen-agentic`)
|
||||
- **Project Templates**: Pre-configured setups for different project types
|
||||
- **Claude Code Integration**: Seamless integration with Claude Code workflows
|
||||
- **Comprehensive Testing**: Full test coverage with multiple testing strategies
|
||||
- **Standards Compliance**: Follows PythonVibes and industry best practices
|
||||
|
||||
## Available Agents
|
||||
|
||||
@@ -101,6 +120,10 @@ kaizen-agentic status
|
||||
- **setupRepository**: Repository initialization and standards compliance
|
||||
- **claude-documentation**: Claude Code configuration and documentation
|
||||
- **tooling-optimization**: Repository tooling usage optimization
|
||||
- **sys-medic**: Infrastructure health monitoring and diagnostics
|
||||
|
||||
### Meta
|
||||
- **coach**: Coaching meta-agent — reads all project agent memories, synthesises cross-agent briefs, and orients incoming agents
|
||||
|
||||
[View complete agent list](docs/AGENT_DISTRIBUTION.md#agent-categories)
|
||||
|
||||
|
||||
163
agents/agent-coach.md
Normal file
163
agents/agent-coach.md
Normal file
@@ -0,0 +1,163 @@
|
||||
---
|
||||
name: coach
|
||||
description: Coaching meta-agent that reads all agent memories in a project and synthesises cross-agent briefs and new-agent orientations
|
||||
category: meta
|
||||
memory: enabled
|
||||
---
|
||||
|
||||
# Coach Agent
|
||||
|
||||
## Role
|
||||
|
||||
You are the **kaizen-agentic Coach** — a meta-agent that observes, synthesises,
|
||||
and advises. You do not perform domain work (coding, testing, infrastructure).
|
||||
Your sole purpose is to read across the accumulated memories of all agents in a
|
||||
project and produce useful, targeted briefs.
|
||||
|
||||
You are invoked via:
|
||||
```
|
||||
kaizen-agentic memory brief <agent-name>
|
||||
```
|
||||
|
||||
Or directly by the operator: *"Coach, brief the sys-medic agent on this project"*
|
||||
or *"Coach, what patterns have you observed across all agents?"*
|
||||
|
||||
---
|
||||
|
||||
## What You Do
|
||||
|
||||
### 1. Cross-Agent Synthesis
|
||||
|
||||
Read all `.kaizen/agents/*/memory.md` files in the current project. Identify:
|
||||
|
||||
- **Shared patterns**: themes that appear across multiple agents
|
||||
(e.g. "three agents flagged missing test coverage as a risk")
|
||||
- **Cross-domain risks**: signals in one agent's memory that should inform
|
||||
another (e.g. infrastructure instability flagged by sys-medic → tdd-workflow
|
||||
should account for flaky environments)
|
||||
- **Resource or architectural signals**: recurring mentions of specific files,
|
||||
modules, services, or systems across agents
|
||||
- **Contradictions or gaps**: where agents hold conflicting assumptions or where
|
||||
no agent has coverage
|
||||
|
||||
### 2. New-Agent Orientation
|
||||
|
||||
When asked to brief a specific agent about to be deployed for the first time:
|
||||
|
||||
1. Read all existing agent memories in the project
|
||||
2. Filter for what is relevant to the incoming agent's domain
|
||||
3. Produce a targeted orientation brief covering:
|
||||
- **Project context**: what kind of project this is, key constraints
|
||||
- **What to know first**: the most important facts for this agent
|
||||
- **Watch points**: risks or pitfalls flagged by other agents that are relevant
|
||||
- **What has worked**: successful approaches in adjacent domains
|
||||
- **Open threads**: unresolved items from other agents that may interact with
|
||||
this agent's work
|
||||
|
||||
### 3. Fleet Health Overview
|
||||
|
||||
When asked for a fleet overview:
|
||||
|
||||
- Summarise the health of the agent fleet: which agents are active, stale, or
|
||||
missing from the project
|
||||
- Flag agents with high `session_count` and still-open `## Open Threads`
|
||||
- Identify agents whose memories suggest overlapping concerns
|
||||
- Recommend whether any memory files should be reviewed or reset
|
||||
|
||||
---
|
||||
|
||||
## How to Read Agent Memory Files
|
||||
|
||||
Memory files live at `.kaizen/agents/<name>/memory.md` relative to the project
|
||||
root. Each follows ADR-002 structure:
|
||||
|
||||
```
|
||||
## Project Context ← agent's understanding of the project
|
||||
## Accumulated Findings ← patterns and recurring issues
|
||||
## What Worked ← validated approaches
|
||||
## Watch Points ← risks and traps
|
||||
## Open Threads ← unresolved items
|
||||
## Session Log ← chronological session summaries
|
||||
```
|
||||
|
||||
When synthesising, weight `## Watch Points` and `## Open Threads` most heavily —
|
||||
these are the signals most likely to be actionable for another agent.
|
||||
|
||||
---
|
||||
|
||||
## Output Format
|
||||
|
||||
### Cross-agent brief
|
||||
|
||||
```
|
||||
## Cross-Agent Brief — <project name>
|
||||
Generated: <date>
|
||||
Agents with memory: <list>
|
||||
|
||||
### Shared Patterns
|
||||
<bullet list of themes appearing across ≥2 agents>
|
||||
|
||||
### Cross-Domain Risks
|
||||
<risks from one domain relevant to others>
|
||||
|
||||
### Open Threads (fleet-wide)
|
||||
<unresolved items that span or affect multiple agents>
|
||||
|
||||
### Fleet Health
|
||||
<which agents are active/stale, any concerning signals>
|
||||
```
|
||||
|
||||
### New-agent orientation
|
||||
|
||||
```
|
||||
## Orientation Brief for: <agent-name>
|
||||
Project: <project name>
|
||||
Generated: <date>
|
||||
Sources: <which agent memories were read>
|
||||
|
||||
### What to Know First
|
||||
<3–5 most important facts for this agent>
|
||||
|
||||
### Watch Points
|
||||
<risks relevant to this agent's domain>
|
||||
|
||||
### What Has Worked
|
||||
<approaches validated by other agents that apply here>
|
||||
|
||||
### Open Threads You May Encounter
|
||||
<items from other agents that may intersect with your work>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Behaviour Boundaries
|
||||
|
||||
- **Do not** modify agent memory files
|
||||
- **Do not** perform any domain-specific work (coding, testing, diagnosis)
|
||||
- **Do not** make decisions — synthesise and advise only
|
||||
- **If no memories exist**: say so clearly and offer to help initialise them
|
||||
- **If asked about a specific agent not present**: note the gap
|
||||
|
||||
---
|
||||
|
||||
## Coach's Own Memory
|
||||
|
||||
The coach maintains `.kaizen/agents/coach/memory.md` covering:
|
||||
|
||||
- Fleet-level patterns observed over time
|
||||
- How the agent population in this project has evolved
|
||||
- Meta-observations about how well the memory convention is being followed
|
||||
- Recurring gaps or blind spots in the agent fleet
|
||||
|
||||
### Session Start
|
||||
|
||||
1. Check for `.kaizen/agents/coach/memory.md`.
|
||||
2. If present, read it — prior fleet observations provide context for the current synthesis.
|
||||
3. Scan `.kaizen/agents/*/memory.md` to build the current fleet picture.
|
||||
|
||||
### Session Close
|
||||
|
||||
1. Update `## Accumulated Findings` with new fleet-level patterns.
|
||||
2. Note any new agents added or memory files reset.
|
||||
3. Append one line to `## Session Log`: `YYYY-MM-DD · <brief requested for> · <key finding>`.
|
||||
4. Bump `last_updated` and `session_count`.
|
||||
@@ -181,3 +181,17 @@ Generate issues for relevantly expensive or risky stuff and in direct feedback w
|
||||
Controled in-scope-work does not need the costly issue capture, refinement, selection roundtrip.
|
||||
|
||||
Remember: Your role is to help developers quickly understand "where we are" and "what should we do next" when picking up work on the MarkiTect project, and to ensure proper session wrap-up for continuity.
|
||||
|
||||
---
|
||||
|
||||
## Session Start
|
||||
|
||||
1. Check for `.kaizen/agents/project-management/memory.md` in the project root.
|
||||
2. If present, read it and surface relevant context (last session summary, open threads, watch points) in your opening brief.
|
||||
3. If absent, offer to initialise with `kaizen-agentic memory init project-management`.
|
||||
|
||||
## Session Close
|
||||
|
||||
1. Update `## Accumulated Findings`, `## What Worked`, `## Watch Points` based on this session.
|
||||
2. Append one line to `## Session Log`: `YYYY-MM-DD · <brief summary> · <outcome>`.
|
||||
3. Bump `last_updated` to today and increment `session_count`.
|
||||
|
||||
@@ -484,4 +484,19 @@ The agent directly addresses the root causes:
|
||||
|
||||
---
|
||||
|
||||
## Session Start
|
||||
|
||||
1. Check for `.kaizen/agents/requirements-engineering/memory.md` in the project root.
|
||||
2. If present, read it — pay attention to `## Watch Points` (recurring interface pitfalls) and `## Accumulated Findings` (known domain model patterns).
|
||||
3. If absent, offer to initialise with `kaizen-agentic memory init requirements-engineering`.
|
||||
|
||||
## Session Close
|
||||
|
||||
1. Update `## Accumulated Findings` with any new interface contracts, domain model patterns, or mock alignment lessons from this session.
|
||||
2. Update `## Watch Points` with any newly discovered incompatibility risks.
|
||||
3. Append one line to `## Session Log`: `YYYY-MM-DD · <feature or component analysed> · <outcome>`.
|
||||
4. Bump `last_updated` to today and increment `session_count`.
|
||||
|
||||
---
|
||||
|
||||
*This agent provides systematic foundation analysis and interface contract verification based on lessons learned from Issue #59 to prevent compatibility issues and ensure solid architectural foundations before implementation.*
|
||||
@@ -353,3 +353,17 @@ A good result allows a reader to quickly answer:
|
||||
- Is it overlapping something else?
|
||||
|
||||
If those are clear, the task is successful.
|
||||
|
||||
---
|
||||
|
||||
## Session Start
|
||||
|
||||
1. Check for `.kaizen/agents/scope-analyst/memory.md` in the project root.
|
||||
2. If present, read it — prior SCOPE.md analyses and boundary decisions may be useful context.
|
||||
3. If absent, this is typically fine for a first-run analysis.
|
||||
|
||||
## Session Close
|
||||
|
||||
1. If a SCOPE.md was produced or meaningfully revised, note the key boundary decisions in `## Accumulated Findings`.
|
||||
2. Append one line to `## Session Log`: `YYYY-MM-DD · <repo analysed> · <outcome>`.
|
||||
3. Bump `last_updated` to today and increment `session_count`.
|
||||
|
||||
@@ -2,9 +2,31 @@
|
||||
name: sys-medic
|
||||
description: Linux/Kubernetes node health assessment agent — diagnoses process, memory, CPU, disk, network, and kubelet issues with safe, prioritized, evidence-driven guidance
|
||||
category: infrastructure
|
||||
memory: enabled
|
||||
source: sys-medic (~/sys-medic/agent-sys-medic.md)
|
||||
---
|
||||
|
||||
# Session Start Protocol
|
||||
|
||||
1. Check for `.kaizen/agents/sys-medic/memory.md` in the project root.
|
||||
2. If present, read it — pay particular attention to `## Node Profiles` (known baselines
|
||||
per host) and `## Recurring Findings` (issues seen before on this infrastructure).
|
||||
3. Acknowledge memory in your opening brief: note any relevant node profiles or prior findings.
|
||||
4. If a structured assessment is requested, check for
|
||||
`agents/protocols/sys-medic/k3s-node-health-assessment.md` and use it as your procedure.
|
||||
|
||||
# Session Close Protocol
|
||||
|
||||
1. Update `## Node Profiles` — add or revise the entry for any host assessed this session
|
||||
(hostname | typical load | known quirks | last assessment date).
|
||||
2. Update `## Recurring Findings` — if an issue was seen previously, increment its frequency
|
||||
and note the date.
|
||||
3. Update `## Accumulated Findings`, `## What Worked`, `## Watch Points` as appropriate.
|
||||
4. Append one line to `## Session Log`: `YYYY-MM-DD · <host(s) assessed> · <key finding> · <outcome>`.
|
||||
5. Bump `last_updated` and `session_count`.
|
||||
|
||||
---
|
||||
|
||||
You are SysMedic, a careful coding and systems operations agent for Linux-based Kubernetes environments.
|
||||
|
||||
Your role is to assess operational health, identify signs of instability, and provide safe, practical guidance to improve system condition. You are not a blind automation bot. You are an evidence-driven operational analyst and remediation advisor.
|
||||
@@ -306,4 +328,39 @@ When invoked, begin by determining the current operational picture and producing
|
||||
- signs of instability
|
||||
- safe guidance for stabilization
|
||||
|
||||
If a structured assessment is requested, use the k3s-node-health-assessment protocol
|
||||
(`agents/protocols/sys-medic/k3s-node-health-assessment.md`) if available. The protocol
|
||||
provides a step-by-step procedure covering OS baseline, process hygiene, memory, CPU,
|
||||
disk, network, Kubernetes node state, and k3s runtime health.
|
||||
|
||||
If insufficient evidence is available, state exactly which safe inspection commands should be run next.
|
||||
|
||||
---
|
||||
|
||||
# Memory Template Extensions
|
||||
|
||||
sys-medic's memory file (`.kaizen/agents/sys-medic/memory.md`) extends the base template
|
||||
(ADR-002) with three additional sections:
|
||||
|
||||
```markdown
|
||||
## Node Profiles
|
||||
<!-- Per-node operational baseline established over sessions -->
|
||||
<!-- hostname | typical load | known quirks | last assessment date -->
|
||||
|
||||
## Recurring Findings
|
||||
<!-- Issues seen more than once: pattern · first seen · frequency -->
|
||||
|
||||
## Cleared Issues
|
||||
<!-- Issues that were resolved: what was done · when · outcome -->
|
||||
```
|
||||
|
||||
These sections are maintained by the session-close protocol above.
|
||||
|
||||
---
|
||||
|
||||
# Related Documents
|
||||
|
||||
- **Protocol runbook:** `agents/protocols/sys-medic/k3s-node-health-assessment.md`
|
||||
- **Memory convention:** `docs/adr/ADR-002-project-memory-convention.md`
|
||||
- **Protocols convention:** `docs/adr/ADR-003-protocols-artifact-convention.md`
|
||||
- **Agency framework:** `docs/agency-framework.md`
|
||||
|
||||
@@ -357,3 +357,18 @@ Remember: The goal is to build software incrementally using the proven TDD8 cycl
|
||||
**ISSUE-TEST-RED-GREEN-REFACTOR-DOCUMENT-REFINE-PUBLISH**
|
||||
|
||||
The comprehensive 8-step development methodology that transforms requirements into production-ready, well-tested, documented functionality while maintaining code quality and project momentum through intelligent sidequest management.
|
||||
|
||||
---
|
||||
|
||||
## Session Start
|
||||
|
||||
1. Check for `.kaizen/agents/tdd-workflow/memory.md` in the project root.
|
||||
2. If present, read it — pay attention to `## Watch Points` (recurring test pitfalls) and `## What Worked` (effective patterns for this project).
|
||||
3. If absent, offer to initialise with `kaizen-agentic memory init tdd-workflow`.
|
||||
|
||||
## Session Close
|
||||
|
||||
1. Update `## Accumulated Findings` with any new TDD patterns or recurring failure modes observed.
|
||||
2. Update `## What Worked` and `## Watch Points` as needed.
|
||||
3. Append one line to `## Session Log`: `YYYY-MM-DD · <issue or feature> · <outcome>`.
|
||||
4. Bump `last_updated` to today and increment `session_count`.
|
||||
|
||||
40
agents/protocols/README.md
Normal file
40
agents/protocols/README.md
Normal file
@@ -0,0 +1,40 @@
|
||||
# Agent Protocols
|
||||
|
||||
This directory contains **protocol runbooks** — structured, human-readable procedural documents that kaizen-agentic agents reference during structured assessments or remediation work.
|
||||
|
||||
Protocols are distinct from agent prompts:
|
||||
- **Agent prompts** (`agents/agent-*.md`) shape AI behaviour
|
||||
- **Protocols** (`agents/protocols/<agent>/<slug>.md`) are procedural checklists for humans and agents to execute
|
||||
|
||||
See [ADR-003](../../docs/adr/ADR-003-protocols-artifact-convention.md) for the full convention.
|
||||
|
||||
## Structure
|
||||
|
||||
```
|
||||
agents/protocols/
|
||||
<agent-name>/
|
||||
<slug>.md ← one file per protocol
|
||||
```
|
||||
|
||||
## Available Protocols
|
||||
|
||||
| Agent | Protocol | Description |
|
||||
|-------|----------|-------------|
|
||||
| sys-medic | [k3s-node-health-assessment](sys-medic/k3s-node-health-assessment.md) | Structured k3s node health check covering kubelet, pods, resources, networking, and storage |
|
||||
|
||||
## Usage
|
||||
|
||||
**From the CLI:**
|
||||
|
||||
```bash
|
||||
kaizen-agentic protocols list # List all protocols
|
||||
kaizen-agentic protocols list sys-medic # List sys-medic protocols
|
||||
kaizen-agentic protocols show sys-medic k3s-node-health-assessment
|
||||
```
|
||||
|
||||
**From an agent session:**
|
||||
|
||||
When an agent references a protocol, it will say something like:
|
||||
> *"Use the k3s-node-health-assessment protocol at `agents/protocols/sys-medic/k3s-node-health-assessment.md` for this assessment."*
|
||||
|
||||
Protocols can also be read and executed directly without an AI agent.
|
||||
306
agents/protocols/sys-medic/k3s-node-health-assessment.md
Normal file
306
agents/protocols/sys-medic/k3s-node-health-assessment.md
Normal file
@@ -0,0 +1,306 @@
|
||||
---
|
||||
agent: sys-medic
|
||||
slug: k3s-node-health-assessment
|
||||
title: k3s Node Health Assessment
|
||||
version: 1.0.0
|
||||
last_updated: "2026-03-18"
|
||||
---
|
||||
|
||||
# k3s Node Health Assessment
|
||||
|
||||
## Purpose
|
||||
|
||||
Structured health assessment for a Linux host running k3s (lightweight Kubernetes). Covers OS baseline, process hygiene, memory, CPU, disk, network, Kubernetes node state, and runtime services. Produces a prioritized findings report with safe next actions.
|
||||
|
||||
## Scope
|
||||
|
||||
- Linux host (any distribution) running k3s
|
||||
- k3s worker nodes and single-node clusters
|
||||
- Hosts where `kubectl` and/or `k3s kubectl` are available
|
||||
- Applies whether the host is healthy, degraded, or in an unknown state
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Shell access to the target host (SSH or console)
|
||||
- Ideally: sudo or root access (some checks require it)
|
||||
- Available tools: `ps`, `top`, `free`, `vmstat`, `iostat`, `ss`, `journalctl`, `systemctl`, `dmesg`, `df`, `du`, `lsof`, `kubectl` or `k3s kubectl`
|
||||
- Note which tools are absent — record what could not be checked
|
||||
|
||||
---
|
||||
|
||||
## Procedure
|
||||
|
||||
### Step 1 — OS and Node Baseline
|
||||
|
||||
Establish context before diagnosing anything.
|
||||
|
||||
```bash
|
||||
hostname
|
||||
uptime
|
||||
uname -r
|
||||
nproc
|
||||
free -h
|
||||
swapon --show
|
||||
df -h
|
||||
date
|
||||
```
|
||||
|
||||
Record:
|
||||
- Hostname and uptime
|
||||
- Kernel version
|
||||
- CPU core count
|
||||
- Total/used/free memory and swap
|
||||
- Overall disk usage per mount
|
||||
- Current time (for correlating log timestamps)
|
||||
|
||||
---
|
||||
|
||||
### Step 2 — Process Hygiene
|
||||
|
||||
```bash
|
||||
# Zombie and D-state processes
|
||||
ps aux | awk '$8 ~ /^[ZD]/ {print}'
|
||||
|
||||
# Top memory consumers
|
||||
ps aux --sort=-%mem | head -20
|
||||
|
||||
# Top CPU consumers
|
||||
ps aux --sort=-%cpu | head -20
|
||||
|
||||
# Processes with high FD counts (requires lsof)
|
||||
sudo lsof 2>/dev/null | awk '{print $2}' | sort | uniq -c | sort -rn | head -20
|
||||
|
||||
# Long-running suspicious processes (> 7 days)
|
||||
ps -eo pid,user,etime,comm --sort=-etime | head -30
|
||||
```
|
||||
|
||||
Look for:
|
||||
- Zombie count > 0
|
||||
- D-state (uninterruptible sleep) tasks
|
||||
- Unexpected high-memory or high-CPU processes
|
||||
- Stale maintenance scripts, port-forwards, debug sessions, rsync, or backup jobs
|
||||
- Orphaned shells or user sessions
|
||||
|
||||
---
|
||||
|
||||
### Step 3 — Memory Health
|
||||
|
||||
```bash
|
||||
# Overall memory picture
|
||||
free -h
|
||||
cat /proc/meminfo | grep -E 'MemAvailable|SwapFree|Dirty|Slab|KReclaimable'
|
||||
|
||||
# OOM kill history
|
||||
sudo dmesg | grep -i 'oom\|killed process' | tail -20
|
||||
sudo journalctl -k --since "24 hours ago" | grep -i 'oom\|out of memory' | tail -20
|
||||
|
||||
# Slab usage
|
||||
sudo slabtop -o | head -30
|
||||
|
||||
# cgroup memory pressure (if cgroups v2)
|
||||
find /sys/fs/cgroup -name "memory.pressure" 2>/dev/null | xargs grep -l "some" 2>/dev/null | head -10
|
||||
```
|
||||
|
||||
Look for:
|
||||
- Available memory < 10% of total
|
||||
- Swap being actively used (churn is worse than swap in use)
|
||||
- Recent OOM kills
|
||||
- High slab growth
|
||||
- cgroup memory pressure events
|
||||
|
||||
---
|
||||
|
||||
### Step 4 — CPU and Scheduler Health
|
||||
|
||||
```bash
|
||||
# Load average vs core count
|
||||
uptime
|
||||
nproc
|
||||
|
||||
# CPU idle and steal
|
||||
top -bn1 | grep '%Cpu'
|
||||
vmstat 1 5
|
||||
|
||||
# Run queue pressure
|
||||
vmstat 1 5 | awk '{print $1, $2}' # r=running, b=blocked
|
||||
```
|
||||
|
||||
Look for:
|
||||
- Load average persistently > core count
|
||||
- CPU idle < 10%
|
||||
- High CPU steal (virtualised hosts)
|
||||
- Run queue (r) > core count sustained
|
||||
- Blocked processes (b) > 0 sustained
|
||||
|
||||
---
|
||||
|
||||
### Step 5 — Disk and Filesystem Health
|
||||
|
||||
```bash
|
||||
# Disk usage
|
||||
df -h
|
||||
df -i # inode usage
|
||||
|
||||
# Large log files
|
||||
sudo du -sh /var/log/* 2>/dev/null | sort -rh | head -20
|
||||
sudo journalctl --disk-usage
|
||||
|
||||
# k3s data directory
|
||||
sudo du -sh /var/lib/rancher/k3s/ 2>/dev/null
|
||||
sudo du -sh /var/lib/rancher/k3s/agent/containerd/ 2>/dev/null
|
||||
|
||||
# Rapidly growing dirs (compare two snapshots 60s apart)
|
||||
sudo du -sh /var/lib/rancher /var/log /tmp 2>/dev/null
|
||||
```
|
||||
|
||||
Look for:
|
||||
- Any mount > 85% full (warning) or > 95% (critical)
|
||||
- Any mount with inode usage > 85%
|
||||
- Container image accumulation in containerd storage
|
||||
- Large or rapidly growing log files
|
||||
- Abandoned temp files
|
||||
|
||||
---
|
||||
|
||||
### Step 6 — Network and Connection State
|
||||
|
||||
```bash
|
||||
# Connection state summary
|
||||
ss -s
|
||||
ss -tnp | awk '{print $1}' | sort | uniq -c | sort -rn
|
||||
|
||||
# Unusual listeners
|
||||
ss -tlnp
|
||||
|
||||
# CLOSE_WAIT accumulation (application socket leak)
|
||||
ss -tnp | grep CLOSE_WAIT | wc -l
|
||||
|
||||
# TIME_WAIT count (normal but high counts may indicate connection thrash)
|
||||
ss -tnp | grep TIME_WAIT | wc -l
|
||||
```
|
||||
|
||||
Look for:
|
||||
- CLOSE_WAIT count > 50 (application not closing sockets)
|
||||
- SYN_RECV accumulation (connection flood or backlog issue)
|
||||
- Unexpected listeners on unusual ports
|
||||
- Long-lived unexpected tunnels or port-forwards
|
||||
|
||||
---
|
||||
|
||||
### Step 7 — Kubernetes Node Health
|
||||
|
||||
```bash
|
||||
# Node status and conditions
|
||||
kubectl get node $(hostname) -o wide 2>/dev/null || k3s kubectl get node $(hostname) -o wide
|
||||
|
||||
# Node conditions in detail
|
||||
kubectl describe node $(hostname) 2>/dev/null | grep -A 10 'Conditions:'
|
||||
|
||||
# Resource pressure
|
||||
kubectl top node $(hostname) 2>/dev/null
|
||||
|
||||
# Recent node events
|
||||
kubectl get events --field-selector involvedObject.name=$(hostname) --sort-by='.lastTimestamp' 2>/dev/null | tail -20
|
||||
|
||||
# Top pods by resource use
|
||||
kubectl top pods --all-namespaces --sort-by=memory 2>/dev/null | head -20
|
||||
|
||||
# Restarting pods on this node
|
||||
kubectl get pods --all-namespaces --field-selector spec.nodeName=$(hostname) 2>/dev/null | awk '$5 > 5 {print}'
|
||||
```
|
||||
|
||||
Look for:
|
||||
- Node Ready=False or Unknown
|
||||
- MemoryPressure, DiskPressure, PIDPressure, or NetworkUnavailable = True
|
||||
- Pods with high restart counts (> 5)
|
||||
- CrashLoopBackOff workloads
|
||||
- Evicted pods (indicates past resource pressure)
|
||||
|
||||
---
|
||||
|
||||
### Step 8 — k3s Runtime and Control Services
|
||||
|
||||
```bash
|
||||
# k3s service status
|
||||
sudo systemctl status k3s 2>/dev/null || sudo systemctl status k3s-agent
|
||||
|
||||
# k3s recent logs (last 100 lines)
|
||||
sudo journalctl -u k3s --since "1 hour ago" -n 100 2>/dev/null || \
|
||||
sudo journalctl -u k3s-agent --since "1 hour ago" -n 100
|
||||
|
||||
# containerd status (k3s embedded)
|
||||
sudo systemctl status containerd 2>/dev/null
|
||||
|
||||
# CNI / flannel if applicable
|
||||
sudo systemctl status flanneld 2>/dev/null
|
||||
sudo ip addr show flannel.1 2>/dev/null
|
||||
```
|
||||
|
||||
Look for:
|
||||
- k3s service not running or in failed state
|
||||
- Repeated restart entries in k3s logs
|
||||
- PLEG errors, image GC failures, sandbox creation failures
|
||||
- cgroup-related errors
|
||||
- API server timeout messages (on worker nodes: etcd or API server unreachable)
|
||||
|
||||
---
|
||||
|
||||
## Interpretation
|
||||
|
||||
| Signal | Normal | Warning | Critical |
|
||||
|--------|--------|---------|----------|
|
||||
| Load average | ≤ core count | 1–2× core count | > 2× sustained |
|
||||
| Memory available | > 20% | 10–20% | < 10% |
|
||||
| Disk usage | < 75% | 75–90% | > 90% |
|
||||
| Inode usage | < 75% | 75–90% | > 90% |
|
||||
| Zombie count | 0 | 1–5 | > 5 or climbing |
|
||||
| OOM kills (24h) | 0 | 1–2 | > 2 or recent |
|
||||
| Pod restarts | < 3 | 3–10 | > 10 or CrashLoop |
|
||||
| CLOSE_WAIT | < 10 | 10–50 | > 50 |
|
||||
| Node Ready | True | — | False / Unknown |
|
||||
|
||||
Confidence in findings:
|
||||
- **High** — direct evidence (OOM kill log, node condition set, error in service log)
|
||||
- **Medium** — indirect evidence (high memory use without OOM, rising load with no clear cause)
|
||||
- **Low** — circumstantial (aging process without other indicators)
|
||||
|
||||
---
|
||||
|
||||
## Remediation
|
||||
|
||||
### High memory pressure
|
||||
|
||||
1. Identify top consumers: `ps aux --sort=-%mem | head -20`
|
||||
2. Check for OOM history: `dmesg | grep -i oom`
|
||||
3. If a workload is leaking: restart the specific pod (not the node)
|
||||
4. If slab is high: check for inode-heavy workloads or NFS mounts
|
||||
5. Do not drop caches unless explicitly justified — Linux reclaims page cache automatically
|
||||
|
||||
### Disk pressure
|
||||
|
||||
1. Find largest directories: `du -sh /var/lib/rancher/k3s/agent/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/* | sort -rh | head -20`
|
||||
2. Prune unused container images: `k3s crictl rmi --prune` (safe — only removes unused images)
|
||||
3. Clear old journal logs: `sudo journalctl --vacuum-size=500M`
|
||||
4. Identify log-bloating pods and fix their logging config
|
||||
|
||||
### k3s service failing
|
||||
|
||||
1. Check service status: `sudo systemctl status k3s`
|
||||
2. Check logs: `sudo journalctl -u k3s -n 200`
|
||||
3. Common causes: etcd data corruption (single-node), API server unreachable (worker), disk full, cert expiry
|
||||
4. Do not restart k3s without understanding the cause — a restart may mask the issue
|
||||
|
||||
### High pod restart count
|
||||
|
||||
1. Check logs: `kubectl logs <pod> --previous`
|
||||
2. Check events: `kubectl describe pod <pod>`
|
||||
3. Distinguish OOMKilled (memory limit) from CrashLoop (application error) from Liveness probe failure
|
||||
|
||||
---
|
||||
|
||||
## Notes
|
||||
|
||||
- This protocol was adapted from the sys-medic agent's structured assessment areas and the sys-medic repo's companion protocol document.
|
||||
- For single-node k3s clusters, the control plane (server) and data plane (agent) run on the same host — check both `k3s` and `k3s-agent` services.
|
||||
- On hosts without `kubectl` in PATH, use `k3s kubectl` as a drop-in replacement.
|
||||
- Protocol version history is tracked via the `version` frontmatter field. Update on significant structural changes.
|
||||
57
docs/adr/ADR-001-workplan-convention.md
Normal file
57
docs/adr/ADR-001-workplan-convention.md
Normal file
@@ -0,0 +1,57 @@
|
||||
---
|
||||
id: ADR-001
|
||||
title: Workplan Convention
|
||||
status: accepted
|
||||
date: "2026-03-18"
|
||||
---
|
||||
|
||||
# ADR-001 — Workplan Convention
|
||||
|
||||
## Status
|
||||
|
||||
Accepted
|
||||
|
||||
## Context
|
||||
|
||||
kaizen-agentic needs a way to track planned work that is version-controlled,
|
||||
visible to the state-hub, and authoritative when the two diverge.
|
||||
|
||||
## Decision
|
||||
|
||||
Work items originate as Markdown files in `workplans/` **before** being
|
||||
registered in the state-hub DB. The file is always authoritative; the DB is
|
||||
a read/query model derived from it.
|
||||
|
||||
**File naming:** `workplans/kaizen-agentic-WP-NNNN-<slug>.md`
|
||||
**ID prefix:** `KAIZEN-WP`
|
||||
|
||||
### Required YAML frontmatter
|
||||
|
||||
```yaml
|
||||
---
|
||||
id: KAIZEN-WP-NNNN
|
||||
type: workplan
|
||||
title: "..."
|
||||
domain: custodian
|
||||
repo: kaizen-agentic
|
||||
status: active | completed | archived
|
||||
owner: kaizen-agentic
|
||||
topic_slug: custodian
|
||||
state_hub_workstream_id: <uuid>
|
||||
created: "YYYY-MM-DD"
|
||||
updated: "YYYY-MM-DD"
|
||||
---
|
||||
```
|
||||
|
||||
### Task tracking
|
||||
|
||||
Tasks use `- [ ]` / `- [x]` checkboxes with a `T##` code prefix. A
|
||||
`## State Hub Task IDs` table at the end of each workplan maps codes to
|
||||
DB UUIDs so status can be synced without a list_tasks lookup.
|
||||
|
||||
## Consequences
|
||||
|
||||
- File is the source of truth; DB drift is auto-fixable via
|
||||
`check_repo_consistency(fix=True)`.
|
||||
- Tasks must be created in the file first, then registered in the hub.
|
||||
- C-12 warnings are expected when the DB host has not yet seen local changes.
|
||||
119
docs/adr/ADR-002-project-memory-convention.md
Normal file
119
docs/adr/ADR-002-project-memory-convention.md
Normal file
@@ -0,0 +1,119 @@
|
||||
---
|
||||
id: ADR-002
|
||||
title: Project Memory Convention
|
||||
status: accepted
|
||||
date: "2026-03-18"
|
||||
---
|
||||
|
||||
# ADR-002 — Project Memory Convention
|
||||
|
||||
## Status
|
||||
|
||||
Accepted
|
||||
|
||||
## Context
|
||||
|
||||
kaizen-agentic agents are stateless by default — each session starts from
|
||||
scratch with no knowledge of what has been tried, what worked, or what the
|
||||
project's recurring patterns are. This makes agents less useful over time
|
||||
and forces the operator to re-supply context that the agent itself
|
||||
accumulated.
|
||||
|
||||
## Decision
|
||||
|
||||
Each agent deployed into a project may maintain a **project-scoped memory
|
||||
file**. Memory files are written at session close and read at session start.
|
||||
|
||||
### File location
|
||||
|
||||
```
|
||||
<project-root>/.kaizen/agents/<agent-name>/memory.md
|
||||
```
|
||||
|
||||
The `.kaizen/` directory is the kaizen-agentic ecosystem's project-level
|
||||
state directory, analogous to `.claude/` for Claude Code.
|
||||
|
||||
### Memory file structure
|
||||
|
||||
```markdown
|
||||
---
|
||||
agent: <agent-name>
|
||||
project: <project-root or slug>
|
||||
last_updated: <ISO date>
|
||||
session_count: <n>
|
||||
---
|
||||
|
||||
## Project Context
|
||||
<!-- What this agent knows about the project it works in -->
|
||||
|
||||
## Accumulated Findings
|
||||
<!-- Patterns, recurring issues, key decisions encountered -->
|
||||
|
||||
## What Worked
|
||||
<!-- Approaches that produced good results in this project -->
|
||||
|
||||
## Watch Points
|
||||
<!-- Recurring risks, traps, or areas requiring extra care -->
|
||||
|
||||
## Open Threads
|
||||
<!-- Things noticed but not yet acted on -->
|
||||
|
||||
## Session Log
|
||||
<!-- One-line entry per session: date · summary · outcome -->
|
||||
```
|
||||
|
||||
### Session-start protocol (all memory-enabled agents)
|
||||
|
||||
1. Check for `.kaizen/agents/<name>/memory.md` in the project root.
|
||||
2. If present, read it before beginning work.
|
||||
3. Acknowledge the memory in the opening brief.
|
||||
|
||||
### Session-close protocol (all memory-enabled agents)
|
||||
|
||||
1. Update `## Accumulated Findings`, `## What Worked`, `## Watch Points`
|
||||
as needed.
|
||||
2. Append one line to `## Session Log`.
|
||||
3. Bump `last_updated` and `session_count`.
|
||||
|
||||
### Agent opt-out
|
||||
|
||||
An agent may declare `memory: disabled` in its YAML frontmatter to opt out.
|
||||
Default is enabled. Stateless utility agents (e.g. `keepaTodofile`) should
|
||||
opt out.
|
||||
|
||||
### CLI interface
|
||||
|
||||
```
|
||||
kaizen-agentic memory show <agent> # Print agent memory for current project
|
||||
kaizen-agentic memory init <agent> # Scaffold empty memory file
|
||||
kaizen-agentic memory brief <agent> # Run coach, print orientation for agent
|
||||
kaizen-agentic memory clear <agent> # Wipe memory (with confirmation prompt)
|
||||
```
|
||||
|
||||
`memory init` creates the `.kaizen/agents/<name>/memory.md` file with the
|
||||
standard structure and populates the frontmatter.
|
||||
|
||||
### Coaching meta-agent
|
||||
|
||||
A dedicated `agent-coach.md` (category: `meta`) reads across all
|
||||
`.kaizen/agents/*/memory.md` files in a project and:
|
||||
|
||||
- Synthesises a cross-agent brief (shared patterns, cross-domain risks)
|
||||
- Produces a new-agent orientation targeted at a specific agent about to
|
||||
be deployed for the first time
|
||||
- Maintains its own memory covering meta-level fleet observations
|
||||
|
||||
`kaizen-agentic memory brief <agent>` invokes the coach to produce this
|
||||
orientation.
|
||||
|
||||
## Consequences
|
||||
|
||||
- Agents accumulate project-specific knowledge and arrive in later sessions
|
||||
informed rather than blank.
|
||||
- The `.kaizen/` directory should be added to `.gitignore` by default;
|
||||
teams may choose to commit it for shared context.
|
||||
- Memory files are human-readable and can be manually edited or reviewed.
|
||||
- The coach agent provides a single synthesised view across all agent
|
||||
memories — reducing the operator's burden of re-supplying context.
|
||||
- Agents with `memory: disabled` remain fully stateless and require no
|
||||
`.kaizen/` setup.
|
||||
116
docs/adr/ADR-003-protocols-artifact-convention.md
Normal file
116
docs/adr/ADR-003-protocols-artifact-convention.md
Normal file
@@ -0,0 +1,116 @@
|
||||
---
|
||||
id: ADR-003
|
||||
title: Protocols Artifact Convention
|
||||
status: accepted
|
||||
date: "2026-03-18"
|
||||
---
|
||||
|
||||
# ADR-003 — Protocols Artifact Convention
|
||||
|
||||
## Status
|
||||
|
||||
Accepted
|
||||
|
||||
## Context
|
||||
|
||||
Some agents perform structured, repeatable assessments or remediation procedures
|
||||
(e.g. sys-medic's k3s node health assessment). These procedures exist as narrative
|
||||
text embedded in agent prompts or companion documents, making them hard to discover,
|
||||
reference, version, or evolve independently of the agent prompt.
|
||||
|
||||
Protocols are distinct from agent prompts:
|
||||
- Agent prompts shape AI behaviour
|
||||
- Protocols are procedural checklists for humans and agents to execute
|
||||
|
||||
They need their own artifact type with a stable location and structure.
|
||||
|
||||
## Decision
|
||||
|
||||
### File location
|
||||
|
||||
```
|
||||
agents/protocols/<agent-name>/<slug>.md
|
||||
```
|
||||
|
||||
Protocols live inside the `agents/` directory alongside agent definitions,
|
||||
grouped by owning agent. The `agents/protocols/` subtree is a managed artifact
|
||||
collection — not executable code, not agent prompts.
|
||||
|
||||
### File structure
|
||||
|
||||
```markdown
|
||||
---
|
||||
agent: <agent-name>
|
||||
slug: <slug>
|
||||
title: <human-readable title>
|
||||
version: <semver>
|
||||
last_updated: <ISO date>
|
||||
---
|
||||
|
||||
# <Title>
|
||||
|
||||
## Purpose
|
||||
<!-- One paragraph: what this protocol checks or achieves -->
|
||||
|
||||
## Scope
|
||||
<!-- What systems, components, or conditions this protocol applies to -->
|
||||
|
||||
## Prerequisites
|
||||
<!-- What must be true before starting -->
|
||||
|
||||
## Procedure
|
||||
|
||||
### Step 1 — <name>
|
||||
<!-- Commands, checks, observations -->
|
||||
|
||||
### Step 2 — <name>
|
||||
...
|
||||
|
||||
## Interpretation
|
||||
<!-- How to read the results: what is normal, what is a warning, what requires action -->
|
||||
|
||||
## Remediation
|
||||
<!-- Common issues and how to resolve them -->
|
||||
|
||||
## Notes
|
||||
<!-- Version history, known limitations, related protocols -->
|
||||
```
|
||||
|
||||
### Lifecycle
|
||||
|
||||
- Protocols are **created** when a repeatable procedure is identified during agent work
|
||||
- Protocols are **refined** across sessions as the owning agent accumulates experience
|
||||
- Protocols are **referenced** by agent prompts using the convention:
|
||||
*"If available, use the `<slug>` protocol at `agents/protocols/<agent-name>/<slug>.md`"*
|
||||
- Protocols are **human-readable** and can be executed without an AI agent present
|
||||
|
||||
### Relationship to agent memory
|
||||
|
||||
Agent memory captures *what was learned* in a project. Protocols capture *how to
|
||||
do a repeatable thing* independent of any specific project. A protocol may be
|
||||
updated based on findings across many projects, but it does not store
|
||||
project-specific state.
|
||||
|
||||
### CLI interface
|
||||
|
||||
```
|
||||
kaizen-agentic protocols list [agent] # List protocols (optionally filtered by agent)
|
||||
kaizen-agentic protocols show <agent> <slug> # Print a protocol
|
||||
```
|
||||
|
||||
`kaizen-agentic memory init sys-medic` will scaffold the sys-medic protocol
|
||||
directory alongside the memory file when protocols exist for that agent.
|
||||
|
||||
### README
|
||||
|
||||
Each `agents/protocols/` directory contains a `README.md` explaining the
|
||||
convention and listing available protocols.
|
||||
|
||||
## Consequences
|
||||
|
||||
- Protocols are independently versioned and evolvable without touching agent prompts.
|
||||
- The `agents/protocols/` directory is part of the kaizen-agentic repo and
|
||||
distributed alongside agent definitions.
|
||||
- Operators can view, adapt, or execute protocols without running the CLI.
|
||||
- The first protocol — sys-medic's k3s node health assessment — migrates from
|
||||
its current location into `agents/protocols/sys-medic/k3s-node-health-assessment.md`.
|
||||
241
docs/agency-framework.md
Normal file
241
docs/agency-framework.md
Normal file
@@ -0,0 +1,241 @@
|
||||
# Agency Framework
|
||||
|
||||
kaizen-agentic is not just a library of agent instruction sets — it is an **agency**: a system where agents are deployed into projects with their own persistent memory, learn from experience, and are guided by a coaching meta-agent that distils patterns across the entire fleet.
|
||||
|
||||
## Overview
|
||||
|
||||
When you deploy a kaizen-agentic agent into a project, it can accumulate **project-scoped memory** — a structured file written at session close and read at session start. A **Coach** meta-agent reads across all agent memories and produces orientation briefs for newly deployed agents: what has been tried, what worked, what to watch out for.
|
||||
|
||||
Agents arrive in a project informed, not blank.
|
||||
|
||||
---
|
||||
|
||||
## Project Memory
|
||||
|
||||
### Location Convention
|
||||
|
||||
```
|
||||
<project-root>/.kaizen/agents/<agent-name>/memory.md
|
||||
```
|
||||
|
||||
The `.kaizen/` directory is analogous to `.claude/` — a project-level configuration and state directory owned by the kaizen-agentic ecosystem.
|
||||
|
||||
### Memory File Structure
|
||||
|
||||
```markdown
|
||||
---
|
||||
agent: <name>
|
||||
project: <project-root or slug>
|
||||
last_updated: <ISO date>
|
||||
session_count: <n>
|
||||
---
|
||||
|
||||
## Project Context
|
||||
<!-- What this agent knows about the project it is working in -->
|
||||
|
||||
## Accumulated Findings
|
||||
<!-- Patterns, recurring issues, key decisions the agent has encountered -->
|
||||
|
||||
## What Worked
|
||||
<!-- Approaches that produced good results in this project -->
|
||||
|
||||
## Watch Points
|
||||
<!-- Recurring risks, traps, or areas requiring extra care -->
|
||||
|
||||
## Open Threads
|
||||
<!-- Things noticed but not yet acted on -->
|
||||
|
||||
## Session Log
|
||||
<!-- One-line entry per session: date · summary · outcome -->
|
||||
```
|
||||
|
||||
### Session Protocols
|
||||
|
||||
**Session-start (all agents with `memory: enabled`):**
|
||||
|
||||
1. Check for `.kaizen/agents/<name>/memory.md` in the project root.
|
||||
2. If present, read it before beginning work.
|
||||
3. Acknowledge the memory in the opening brief.
|
||||
|
||||
**Session-close (all agents with `memory: enabled`):**
|
||||
|
||||
1. Update `## Accumulated Findings`, `## What Worked`, `## Watch Points` as appropriate.
|
||||
2. Append one line to `## Session Log`: `YYYY-MM-DD · <summary> · <outcome>`.
|
||||
3. Bump `last_updated` and `session_count`.
|
||||
|
||||
---
|
||||
|
||||
## Agent YAML Frontmatter
|
||||
|
||||
Each agent definition (`agents/agent-<name>.md`) includes a YAML frontmatter block:
|
||||
|
||||
```yaml
|
||||
---
|
||||
name: <name>
|
||||
description: <one-line description>
|
||||
category: <category>
|
||||
memory: enabled # or: disabled
|
||||
---
|
||||
```
|
||||
|
||||
The `memory` field defaults to `enabled`. Set `memory: disabled` for agents that are stateless by design (e.g. `wisdom-encouragement`).
|
||||
|
||||
---
|
||||
|
||||
## The Coach Meta-Agent
|
||||
|
||||
`agents/agent-coach.md` is a **meta-agent** — it performs no domain work (coding, testing, infrastructure). Its sole purpose is synthesis and advice.
|
||||
|
||||
### What the Coach Does
|
||||
|
||||
- **Cross-agent synthesis**: reads all `.kaizen/agents/*/memory.md` files, identifies shared patterns, cross-domain risks, and contradictions
|
||||
- **New-agent orientation**: when briefing a specific agent, filters all existing memories for what is relevant and produces a targeted brief
|
||||
- **Fleet health overview**: summarises which agents are active, stale, or missing; flags high-session-count agents with open threads
|
||||
|
||||
### Invoking the Coach
|
||||
|
||||
**Via CLI (assembles raw memory context):**
|
||||
|
||||
```bash
|
||||
kaizen-agentic memory brief <agent-name>
|
||||
```
|
||||
|
||||
This prints a structured orientation brief. Pass the output to a Claude session with `agents/agent-coach.md` loaded for full LLM synthesis.
|
||||
|
||||
**Directly in a Claude session:**
|
||||
|
||||
```
|
||||
Coach, brief the sys-medic agent on this project.
|
||||
Coach, what patterns have you observed across all agents?
|
||||
```
|
||||
|
||||
The Coach maintains its own memory at `.kaizen/agents/coach/memory.md` covering fleet-level observations over time.
|
||||
|
||||
---
|
||||
|
||||
## CLI Reference
|
||||
|
||||
The `memory` command group manages project-scoped agent memory:
|
||||
|
||||
```
|
||||
kaizen-agentic memory show <agent> # Print agent memory for the current project
|
||||
kaizen-agentic memory init <agent> # Scaffold an empty memory file
|
||||
kaizen-agentic memory brief <agent> # Assemble orientation context for the coach
|
||||
kaizen-agentic memory clear <agent> # Wipe memory (with confirmation prompt)
|
||||
```
|
||||
|
||||
### Options
|
||||
|
||||
`memory brief` accepts:
|
||||
- `--target / -t` — project root (default: current directory)
|
||||
- `--raw` — dump raw memory file contents without the structured header
|
||||
|
||||
### Example Workflow
|
||||
|
||||
```bash
|
||||
# First deployment of sys-medic into a project
|
||||
kaizen-agentic memory init sys-medic
|
||||
|
||||
# After a few sessions, brief an incoming tdd-workflow agent
|
||||
kaizen-agentic memory brief tdd-workflow
|
||||
# → paste output into Claude with agent-coach.md loaded
|
||||
|
||||
# Review accumulated memory for a specific agent
|
||||
kaizen-agentic memory show project-management
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Protocol Runbooks
|
||||
|
||||
Agents can reference **protocol runbooks** — structured, human-readable procedural checklists for structured assessments or remediation work. Protocols are distinct from agent prompts:
|
||||
|
||||
- **Agent prompts** (`agents/agent-*.md`) shape AI behaviour
|
||||
- **Protocols** (`agents/protocols/<agent>/<slug>.md`) are procedural documents for humans and agents to execute
|
||||
|
||||
### Location Convention
|
||||
|
||||
```
|
||||
agents/protocols/
|
||||
<agent-name>/
|
||||
<slug>.md ← one file per protocol
|
||||
```
|
||||
|
||||
### Protocol Frontmatter
|
||||
|
||||
Each protocol file has a YAML frontmatter block:
|
||||
|
||||
```yaml
|
||||
---
|
||||
agent: <agent-name>
|
||||
slug: <slug>
|
||||
title: <human-readable title>
|
||||
version: 1.0.0
|
||||
last_updated: "<ISO date>"
|
||||
---
|
||||
```
|
||||
|
||||
### Referencing Protocols from Agents
|
||||
|
||||
Agents with `memory: enabled` check for relevant protocols at session start and reference them in their session-start protocol block. For example, sys-medic's session-start protocol instructs:
|
||||
|
||||
> *"If a structured assessment is requested, check for `agents/protocols/sys-medic/k3s-node-health-assessment.md` and use it as your procedure."*
|
||||
|
||||
### CLI Reference
|
||||
|
||||
```bash
|
||||
kaizen-agentic protocols list # List all protocols
|
||||
kaizen-agentic protocols list sys-medic # Filter by agent
|
||||
kaizen-agentic protocols show sys-medic k3s-node-health-assessment
|
||||
```
|
||||
|
||||
### sys-medic Memory and Protocols Integration
|
||||
|
||||
sys-medic extends the base memory template with three additional sections for operational continuity across sessions:
|
||||
|
||||
```markdown
|
||||
## Node Profiles
|
||||
<!-- Per-node operational baseline established over sessions -->
|
||||
<!-- hostname | typical load | known quirks | last assessment date -->
|
||||
|
||||
## Recurring Findings
|
||||
<!-- Issues seen more than once: pattern · first seen · frequency -->
|
||||
|
||||
## Cleared Issues
|
||||
<!-- Issues that were resolved: what was done · when · outcome -->
|
||||
```
|
||||
|
||||
These sections are maintained automatically by the sys-medic session-close protocol.
|
||||
|
||||
The **k3s Node Health Assessment** (`agents/protocols/sys-medic/k3s-node-health-assessment.md`) is the first protocol runbook — a step-by-step procedure covering OS baseline, process hygiene, memory, CPU, disk, network, Kubernetes node state, and k3s runtime health.
|
||||
|
||||
### Available Protocols
|
||||
|
||||
| Agent | Protocol | Description |
|
||||
|-------|----------|-------------|
|
||||
| sys-medic | [k3s-node-health-assessment](../agents/protocols/sys-medic/k3s-node-health-assessment.md) | Structured k3s node health check |
|
||||
|
||||
See [ADR-003: Protocols Artifact Convention](adr/ADR-003-protocols-artifact-convention.md) for the full specification.
|
||||
|
||||
---
|
||||
|
||||
## Agents with Memory Enabled
|
||||
|
||||
All agents that do session-bound project work have `memory: enabled` in their frontmatter and include session-start/session-close protocol blocks:
|
||||
|
||||
| Agent | Category | Notes |
|
||||
|-------|----------|-------|
|
||||
| project-management | process | Reference implementation of the session protocol pattern |
|
||||
| tdd-workflow | testing | |
|
||||
| requirements-engineering | process | |
|
||||
| scope-analyst | process | |
|
||||
| sys-medic | infrastructure | Extended memory template (node profiles, recurring findings) |
|
||||
| coach | meta | Fleet-level memory |
|
||||
|
||||
---
|
||||
|
||||
## Related Documents
|
||||
|
||||
- [ADR-001: Workplan Convention](../workplans/kaizen-agentic-WP-0001-community-engagement.md) — how work items are structured
|
||||
- [ADR-002: Project Memory Convention](../workplans/kaizen-agentic-WP-0002-agency-framework.md) — memory file location, structure, and lifecycle
|
||||
- [WP-0002: Agency Framework](../workplans/kaizen-agentic-WP-0002-agency-framework.md) — full implementation workplan
|
||||
@@ -118,14 +118,14 @@ def cli():
|
||||
pass
|
||||
|
||||
|
||||
@cli.command()
|
||||
@cli.command("list")
|
||||
@click.option(
|
||||
"--category",
|
||||
type=click.Choice([c.value for c in AgentCategory]),
|
||||
help="Filter by category",
|
||||
)
|
||||
@click.option("--verbose", "-v", is_flag=True, help="Show detailed information")
|
||||
def list(category: Optional[str], verbose: bool):
|
||||
def list_agents(category: Optional[str], verbose: bool):
|
||||
"""List available agents."""
|
||||
registry = _get_registry()
|
||||
|
||||
@@ -756,6 +756,260 @@ def remove(name: str, target: str):
|
||||
click.echo(f"❌ Extension not found: {name}")
|
||||
|
||||
|
||||
@cli.group()
|
||||
def memory():
|
||||
"""Manage project-scoped agent memory (.kaizen/agents/<name>/memory.md)."""
|
||||
pass
|
||||
|
||||
|
||||
@memory.command("show")
|
||||
@click.argument("agent_name")
|
||||
@click.option("--target", "-t", default=".", help="Project root (default: current)")
|
||||
def memory_show(agent_name: str, target: str):
|
||||
"""Print agent memory for the current project."""
|
||||
memory_path = _memory_path(target, agent_name)
|
||||
|
||||
if not memory_path.exists():
|
||||
click.echo(f"No memory found for agent '{agent_name}'.")
|
||||
click.echo(f" Expected: {memory_path}")
|
||||
click.echo(f" Run: kaizen-agentic memory init {agent_name}")
|
||||
return
|
||||
|
||||
click.echo(memory_path.read_text())
|
||||
|
||||
|
||||
@memory.command("init")
|
||||
@click.argument("agent_name")
|
||||
@click.option("--target", "-t", default=".", help="Project root (default: current)")
|
||||
def memory_init(agent_name: str, target: str):
|
||||
"""Scaffold an empty memory file for an agent."""
|
||||
memory_path = _memory_path(target, agent_name)
|
||||
|
||||
if memory_path.exists():
|
||||
click.echo(f"Memory file already exists: {memory_path}")
|
||||
return
|
||||
|
||||
memory_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
project_name = Path(target).resolve().name
|
||||
|
||||
content = f"""---
|
||||
agent: {agent_name}
|
||||
project: {project_name}
|
||||
last_updated: {_today()}
|
||||
session_count: 0
|
||||
---
|
||||
|
||||
## Project Context
|
||||
<!-- What this agent knows about the project it works in -->
|
||||
|
||||
## Accumulated Findings
|
||||
<!-- Patterns, recurring issues, key decisions encountered -->
|
||||
|
||||
## What Worked
|
||||
<!-- Approaches that produced good results in this project -->
|
||||
|
||||
## Watch Points
|
||||
<!-- Recurring risks, traps, or areas requiring extra care -->
|
||||
|
||||
## Open Threads
|
||||
<!-- Things noticed but not yet acted on -->
|
||||
|
||||
## Session Log
|
||||
<!-- One-line entry per session: date · summary · outcome -->
|
||||
"""
|
||||
memory_path.write_text(content)
|
||||
click.echo(f"Initialized memory for '{agent_name}': {memory_path}")
|
||||
|
||||
# For agents with protocols, note the protocol location
|
||||
registry = _get_registry()
|
||||
protocols_dir = registry.agents_dir / "protocols" / agent_name
|
||||
if protocols_dir.exists():
|
||||
slugs = [f.stem for f in sorted(protocols_dir.glob("*.md")) if f.name != "README.md"]
|
||||
if slugs:
|
||||
click.echo(f" Protocols available for '{agent_name}':")
|
||||
for slug in slugs:
|
||||
click.echo(f" kaizen-agentic protocols show {agent_name} {slug}")
|
||||
|
||||
|
||||
@memory.command("brief")
|
||||
@click.argument("agent_name")
|
||||
@click.option("--target", "-t", default=".", help="Project root (default: current)")
|
||||
@click.option("--raw", is_flag=True, help="Dump raw memory files without synthesis header")
|
||||
def memory_brief(agent_name: str, target: str, raw: bool):
|
||||
"""Print a coach-synthesised orientation for an agent.
|
||||
|
||||
Reads all agent memories in the project and formats an orientation brief
|
||||
for the specified agent, following the coach agent (agents/agent-coach.md)
|
||||
output format. Pass to a Claude session with the coach agent loaded for
|
||||
full LLM synthesis.
|
||||
"""
|
||||
project_root = Path(target).resolve()
|
||||
kaizen_dir = project_root / ".kaizen" / "agents"
|
||||
project_name = project_root.name
|
||||
|
||||
# Collect all agent memories
|
||||
own_memory: Optional[str] = None
|
||||
other_memories: dict = {}
|
||||
|
||||
if kaizen_dir.exists():
|
||||
for agent_dir in sorted(kaizen_dir.iterdir()):
|
||||
if not agent_dir.is_dir():
|
||||
continue
|
||||
mf = agent_dir / "memory.md"
|
||||
if not mf.exists():
|
||||
continue
|
||||
if agent_dir.name == agent_name:
|
||||
own_memory = mf.read_text()
|
||||
else:
|
||||
other_memories[agent_dir.name] = mf.read_text()
|
||||
|
||||
if raw:
|
||||
if own_memory:
|
||||
click.echo(f"=== {agent_name} ===\n{own_memory}")
|
||||
for name, content in other_memories.items():
|
||||
click.echo(f"=== {name} ===\n{content}")
|
||||
return
|
||||
|
||||
from datetime import date as _date
|
||||
today = _date.today().isoformat()
|
||||
sources = ([agent_name] if own_memory else []) + list(other_memories.keys())
|
||||
|
||||
click.echo(f"## Orientation Brief for: {agent_name}")
|
||||
click.echo(f"Project: {project_name}")
|
||||
click.echo(f"Generated: {today}")
|
||||
click.echo(f"Sources: {', '.join(sources) if sources else 'none'}")
|
||||
click.echo()
|
||||
|
||||
if not sources:
|
||||
click.echo("No agent memory files found in this project.")
|
||||
click.echo(f" Run: kaizen-agentic memory init {agent_name}")
|
||||
click.echo(" Then load the coach agent (agents/agent-coach.md) for synthesis.")
|
||||
return
|
||||
|
||||
# Own memory section
|
||||
if own_memory:
|
||||
click.echo("### Your Memory")
|
||||
click.echo(own_memory)
|
||||
else:
|
||||
click.echo(f"### Your Memory\n(none — run: kaizen-agentic memory init {agent_name})\n")
|
||||
|
||||
# Cross-agent context
|
||||
if other_memories:
|
||||
click.echo("### Context From Other Agents")
|
||||
click.echo("(Load coach agent for full synthesis. Raw content below.)\n")
|
||||
for name, content in other_memories.items():
|
||||
click.echo(f"--- {name} ---")
|
||||
click.echo(content)
|
||||
else:
|
||||
click.echo("### Context From Other Agents\nNo other agent memories found in this project.\n")
|
||||
|
||||
click.echo("---")
|
||||
click.echo("Tip: Load agents/agent-coach.md in your Claude session and pass this output")
|
||||
click.echo(" for a full cross-agent synthesis and orientation brief.")
|
||||
|
||||
|
||||
@memory.command("clear")
|
||||
@click.argument("agent_name")
|
||||
@click.option("--target", "-t", default=".", help="Project root (default: current)")
|
||||
@click.confirmation_option(prompt="This will permanently delete the agent memory. Continue?")
|
||||
def memory_clear(agent_name: str, target: str):
|
||||
"""Wipe agent memory for the current project."""
|
||||
memory_path = _memory_path(target, agent_name)
|
||||
|
||||
if not memory_path.exists():
|
||||
click.echo(f"No memory found for agent '{agent_name}' — nothing to clear.")
|
||||
return
|
||||
|
||||
memory_path.unlink()
|
||||
click.echo(f"Cleared memory for '{agent_name}': {memory_path}")
|
||||
|
||||
# Remove empty parent directory
|
||||
if not any(memory_path.parent.iterdir()):
|
||||
memory_path.parent.rmdir()
|
||||
|
||||
|
||||
@cli.group()
|
||||
def protocols():
|
||||
"""Browse agent protocol runbooks (agents/protocols/<agent>/<slug>.md)."""
|
||||
pass
|
||||
|
||||
|
||||
@protocols.command("list")
|
||||
@click.argument("agent_name", required=False)
|
||||
def protocols_list(agent_name: Optional[str]):
|
||||
"""List available protocols, optionally filtered by agent."""
|
||||
registry = _get_registry()
|
||||
protocols_dir = registry.agents_dir / "protocols"
|
||||
|
||||
if not protocols_dir.exists():
|
||||
click.echo("No protocols directory found.")
|
||||
return
|
||||
|
||||
found = []
|
||||
agent_dirs = (
|
||||
[protocols_dir / agent_name] if agent_name else sorted(protocols_dir.iterdir())
|
||||
)
|
||||
for agent_dir in agent_dirs:
|
||||
if not agent_dir.is_dir() or agent_dir.name == "__pycache__":
|
||||
continue
|
||||
for protocol_file in sorted(agent_dir.glob("*.md")):
|
||||
if protocol_file.name == "README.md":
|
||||
continue
|
||||
# Try to read title from frontmatter
|
||||
title = protocol_file.stem.replace("-", " ").title()
|
||||
try:
|
||||
content = protocol_file.read_text()
|
||||
for line in content.splitlines():
|
||||
if line.startswith("title:"):
|
||||
title = line.split(":", 1)[1].strip().strip('"')
|
||||
break
|
||||
except Exception:
|
||||
pass
|
||||
found.append((agent_dir.name, protocol_file.stem, title))
|
||||
|
||||
if not found:
|
||||
if agent_name:
|
||||
click.echo(f"No protocols found for agent '{agent_name}'.")
|
||||
else:
|
||||
click.echo("No protocols found.")
|
||||
return
|
||||
|
||||
click.echo("Available Protocols:")
|
||||
click.echo("=" * 40)
|
||||
current_agent = None
|
||||
for agent, slug, title in found:
|
||||
if agent != current_agent:
|
||||
click.echo(f"\n {agent}:")
|
||||
current_agent = agent
|
||||
click.echo(f" • {slug}: {title}")
|
||||
|
||||
|
||||
@protocols.command("show")
|
||||
@click.argument("agent_name")
|
||||
@click.argument("slug")
|
||||
def protocols_show(agent_name: str, slug: str):
|
||||
"""Print a protocol runbook."""
|
||||
registry = _get_registry()
|
||||
protocol_path = registry.agents_dir / "protocols" / agent_name / f"{slug}.md"
|
||||
|
||||
if not protocol_path.exists():
|
||||
click.echo(f"Protocol not found: {agent_name}/{slug}")
|
||||
click.echo(f" Expected: {protocol_path}")
|
||||
click.echo(f" Run: kaizen-agentic protocols list {agent_name}")
|
||||
return
|
||||
|
||||
click.echo(protocol_path.read_text())
|
||||
|
||||
|
||||
def _memory_path(target: str, agent_name: str) -> Path:
|
||||
return Path(target).resolve() / ".kaizen" / "agents" / agent_name / "memory.md"
|
||||
|
||||
|
||||
def _today() -> str:
|
||||
from datetime import date
|
||||
return date.today().isoformat()
|
||||
|
||||
|
||||
def _get_registry() -> AgentRegistry:
|
||||
"""Get the agent registry."""
|
||||
# Try to find agents directory
|
||||
|
||||
@@ -17,6 +17,7 @@ class AgentCategory(Enum):
|
||||
INFRASTRUCTURE = "infrastructure"
|
||||
TESTING = "testing"
|
||||
DOCUMENTATION = "documentation"
|
||||
META = "meta"
|
||||
|
||||
|
||||
@dataclass
|
||||
@@ -29,6 +30,7 @@ class AgentDefinition:
|
||||
category: AgentCategory
|
||||
dependencies: Set[str]
|
||||
model: Optional[str] = None
|
||||
memory: Optional[str] = None # "enabled" (default) | "disabled"
|
||||
|
||||
@classmethod
|
||||
def from_file(cls, file_path: Path) -> "AgentDefinition":
|
||||
@@ -56,6 +58,7 @@ class AgentDefinition:
|
||||
category=category,
|
||||
dependencies=dependencies,
|
||||
model=frontmatter.get("model"),
|
||||
memory=frontmatter.get("memory"),
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
@@ -127,8 +130,12 @@ class AgentDefinition:
|
||||
if any(keyword in name_lower for keyword in ["documentation", "claude"]):
|
||||
return AgentCategory.DOCUMENTATION
|
||||
|
||||
# Meta agents (coaching, cross-agent orchestration)
|
||||
if any(keyword in name_lower for keyword in ["coach", "meta"]):
|
||||
return AgentCategory.META
|
||||
|
||||
# Infrastructure agents
|
||||
if any(keyword in name_lower for keyword in ["setup", "repository", "tooling"]):
|
||||
if any(keyword in name_lower for keyword in ["setup", "repository", "tooling", "sys-medic", "medic"]):
|
||||
return AgentCategory.INFRASTRUCTURE
|
||||
|
||||
# Development process agents
|
||||
|
||||
262
tests/test_e2e_agency_framework.py
Normal file
262
tests/test_e2e_agency_framework.py
Normal file
@@ -0,0 +1,262 @@
|
||||
"""
|
||||
End-to-end tests for the agency framework: memory lifecycle and coach orientation.
|
||||
|
||||
Tests the full workflow:
|
||||
1. memory init — scaffold a memory file in a test project
|
||||
2. Populate memory with realistic content (simulating sessions)
|
||||
3. memory show — verify content is readable
|
||||
4. memory brief — verify orientation brief includes own memory and cross-agent context
|
||||
5. protocols list / show — verify protocol discovery works
|
||||
6. memory clear — verify wipe works
|
||||
"""
|
||||
|
||||
import textwrap
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
from click.testing import CliRunner
|
||||
|
||||
from kaizen_agentic.cli import cli
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Helpers
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
def _sys_medic_memory() -> str:
|
||||
"""Realistic sys-medic memory after two simulated sessions."""
|
||||
return textwrap.dedent("""\
|
||||
---
|
||||
agent: sys-medic
|
||||
project: test-cluster
|
||||
last_updated: 2026-03-18
|
||||
session_count: 2
|
||||
---
|
||||
|
||||
## Project Context
|
||||
k3s single-node cluster on an ARM64 host (tegpi-01).
|
||||
No external load balancer. Traefik ingress. Longhorn storage.
|
||||
|
||||
## Accumulated Findings
|
||||
- kubelet log rotation was disabled; logs grew to 2.1 GB
|
||||
- containerd image GC threshold was set too high (98%)
|
||||
|
||||
## What Worked
|
||||
- `journalctl --vacuum-size=500M` recovered ~1.8 GB without restart
|
||||
- Lowering GC threshold to 80% in containerd config resolved disk pressure
|
||||
|
||||
## Watch Points
|
||||
- inotify watch limit hits ceiling under heavy Longhorn load
|
||||
- node has only 4 GB RAM; memory pressure risk during backup windows
|
||||
|
||||
## Open Threads
|
||||
- Check whether kube-system namespace daemonsets have resource limits set
|
||||
|
||||
## Node Profiles
|
||||
tegpi-01 | load avg ~0.6 at idle | inotify-limited under load | 2026-03-18
|
||||
|
||||
## Recurring Findings
|
||||
- kubelet log growth · first seen 2026-03-10 · 2 occurrences
|
||||
|
||||
## Cleared Issues
|
||||
- containerd GC disk pressure · adjusted config 2026-03-18 · resolved
|
||||
|
||||
## Session Log
|
||||
2026-03-10 · tegpi-01 initial assessment · found log bloat + GC issue · recommendations documented
|
||||
2026-03-18 · tegpi-01 follow-up · verified GC fix; inotify limit noted · watch
|
||||
""")
|
||||
|
||||
|
||||
def _project_management_memory() -> str:
|
||||
"""Minimal project-management agent memory."""
|
||||
return textwrap.dedent("""\
|
||||
---
|
||||
agent: project-management
|
||||
project: test-cluster
|
||||
last_updated: 2026-03-15
|
||||
session_count: 1
|
||||
---
|
||||
|
||||
## Project Context
|
||||
Operational runbook project for the k3s home cluster.
|
||||
|
||||
## Accumulated Findings
|
||||
- Infra tasks are better tracked in Gitea issues than in TODO files
|
||||
|
||||
## Session Log
|
||||
2026-03-15 · initial planning session · task structure agreed
|
||||
""")
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Fixtures
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
@pytest.fixture
|
||||
def project(tmp_path):
|
||||
"""A temporary 'project' directory with a name."""
|
||||
p = tmp_path / "test-cluster"
|
||||
p.mkdir()
|
||||
return p
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Tests
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
class TestMemoryInit:
|
||||
def test_init_creates_file(self, project):
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(cli, ["memory", "init", "sys-medic", "--target", str(project)])
|
||||
assert result.exit_code == 0, result.output
|
||||
assert "Initialized memory" in result.output
|
||||
|
||||
memory_file = project / ".kaizen" / "agents" / "sys-medic" / "memory.md"
|
||||
assert memory_file.exists()
|
||||
|
||||
def test_init_file_content_has_required_sections(self, project):
|
||||
runner = CliRunner()
|
||||
runner.invoke(cli, ["memory", "init", "sys-medic", "--target", str(project)])
|
||||
|
||||
memory_file = project / ".kaizen" / "agents" / "sys-medic" / "memory.md"
|
||||
content = memory_file.read_text()
|
||||
|
||||
assert "agent: sys-medic" in content
|
||||
assert "project: test-cluster" in content
|
||||
assert "session_count: 0" in content
|
||||
assert "## Project Context" in content
|
||||
assert "## Accumulated Findings" in content
|
||||
assert "## What Worked" in content
|
||||
assert "## Watch Points" in content
|
||||
assert "## Open Threads" in content
|
||||
assert "## Session Log" in content
|
||||
|
||||
def test_init_idempotent(self, project):
|
||||
runner = CliRunner()
|
||||
runner.invoke(cli, ["memory", "init", "sys-medic", "--target", str(project)])
|
||||
result = runner.invoke(cli, ["memory", "init", "sys-medic", "--target", str(project)])
|
||||
assert result.exit_code == 0
|
||||
assert "already exists" in result.output
|
||||
|
||||
|
||||
class TestMemoryShow:
|
||||
def test_show_returns_content(self, project):
|
||||
memory_file = project / ".kaizen" / "agents" / "sys-medic" / "memory.md"
|
||||
memory_file.parent.mkdir(parents=True, exist_ok=True)
|
||||
memory_file.write_text(_sys_medic_memory())
|
||||
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(cli, ["memory", "show", "sys-medic", "--target", str(project)])
|
||||
assert result.exit_code == 0
|
||||
assert "Node Profiles" in result.output
|
||||
assert "tegpi-01" in result.output
|
||||
|
||||
def test_show_missing_prints_guidance(self, project):
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(cli, ["memory", "show", "sys-medic", "--target", str(project)])
|
||||
assert result.exit_code == 0
|
||||
assert "No memory found" in result.output
|
||||
assert "memory init" in result.output
|
||||
|
||||
|
||||
class TestMemoryBrief:
|
||||
def _populate(self, project):
|
||||
"""Write both agent memories into the project."""
|
||||
sm_dir = project / ".kaizen" / "agents" / "sys-medic"
|
||||
sm_dir.mkdir(parents=True, exist_ok=True)
|
||||
(sm_dir / "memory.md").write_text(_sys_medic_memory())
|
||||
|
||||
pm_dir = project / ".kaizen" / "agents" / "project-management"
|
||||
pm_dir.mkdir(parents=True, exist_ok=True)
|
||||
(pm_dir / "memory.md").write_text(_project_management_memory())
|
||||
|
||||
def test_brief_includes_own_memory(self, project):
|
||||
self._populate(project)
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(cli, ["memory", "brief", "sys-medic", "--target", str(project)])
|
||||
assert result.exit_code == 0
|
||||
assert "Orientation Brief for: sys-medic" in result.output
|
||||
assert "Your Memory" in result.output
|
||||
assert "tegpi-01" in result.output # content from sys-medic memory
|
||||
|
||||
def test_brief_includes_cross_agent_context(self, project):
|
||||
self._populate(project)
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(cli, ["memory", "brief", "sys-medic", "--target", str(project)])
|
||||
assert result.exit_code == 0
|
||||
assert "Context From Other Agents" in result.output
|
||||
assert "project-management" in result.output
|
||||
|
||||
def test_brief_coach_tip_present(self, project):
|
||||
self._populate(project)
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(cli, ["memory", "brief", "sys-medic", "--target", str(project)])
|
||||
assert result.exit_code == 0
|
||||
assert "agent-coach" in result.output
|
||||
|
||||
def test_brief_no_memory_gives_guidance(self, project):
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(cli, ["memory", "brief", "sys-medic", "--target", str(project)])
|
||||
assert result.exit_code == 0
|
||||
assert "No agent memory files found" in result.output
|
||||
|
||||
def test_brief_raw_flag_skips_header(self, project):
|
||||
self._populate(project)
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(cli, ["memory", "brief", "sys-medic", "--target", str(project), "--raw"])
|
||||
assert result.exit_code == 0
|
||||
assert "=== sys-medic ===" in result.output
|
||||
# Raw mode should not include the orientation header
|
||||
assert "Orientation Brief for:" not in result.output
|
||||
|
||||
|
||||
class TestMemoryClear:
|
||||
def test_clear_removes_file(self, project):
|
||||
memory_file = project / ".kaizen" / "agents" / "sys-medic" / "memory.md"
|
||||
memory_file.parent.mkdir(parents=True, exist_ok=True)
|
||||
memory_file.write_text(_sys_medic_memory())
|
||||
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(
|
||||
cli, ["memory", "clear", "sys-medic", "--target", str(project)], input="y\n"
|
||||
)
|
||||
assert result.exit_code == 0
|
||||
assert not memory_file.exists()
|
||||
|
||||
def test_clear_missing_is_graceful(self, project):
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(
|
||||
cli, ["memory", "clear", "sys-medic", "--target", str(project)], input="y\n"
|
||||
)
|
||||
assert result.exit_code == 0
|
||||
assert "nothing to clear" in result.output
|
||||
|
||||
|
||||
class TestProtocolsCommand:
|
||||
def test_protocols_list_finds_sys_medic(self):
|
||||
"""Protocols list against the real agents dir should include sys-medic k3s protocol."""
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(cli, ["protocols", "list"])
|
||||
assert result.exit_code == 0
|
||||
assert "sys-medic" in result.output
|
||||
assert "k3s-node-health-assessment" in result.output.replace("-", "-")
|
||||
|
||||
def test_protocols_list_filtered_by_agent(self):
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(cli, ["protocols", "list", "sys-medic"])
|
||||
assert result.exit_code == 0
|
||||
assert "k3s" in result.output.lower()
|
||||
|
||||
def test_protocols_show_outputs_content(self):
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(cli, ["protocols", "show", "sys-medic", "k3s-node-health-assessment"])
|
||||
assert result.exit_code == 0
|
||||
# Protocol should contain key structural sections
|
||||
assert "k3s" in result.output.lower()
|
||||
assert "Prerequisites" in result.output or "Scope" in result.output
|
||||
|
||||
def test_protocols_list_unknown_agent_no_crash(self):
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(cli, ["protocols", "list", "nonexistent-agent"])
|
||||
assert result.exit_code == 0
|
||||
assert "No protocols found" in result.output
|
||||
@@ -46,6 +46,19 @@ to make kaizen-agentic easier to adopt, contribute to, and operate reliably.
|
||||
|
||||
- [ ] T08 — Remove remaining development scaffolding or temporary files
|
||||
|
||||
## State Hub Task IDs
|
||||
|
||||
| Code | UUID |
|
||||
|------|------|
|
||||
| T01 | 349a5974-ce28-4624-b66e-3bb6bd961ad4 |
|
||||
| T02 | b88b4b39-1e35-424b-9a89-ba2a15e1c4e4 |
|
||||
| T03 | 588afaa3-cefb-48ff-9867-d7ccf78b92b8 |
|
||||
| T04 | 926969b5-f7db-414e-8752-00bb42951f13 |
|
||||
| T05 | 036022ef-4c7d-49c2-ad7e-c98d66079852 |
|
||||
| T06 | dfb9048b-353c-4c6d-96e4-67dd4846e592 |
|
||||
| T07 | da5322b3-4931-4846-a142-c5b67ee6fe6d |
|
||||
| T08 | af8a6f1e-e85b-4c49-98aa-cb2334b2870c |
|
||||
|
||||
## Notes
|
||||
|
||||
Tasks migrated from TODO.md [Unreleased] section on 2026-03-18.
|
||||
|
||||
@@ -4,17 +4,17 @@ type: workplan
|
||||
title: "Agency Framework: Project Memory, Coaching, and sys-medic Integration"
|
||||
domain: custodian
|
||||
repo: kaizen-agentic
|
||||
status: active
|
||||
status: done
|
||||
owner: kaizen-agentic
|
||||
topic_slug: custodian
|
||||
state_hub_workstream_id: d82b5ec9-ee3c-4b3b-9a27-2e30ab3a8158
|
||||
created: "2026-03-18"
|
||||
updated: "2026-03-18"
|
||||
updated: "2026-03-19"
|
||||
---
|
||||
|
||||
# KAIZEN-WP-0002 — Agency Framework: Project Memory, Coaching, and sys-medic Integration
|
||||
|
||||
**Status:** active
|
||||
**Status:** done
|
||||
**Owner:** kaizen-agentic
|
||||
**Repo:** kaizen-agentic
|
||||
|
||||
@@ -138,27 +138,27 @@ kaizen-agentic memory clear <agent> # Wipe memory (with confirmation)
|
||||
### Tasks
|
||||
|
||||
**Memory convention and tooling**
|
||||
- [ ] T07 — Write ADR: project memory convention (file location, structure, lifecycle)
|
||||
- [ ] T08 — Implement `memory` CLI command group (show, init, brief, clear)
|
||||
- [ ] T09 — Add session-start and session-close protocol sections to agent template /
|
||||
- [x] T07 — Write ADR: project memory convention (file location, structure, lifecycle)
|
||||
- [x] T08 — Implement `memory` CLI command group (show, init, brief, clear)
|
||||
- [x] T09 — Add session-start and session-close protocol sections to agent template /
|
||||
contributor guide
|
||||
|
||||
**Agent definition updates**
|
||||
- [ ] T10 — Add session-start and session-close protocol blocks to all existing
|
||||
- [x] T10 — Add session-start and session-close protocol blocks to all existing
|
||||
agents that do session-bound work (project-management, tdd-workflow,
|
||||
requirements-engineering, scope-analyst, sys-medic)
|
||||
- [ ] T11 — Update agent YAML frontmatter schema to include optional
|
||||
- [x] T11 — Update agent YAML frontmatter schema to include optional
|
||||
`memory: enabled|disabled` field (default: enabled)
|
||||
|
||||
**Coaching meta-agent**
|
||||
- [ ] T12 — Write `agents/agent-coach.md` definition
|
||||
- [ ] T13 — Wire `kaizen-agentic memory brief <agent>` to invoke coach logic
|
||||
- [ ] T14 — Add coach to agent registry and validate
|
||||
- [x] T12 — Write `agents/agent-coach.md` definition
|
||||
- [x] T13 — Wire `kaizen-agentic memory brief <agent>` to invoke coach logic
|
||||
- [x] T14 — Add coach to agent registry and validate
|
||||
|
||||
**Documentation**
|
||||
- [ ] T15 — Write `docs/agency-framework.md` explaining the memory model, coach
|
||||
- [x] T15 — Write `docs/agency-framework.md` explaining the memory model, coach
|
||||
agent, and deployment lifecycle
|
||||
- [ ] T16 — Update README to reflect the agency positioning
|
||||
- [x] T16 — Update README to reflect the agency positioning
|
||||
|
||||
### Definition of done
|
||||
|
||||
@@ -211,30 +211,30 @@ sys-medic's memory file gains an additional section beyond the base template:
|
||||
### Tasks
|
||||
|
||||
**Protocols convention**
|
||||
- [ ] T17 — Write ADR: protocols artifact convention (location, structure, lifecycle)
|
||||
- [ ] T18 — Create `agents/protocols/` directory with `README.md` explaining the
|
||||
- [x] T17 — Write ADR: protocols artifact convention (location, structure, lifecycle)
|
||||
- [x] T18 — Create `agents/protocols/` directory with `README.md` explaining the
|
||||
convention
|
||||
- [ ] T19 — Move/adapt `sys-medic` k3s health assessment protocol into
|
||||
- [x] T19 — Move/adapt `sys-medic` k3s health assessment protocol into
|
||||
`agents/protocols/sys-medic/k3s-node-health-assessment.md`
|
||||
|
||||
**sys-medic memory integration**
|
||||
- [ ] T20 — Add session-start and session-close protocol blocks to `agent-sys-medic.md`
|
||||
- [x] T20 — Add session-start and session-close protocol blocks to `agent-sys-medic.md`
|
||||
(extending the base protocol from Part 2 with the node-profile extensions)
|
||||
- [ ] T21 — Add `## Node Profiles`, `## Recurring Findings`, `## Cleared Issues`
|
||||
- [x] T21 — Add `## Node Profiles`, `## Recurring Findings`, `## Cleared Issues`
|
||||
extensions to sys-medic memory template
|
||||
- [ ] T22 — Update sys-medic prompt to reference its protocol runbook when performing
|
||||
- [x] T22 — Update sys-medic prompt to reference its protocol runbook when performing
|
||||
structured assessments ("use the k3s protocol if available")
|
||||
|
||||
**CLI integration**
|
||||
- [ ] T23 — Add `kaizen-agentic protocols list [agent]` and
|
||||
- [x] T23 — Add `kaizen-agentic protocols list [agent]` and
|
||||
`kaizen-agentic protocols show <agent> <slug>` commands
|
||||
- [ ] T24 — Add protocol scaffolding to `kaizen-agentic memory init sys-medic`
|
||||
- [x] T24 — Add protocol scaffolding to `kaizen-agentic memory init sys-medic`
|
||||
|
||||
**Validation and documentation**
|
||||
- [ ] T25 — End-to-end test: deploy sys-medic into a test project, run two simulated
|
||||
- [x] T25 — End-to-end test: deploy sys-medic into a test project, run two simulated
|
||||
sessions, verify memory accumulates and coach produces a useful brief
|
||||
- [ ] T26 — Update `docs/agency-framework.md` with protocols section
|
||||
- [ ] T27 — Update sys-medic agent doc with memory and protocol references
|
||||
- [x] T26 — Update `docs/agency-framework.md` with protocols section
|
||||
- [x] T27 — Update sys-medic agent doc with memory and protocol references
|
||||
|
||||
### Definition of done
|
||||
|
||||
@@ -261,6 +261,40 @@ sys-medic) into the framework at lower incremental cost.
|
||||
|
||||
---
|
||||
|
||||
## State Hub Task IDs
|
||||
|
||||
| Code | UUID |
|
||||
|------|------|
|
||||
| T01 | 41c9380b-1337-4e6d-aa74-98cc527a7975 |
|
||||
| T02 | 4badb7bb-9a1f-49bf-b75c-bce98f3d5490 |
|
||||
| T03 | d94b305a-e542-4e0e-a29e-e07339baf000 |
|
||||
| T04 | 15f5521e-c111-4078-b781-54bc3e208d9a |
|
||||
| T05 | bfc1f741-ce12-42a1-832a-588549446692 |
|
||||
| T06 | 7c2f87b4-023d-455f-9874-ad920d7e15ab |
|
||||
| T07 | 822c5aae-482e-4eae-9abc-c36bec6b3316 |
|
||||
| T08 | 49b164e0-3620-431b-89a5-cc5c12b42825 |
|
||||
| T09 | 104181da-2c3b-4482-a472-5316ec1dba9e |
|
||||
| T10 | 3ff44d3b-507b-4ece-98b9-e06a808405f3 |
|
||||
| T11 | 763ff109-02e4-4817-9aef-b91539a8a010 |
|
||||
| T12 | 9455c6c2-67df-49cc-b6ae-e7b813799824 |
|
||||
| T13 | 7175a344-35ca-4d13-bfa5-3fb0888cb6d2 |
|
||||
| T14 | c040e902-a0d2-48ad-89e9-2890cdf6d9a6 |
|
||||
| T15 | 88380f99-4b3e-4369-ab19-9ac0730343f9 |
|
||||
| T16 | c5770067-08ee-4944-ba0f-366a19f0d581 |
|
||||
| T17 | 4814e450-0d74-4fe9-9f80-940eabde8339 |
|
||||
| T18 | a0e8ee82-4f10-4f0f-baa3-8a656e9b8539 |
|
||||
| T19 | 814dc6f9-8652-4d0e-8c83-c99881b752f1 |
|
||||
| T20 | d2255c79-c211-4cf7-aa3c-2750637b7dee |
|
||||
| T21 | 1f249dd4-a74c-4063-b0d2-fb67ec0902d5 |
|
||||
| T22 | 1ddd546a-7868-4d18-81b4-f5c1fd364afe |
|
||||
| T23 | e533358e-15c3-4273-98e0-0365ead78d6a |
|
||||
| T24 | 787b5d6a-9c51-4043-910e-02f085894dc5 |
|
||||
| T25 | 81c57475-a0c1-4636-9baf-b3c9675e218e |
|
||||
| T26 | d1bdff1e-4c06-4677-85d0-8e109c3fa1a2 |
|
||||
| T27 | b10462d3-eb79-4336-adea-e2df758eb91f |
|
||||
|
||||
---
|
||||
|
||||
## Notes
|
||||
|
||||
- The `.kaizen/` directory in target projects is analogous to `.claude/` — a
|
||||
|
||||
Reference in New Issue
Block a user