7 Commits

Author SHA1 Message Date
eeb4eee5ef chore(release): bump version to 1.3.0 and date CHANGELOG
Some checks failed
ci / test (push) Has been cancelled
Publish Python package / publish (push) Failing after 8s
Scheduled agent execution (WP-0006). release-check passes: version
consistency, lint, tests, docs, packaged-agent parity all green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-17 23:33:55 +02:00
3b2edd4a9e feat: scheduled agent execution via activity-core (WP-0006, v1.3.0)
Enable kaizen agents to run on a regular cadence against a preselected repo
roster, orchestrated by activity-core and prepared by kaizen-agentic — without
this repo owning cron, Temporal workers, or an LLM runtime.

CLI + module:
- src/kaizen_agentic/schedule.py — .kaizen/schedule.yml parse/validate/scaffold
- `kaizen-agentic schedule` group: init, validate, list, prepare <agent>
  (prepare bundles agent prompt + memory + metrics + repo pointers, offline)
- tests/test_schedule_cli.py — 15 tests

Contract & design:
- ADR-005 scheduled agent execution; schema doc + example manifest
- discover_kaizen_scheduled_repos resolver spec, state-hub roster fields,
  kaizen.schedule.prepared event payload, activity-core handoff checklist
- INTEGRATION_PATTERNS Pattern 2 extended with roster model

ActivityDefinition drafts (enabled: false):
- weekly-coach-orientation, weekly-optimization-review

Docs: agency-framework, CLI cheat sheet, PACKAGE_RELEASE runner prereqs,
EcosystemIntegration, CHANGELOG, TODO. Workplan closed (status: done).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-17 08:19:51 +02:00
2400ff4890 docs: bind WP-0006 State Hub task IDs after fix-consistency
Some checks failed
ci / test (push) Failing after 13m57s
Inject hub task UUIDs from consistency sync; normalize workplan frontmatter.
2026-06-17 01:13:54 +02:00
df899abd98 docs: add WP-0006 scheduled agent execution workplan
Some checks failed
ci / test (push) Has been cancelled
Define activity-core scheduling for kaizen agents on preselected repos:
schedule manifest, prepare CLI, roster resolver handoff, and custodian pilot.
Point TODO/SCOPE at v1.3.0 active work.
2026-06-17 01:13:10 +02:00
b1fceeebc8 docs: close WP-0004 workplan and bind State Hub tasks
Some checks failed
ci / test (push) Failing after 37s
Add frontmatter tasks list with state_hub_task_id links and completion
section for ecosystem integration (Helix, activity-core, artifact-store).
2026-06-17 01:07:12 +02:00
fe795ca750 docs: close WP-0003 workplan and bind State Hub tasks
Some checks failed
ci / test (push) Failing after 38s
Add frontmatter tasks list with state_hub_task_id links and completion
section for the measurement loop (ADR-004, metrics CLI, Coach bridge).
2026-06-17 01:04:39 +02:00
1d0999eabb docs: close WP-0005 workplan and bind State Hub tasks
Some checks failed
ci / test (push) Failing after 36s
Add frontmatter tasks list with state_hub_task_id links, completion
section for v1.2.0 ship, and custodian brief from hub sync.
2026-06-17 01:02:08 +02:00
28 changed files with 2085 additions and 20 deletions

18
.custodian-brief.md Normal file
View File

@@ -0,0 +1,18 @@
<!-- custodian-brief: generated by fix-consistency — do not edit manually -->
# Custodian Brief — kaizen-agentic
**Domain:** custodian
**Last synced:** 2026-06-16 23:04 UTC
**State Hub:** http://127.0.0.1:8000 *(adjust if running on a remote machine)*
## Active Workstreams
*(none — repo may need first-session setup)*
---
## MCP Orientation (when available)
If the state-hub MCP server is reachable, call:
`get_domain_summary("custodian")`
This provides richer cross-domain context.
If the MCP call fails, use this file as your orientation source.

View File

@@ -7,6 +7,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
## [1.3.0] - 2026-06-17
### Added
- **Scheduled agent execution (WP-0006, ADR-005)** — run agents on a cadence
against a preselected repo roster, orchestrated by activity-core and prepared
by kaizen-agentic (no Temporal workers or LLM runtime in this repo)
- **`kaizen-agentic schedule`** CLI group — `init`, `validate`, `list`,
`prepare <agent>` (markdown/json) over `.kaizen/schedule.yml`
- **`.kaizen/schedule.yml`** manifest + schema docs and example
(`docs/integrations/schedule-schema.md`, `docs/examples/.kaizen/schedule.yml`)
- **ActivityDefinition drafts** (`enabled: false`) — `weekly-coach-orientation`,
`weekly-optimization-review`
- **Design specs** — `discover_kaizen_scheduled_repos` resolver, State Hub
roster fields, `kaizen.schedule.prepared` event payload, activity-core handoff
checklist
## [1.2.0] - 2026-06-16
### Added

View File

@@ -74,7 +74,7 @@ This repo is the canonical home for the **KaizenAgentic** operating model (`INTE
- Implementation: 20 agents, full CLI (`metrics`, `memory`, `feedback`), agency memory + ADR-004 metrics + optimizer wiring
- Stability: CLI stable (Click workaround in place); Gitea CI on main; publish workflow on `v*` tags
- Usage: internal dev projects and Custodian MCP hub-wide; pip install via Gitea extra index
- Active work: **WP-0005** (adoption polish, fleet parity, publish verification → v1.2.0)
- Active work: **WP-0006** (scheduled agent execution via activity-core → v1.3.0)
---

20
TODO.md
View File

@@ -10,18 +10,20 @@ The structure organizes **future tasks** by their impact, just as a changelog or
## [Unreleased] - *Active Vibe-Coding State* 💡
Tasks in workplan: `workplans/kaizen-agentic-WP-0005-adoption-parity.md` (v1.2.0)
Tasks in workplan: `workplans/kaizen-agentic-WP-0006-scheduled-agent-execution.md` (v1.3.0)
### To Add
* **Gitea publish pipeline verification** — secrets + workflow smoke test
* **`make agents-sync-package`** — keep `data/agents/` aligned with `agents/`
* **Install doc sweep** — HELLO_WORLD, CLI_CHEAT_SHEET, AGENT_DISTRIBUTION
### Implemented (pending v1.3.0 tag)
* **ADR-005 + `.kaizen/schedule.yml`** — scheduled agent execution contract
* **`kaizen-agentic schedule`** — validate, init, prepare, list
* **activity-core definitions** — weekly coach + optimization on preselected repos
* **Resolver + roster + event design** — `discover_kaizen_scheduled_repos`,
State Hub roster fields, `kaizen.schedule.prepared` payload, handoff checklist
### To Refactor
* **CI lint gate** — flake8 on `src/` in Gitea Actions
* **Makefile install hints** — point at Gitea registry or dev install
### To Add (release)
* **Tag v1.3.0** — once activity-core handoff issue is opened and pilot smoke-tested
* **activity-core implementation** — resolver + sync (separate repo; see handoff doc)
### Deferred to WP-0006 (v1.3.0)
### Deferred to WP-0007 (v1.3.0+)
* Interactive agent selection wizard
* Agent template schema validation in `validate`
* Documentation generation from agent metadata

View File

@@ -88,6 +88,22 @@ kaizen-agentic memory init tdd-workflow --no-metrics # memory only
Session-close template: `docs/templates/session-close-protocol.md`
### Scheduled Agent Execution (ADR-005)
```bash
# Opt this repo into fleet scheduling
kaizen-agentic schedule init # coach + optimization weekly
kaizen-agentic schedule init --timezone UTC # override timezone
kaizen-agentic schedule validate # schema + agent-name checks
kaizen-agentic schedule list # enabled entries (--all incl. disabled)
# Prepare orientation for a scheduled run (offline; no State Hub needed)
kaizen-agentic schedule prepare coach # markdown bundle
kaizen-agentic schedule prepare optimization --format json
```
activity-core fires the schedule and creates a task per (repo, agent); the task
runs `schedule prepare`. kaizen-agentic does not run cron or invoke Claude.
### Information
```bash
# List templates

View File

@@ -73,6 +73,45 @@ test -f .kaizen/metrics/optimizer/analysis.json && echo OK
**Boundary:** kaizen-agentic does not run Temporal schedules.
### Scheduled agent execution (WP-0006, ADR-005)
Beyond the metrics-only definitions above, agents themselves run on a cadence
against a **preselected repo roster**. The roster combines three sources:
| Source | Purpose |
|--------|---------|
| State Hub `GET /repos/` | Canonical slug list + `host_paths` |
| Repo opt-in: `.kaizen/schedule.yml` exists with `version` set | Per-repo enablement |
| Optional hub flag `kaizen_schedule_enabled: true` (future) | Operator override |
A repo is **schedule-eligible** when it is registered with reachable
`host_paths` **and** carries a valid `.kaizen/schedule.yml`. The activity-core
resolver `discover_kaizen_scheduled_repos` intersects these and emits
`context.scheduled_runs` (one entry per `(repo, agent)`); definitions `for_each`
over that output.
| Definition | Trigger | Agent | Prepare command |
|------------|---------|-------|-----------------|
| [weekly-coach-orientation](integrations/activity-definitions/weekly-coach-orientation.md) | Cron Mon 09:00 | `coach` | `schedule prepare coach` |
| [weekly-optimization-review](integrations/activity-definitions/weekly-optimization-review.md) | Cron Mon 10:00 | `optimization` | `schedule prepare optimization` |
**Listing schedule-eligible repos** (operator, no activity-core code):
```bash
# In each candidate repo on a host listed in state-hub host_paths:
kaizen-agentic schedule validate && kaizen-agentic schedule list
```
**Design docs (no state-hub / activity-core code in this repo):**
- [schedule-schema.md](integrations/schedule-schema.md) — `.kaizen/schedule.yml`
- [state-hub-roster-fields.md](integrations/state-hub-roster-fields.md) — hub fields/filters
- [discover-kaizen-scheduled-repos.md](integrations/discover-kaizen-scheduled-repos.md) — resolver spec
- [kaizen-schedule-prepared-event.md](integrations/kaizen-schedule-prepared-event.md) — event payload
**Boundary:** kaizen-agentic declares and prepares; activity-core schedules;
state-hub owns the roster.
---
## Pattern 3 — artifact-store evidence retention

View File

@@ -128,3 +128,27 @@ token with `TWINE_USERNAME=__token__`):
make release-publish
python -m twine upload dist/*
```
## Scheduled-run runner prerequisites (WP-0006)
A runner that executes a scheduled kaizen agent task (fired by activity-core)
needs:
- **`kaizen-agentic` on PATH** — `pip install kaizen-agentic` (or `pipx install
kaizen-agentic`) using the Gitea PyPI extra index when installing from the
internal registry:
```bash
pip install kaizen-agentic \
--extra-index-url https://gitea.coulomb.social/api/packages/coulomb/pypi/simple/
```
- **Repo checkout reachable** at the `host_paths[<host>]` registered in State
Hub, with a valid `.kaizen/schedule.yml` (`kaizen-agentic schedule validate`).
- **No State Hub required for `prepare`** — `schedule prepare` reads local
`.kaizen/` state only. The hub is needed by the *resolver* (activity-core),
not by the prepared session.
**Enabling a definition** (activity-core operator): keep the kaizen definitions
at `enabled: false` until a manual smoke test passes (see
[INTEGRATION_PATTERNS.md Pattern 2](INTEGRATION_PATTERNS.md) and the
[activity-core handoff checklist](integrations/activity-core-handoff-wp0006.md)),
then flip one definition to `enabled: true` in staging before fleet-wide enable.

View File

@@ -0,0 +1,149 @@
---
id: ADR-005
title: Scheduled Agent Execution Convention
status: accepted
date: "2026-06-17"
---
# ADR-005 — Scheduled Agent Execution Convention
## Status
Accepted
## Context
Kaizen agents are markdown instruction sets invoked in coding-agent sessions.
ADR-004 added project-scoped metrics; WP-0004 committed three metrics-focused
`ActivityDefinition` drafts (`enabled: false`). What is still missing is a way to
run **agents themselves** — not just the metrics optimizer — on a **regular
cadence** against a **preselected set of repos**, without kaizen-agentic owning
Temporal workers, cron, or an LLM runtime.
The ecosystem already separates concerns:
- **activity-core** owns scheduling (cron/event → task creation).
- **state-hub** owns the canonical repo roster and `host_paths`.
- **kaizen-agentic** owns the agents, project memory, and metrics.
A scheduled agent run therefore needs a contract that crosses these repos
without merging them.
## Decision
Introduce a **repo-local schedule manifest** and a **prepare** step. The
end-to-end flow:
```
activity-core cron
→ context resolver (roster ∩ repos with schedule.yml)
→ task per (repo, agent)
→ coding-agent session runs `kaizen-agentic schedule prepare <agent>`
→ session executes the agent instructions in that repo
```
kaizen-agentic's responsibilities are exactly two: **declare** the schedule
(`.kaizen/schedule.yml`) and **prepare** an orientation bundle for a run. It
does **not** fire cron, create tasks, or invoke Claude.
### 1. Schedule manifest — `.kaizen/schedule.yml`
A repo opts into fleet scheduling by committing this file:
```yaml
version: "1"
timezone: Europe/Berlin
agents:
coach:
cadence: weekly
cron: "0 9 * * 1" # optional override; default from ActivityDefinition
enabled: true
optimization:
cadence: weekly
cron: "0 10 * * 1"
enabled: true
tdd-workflow:
cadence: monthly
enabled: false
```
**Schema:**
| Key | Required | Type | Notes |
|-----|----------|------|-------|
| `version` | yes | string | Must be `"1"` |
| `timezone` | no | string | IANA tz; default supplied by ActivityDefinition |
| `agents` | yes | mapping | `agent-name → settings` |
| `agents.<name>.cadence` | yes | enum | `daily` \| `weekly` \| `monthly` |
| `agents.<name>.cron` | no | string | 5-field cron; overrides cadence default |
| `agents.<name>.enabled` | no | bool | Default `true` |
**Validation rules** (`kaizen-agentic schedule validate`):
- `version` must equal `"1"`.
- Every agent key must be an installed or packaged agent name.
- `cadence` must be one of the allowed values.
- Duplicate agent entries are rejected.
### 2. Roster (preselected repos)
A repo is **schedule-eligible** when **all** of:
1. It is a registered repo in state-hub (`GET /repos/`) with reachable
`host_paths`.
2. It contains a valid `.kaizen/schedule.yml`.
3. (Optional, future) it carries a `kaizen_schedule_enabled: true` hub flag.
The resolver `discover_kaizen_scheduled_repos` (specified in
`docs/integrations/discover-kaizen-scheduled-repos.md`, implemented in
activity-core) intersects these sources and emits `context.scheduled_runs`.
### 3. Prepare bundle — `schedule prepare <agent>`
Assembles, from **local `.kaizen/` state only** (offline-safe):
- The agent prompt (`agents/agent-<name>.md`, installed or packaged).
- Project memory (`.kaizen/agents/<name>/memory.md`) when present.
- Metrics summary (`.kaizen/metrics/<name>/summary.json`) when present.
- Repo pointers (`SCOPE.md`, `TODO.md`) when present.
- Suggested session-close commands (`metrics record`, memory update).
Output is `markdown` (default) or `json` (`--format json`) so activity-core can
embed it in a task `description` or a runner can parse it.
### CLI interface
```
kaizen-agentic schedule init [--target PATH] [--timezone TZ] [--force]
kaizen-agentic schedule validate [--target PATH]
kaizen-agentic schedule list [--target PATH] [--all]
kaizen-agentic schedule prepare <agent> [--target PATH] [--format markdown|json]
```
## Boundaries
- **No scheduling code** in kaizen-agentic. Cron and task creation belong to
activity-core; the roster query belongs to state-hub.
- **No LLM invocation.** `prepare` produces a runner-agnostic bundle; a human or
automated coding-agent session executes it.
- **State-hub schema changes** (roster opt-in flag) are designed here but
implemented in `the-custodian` (repo boundary).
## Consequences
- Operators declare per-repo schedules and a fleet roster without tribal
knowledge.
- activity-core can fire recurring tasks referencing `schedule prepare`.
- A scheduled session opens with full orientation (prompt + memory + metrics).
- The existing `weekly-metrics-optimize` definition (ADR-004 / WP-0004) remains
complementary; an `optimization` agent run may chain `schedule prepare
optimization` then `metrics optimize`.
## Related Documents
- [ADR-002: Project Memory Convention](ADR-002-project-memory-convention.md)
- [ADR-004: Project Metrics Convention](ADR-004-project-metrics-convention.md)
- [docs/integrations/schedule-schema.md](../integrations/schedule-schema.md)
- [docs/integrations/discover-kaizen-scheduled-repos.md](../integrations/discover-kaizen-scheduled-repos.md)
- [docs/agency-framework.md](../agency-framework.md)
- [KAIZEN-WP-0006](../../workplans/kaizen-agentic-WP-0006-scheduled-agent-execution.md)

View File

@@ -299,12 +299,35 @@ Manifest: [integrations/optimizer-artifact-manifest.md](integrations/optimizer-a
---
## Scheduled Agent Execution
Agents can run on a **regular cadence** against **preselected repos**, fired by
**activity-core** and prepared by kaizen-agentic (ADR-005). A repo opts in by
committing `.kaizen/schedule.yml`:
```bash
kaizen-agentic schedule init # scaffold (coach + optimization weekly)
kaizen-agentic schedule validate # check schema + agent names
kaizen-agentic schedule list # show enabled entries
kaizen-agentic schedule prepare coach # orientation bundle for a scheduled run
```
`schedule prepare <agent>` bundles the agent prompt, project memory, metrics
summary, and repo pointers — offline, no State Hub required. kaizen-agentic does
**not** run cron or invoke Claude; activity-core fires the schedule and a
coding-agent session executes the prepared bundle.
Schema: [integrations/schedule-schema.md](integrations/schedule-schema.md).
---
## Related Documents
- [ADR-001: Workplan Convention](adr/ADR-001-workplan-convention.md)
- [ADR-002: Project Memory Convention](adr/ADR-002-project-memory-convention.md)
- [ADR-003: Protocols Artifact Convention](adr/ADR-003-protocols-artifact-convention.md)
- [ADR-004: Project Metrics Convention](adr/ADR-004-project-metrics-convention.md)
- [ADR-005: Scheduled Agent Execution](adr/ADR-005-scheduled-agent-execution.md)
- [wiki/EcosystemIntegration.md](../wiki/EcosystemIntegration.md) — two-layer measurement model
- [WP-0002: Agency Framework](../workplans/kaizen-agentic-WP-0002-agency-framework.md)
- [WP-0003: Measurement Loop](../workplans/kaizen-agentic-WP-0003-measurement-loop.md)

View File

@@ -0,0 +1,17 @@
# Kaizen scheduled agent execution manifest (ADR-005)
# Declares which agents run on what cadence in this repo.
# Validate with: kaizen-agentic schedule validate
version: "1"
timezone: Europe/Berlin
agents:
coach:
cadence: weekly
cron: "0 9 * * 1" # Monday 09:00 — cross-agent orientation brief
enabled: true
optimization:
cadence: weekly
cron: "0 10 * * 1" # Monday 10:00 — agent performance review
enabled: true
tdd-workflow:
cadence: monthly
enabled: false # declared but paused; operator opts in deliberately

View File

@@ -0,0 +1,69 @@
# activity-core Handoff — Scheduled Agent Execution (WP-0006)
Coordination checklist for the **activity-core** team to enable kaizen scheduled
agent runs. kaizen-agentic owns the schedule contract, the prepare CLI, and the
ActivityDefinition **drafts**; activity-core owns the resolver, the schedule
firing, and task creation (repo boundary, ADR-005).
Open this as an activity-core issue/PR titled *"Enable kaizen scheduled agent
execution (WP-0006)"* and track the boxes there.
## What kaizen-agentic ships (done in this repo)
- [x] `.kaizen/schedule.yml` schema + `schedule validate|init|list|prepare` CLI
- [x] ADR-005 contract
- [x] Resolver spec: [discover-kaizen-scheduled-repos.md](discover-kaizen-scheduled-repos.md)
- [x] State Hub roster fields design: [state-hub-roster-fields.md](state-hub-roster-fields.md)
- [x] Draft definitions (`enabled: false`):
[weekly-coach-orientation](activity-definitions/weekly-coach-orientation.md),
[weekly-optimization-review](activity-definitions/weekly-optimization-review.md)
- [x] Event payload spec: [kaizen-schedule-prepared-event.md](kaizen-schedule-prepared-event.md)
## What activity-core must do
- [ ] **Implement resolver** `discover_kaizen_scheduled_repos` per the spec
(hub roster ∩ repos with valid `.kaizen/schedule.yml`).
- [ ] **Add resolver unit tests** using the four fixtures in the spec.
- [ ] **Copy definitions** from `docs/integrations/activity-definitions/`
(`weekly-coach-orientation.md`, `weekly-optimization-review.md`) into the
activity-core catalog path (per ACT-ADR-002).
- [ ] **Register** each definition slug in the activity-core index.
- [ ] **Run** `make sync-activity-definitions` in activity-core.
- [ ] **Wire cron** triggers (Mon 09:00 / 10:00 Europe/Berlin) to the resolver.
- [ ] **Smoke test** against a pilot repo (see below) with the definition still
`enabled: false` (dry-run task creation).
- [ ] **Enable gradually** — flip one definition to `enabled: true` in staging
after the smoke test passes.
- [ ] **Verify runner prerequisites**`kaizen-agentic` on PATH and the Gitea
PyPI extra index if the runner installs from registry (see
[PACKAGE_RELEASE.md](../PACKAGE_RELEASE.md)).
## State Hub team (the-custodian)
- [ ] Optional: add `kaizen_schedule_enabled` repo flag + `GET /repos/` filter
(v2 pre-filter; the repo file remains the source of truth).
## Smoke test (manual, runner-agnostic)
```bash
cd /path/to/pilot-repo
kaizen-agentic schedule init # if not already present
kaizen-agentic schedule validate # exit 0
kaizen-agentic schedule list # shows coach + optimization enabled
kaizen-agentic schedule prepare coach # non-empty orientation bundle
```
Then in activity-core: run the resolver (dry-run) and confirm one
`scheduled_run` per enabled `(repo, agent)` with a correct `prepare_command`.
## Pilot roster
- `kaizen-agentic` (dogfood)
- `the-custodian` (hub operator)
- one additional custodian-domain repo with `.kaizen/` state (TBD at pilot time)
## Related
- [ADR-005](../adr/ADR-005-scheduled-agent-execution.md)
- [INTEGRATION_PATTERNS.md Pattern 2](../INTEGRATION_PATTERNS.md)
- [KAIZEN-WP-0006](../../workplans/kaizen-agentic-WP-0006-scheduled-agent-execution.md)

View File

@@ -0,0 +1,55 @@
---
id: kaizen-weekly-coach-orientation
name: Weekly Kaizen Coach Orientation
enabled: false
owner: kaizen-agentic
governance: custodian
status: proposed
trigger:
type: cron
cron_expression: "0 9 * * 1"
timezone: Europe/Berlin
misfire_policy: skip
context_sources:
- type: resolver
query: discover_kaizen_scheduled_repos
params:
domain: custodian
cadence: weekly
bind_to: context.scheduled_runs
---
# Weekly Kaizen Coach Orientation
Every Monday 09:00 Berlin time, opens a coach orientation task for each
schedule-eligible repo whose `.kaizen/schedule.yml` enables the `coach` agent.
The resolver `discover_kaizen_scheduled_repos` (see
[discover-kaizen-scheduled-repos.md](../discover-kaizen-scheduled-repos.md))
returns one `scheduled_run` per `(repo, agent)`; this definition selects the
`coach` runs.
```rule
id: run-weekly-coach
for_each: context.scheduled_runs
bind_as: r
condition: 'r.agent == "coach" and r.enabled == true'
action:
task_template: "Weekly coach orientation: {{r.repo}}"
description: |
{{r.prepare_command}}
Then load agents/agent-coach.md in a coding-agent session, paste the
prepared bundle, and follow the coach synthesis. At session close:
kaizen-agentic metrics record coach --success --time <s> --quality <0-1>
target_repo: "{{r.repo}}"
priority: medium
labels: ["kaizen", "agent-run", "coach", "scheduled", "automated"]
```
**CLI mapping:** `kaizen-agentic schedule prepare coach` (offline-safe; reads
local `.kaizen/` state).
**Activation:** sync into activity-core via `make sync-activity-definitions`
after the `discover_kaizen_scheduled_repos` resolver is enabled. Keep
`enabled: false` until a manual smoke test passes on a pilot repo. See
[INTEGRATION_PATTERNS.md Pattern 2](../../INTEGRATION_PATTERNS.md).

View File

@@ -0,0 +1,55 @@
---
id: kaizen-weekly-optimization-review
name: Weekly Kaizen Optimization Review
enabled: false
owner: kaizen-agentic
governance: custodian
status: proposed
trigger:
type: cron
cron_expression: "0 10 * * 1"
timezone: Europe/Berlin
misfire_policy: skip
context_sources:
- type: resolver
query: discover_kaizen_scheduled_repos
params:
domain: custodian
cadence: weekly
bind_to: context.scheduled_runs
---
# Weekly Kaizen Optimization Review
Every Monday 10:00 Berlin time, opens an optimization-agent review task for each
schedule-eligible repo whose `.kaizen/schedule.yml` enables the `optimization`
agent. Chains the agent orientation with the existing metrics optimizer so the
review is evidence-backed.
```rule
id: run-weekly-optimization
for_each: context.scheduled_runs
bind_as: r
condition: 'r.agent == "optimization" and r.enabled == true'
action:
task_template: "Weekly optimization review: {{r.repo}}"
description: |
{{r.prepare_command}}
kaizen-agentic metrics optimize # refresh evidence
Then load agents/agent-optimization.md, paste the prepared bundle plus the
optimizer report, and act on recommendations. At session close:
kaizen-agentic metrics record optimization --success --time <s> --quality <0-1>
target_repo: "{{r.repo}}"
priority: medium
labels: ["kaizen", "agent-run", "optimization", "scheduled", "automated"]
```
**CLI mapping:** `kaizen-agentic schedule prepare optimization` then
`kaizen-agentic metrics optimize`.
**Complementarity:** this generalizes the metrics-only
[weekly-metrics-optimize](weekly-metrics-optimize.md) definition into a full
agent run. Repos may run either; running both duplicates the optimizer step.
**Activation:** sync into activity-core via `make sync-activity-definitions`
after the resolver is enabled; hold at `enabled: false` until smoke-tested.

View File

@@ -0,0 +1,109 @@
# Resolver Spec: `discover_kaizen_scheduled_repos`
**Status:** specification — **implemented in activity-core**, not here. This doc
is the contract an activity-core implementer needs to add the context resolver
that feeds the scheduled-agent ActivityDefinitions (ADR-005).
## Purpose
Given the fleet roster and per-repo schedule manifests, emit one entry per
`(repo, agent)` that is due to run, so ActivityDefinitions can `for_each` over
the result.
## Signature
```
discover_kaizen_scheduled_repos(
domain: str | None = None, # optional scope filter, e.g. "custodian"
cadence: str | None = None, # optional: "daily" | "weekly" | "monthly"
now: datetime | None = None, # injection point for testing
) -> { "scheduled_runs": list[ScheduledRun] }
```
Bound in a definition as:
```yaml
context_sources:
- type: resolver
query: discover_kaizen_scheduled_repos
params:
domain: custodian
cadence: weekly
bind_to: context.scheduled_runs
```
## Inputs (sources, in order)
1. **State Hub** `GET /repos/` (optionally filtered by `domain` and, when the v2
flag lands, `kaizen_schedule_enabled=true`). Yields `slug`, `host_paths`,
`domain`.
2. **Repo checkout** at `host_paths[<runner-host>]`: read
`.kaizen/schedule.yml`. Skip repos without the file.
3. **Validation**: run the equivalent of `kaizen-agentic schedule validate`.
Skip (and log) repos whose schedule is invalid — never emit a bad entry.
## Output shape
```json
{
"scheduled_runs": [
{
"repo": "kaizen-agentic",
"root": "/home/worsch/kaizen-agentic",
"agent": "coach",
"cadence": "weekly",
"cron": "0 9 * * 1",
"timezone": "Europe/Berlin",
"enabled": true,
"prepare_command": "kaizen-agentic schedule prepare coach --target /home/worsch/kaizen-agentic"
}
]
}
```
### `ScheduledRun` fields
| Field | Source | Notes |
|-------|--------|-------|
| `repo` | hub `slug` | becomes `target_repo` on the created task |
| `root` | `host_paths[<host>]` | absolute checkout path on the runner |
| `agent` | schedule.yml key | |
| `cadence` | schedule.yml | |
| `cron` | schedule.yml or definition default | per-repo override when present |
| `timezone` | schedule.yml or definition default | |
| `enabled` | schedule.yml (`true` only emitted) | disabled entries are filtered out |
| `prepare_command` | derived | exact CLI the task should run |
## Filtering rules
- Emit only entries with `enabled: true`.
- When `cadence` param is set, emit only matching entries (lets each cron-bound
definition select its own cadence slice).
- When `cron` is present on the entry, it is the authoritative per-repo time;
otherwise the definition's cron applies.
## Errors
| Condition | Behavior |
|-----------|----------|
| Repo unreachable / path missing on host | Skip + log `repo_unreachable` |
| `.kaizen/schedule.yml` absent | Skip silently (not opted in) |
| schedule.yml invalid | Skip + log `schedule_invalid` with validation errors |
| Hub unreachable | Fail the resolver run (no roster = no safe output) |
The resolver must be **idempotent** and **side-effect free**: it reads, it does
not write. Task creation happens in the ActivityDefinition rule, not here.
## Test fixtures
- A repo with valid `.kaizen/schedule.yml` (coach enabled) → one entry.
- A repo with the file but coach `enabled: false` → no entry.
- A repo without the file → no entry.
- A repo with an invalid schedule → no entry + logged error.
## Related
- [state-hub-roster-fields.md](state-hub-roster-fields.md)
- [schedule-schema.md](schedule-schema.md)
- [activity-definitions/weekly-coach-orientation.md](activity-definitions/weekly-coach-orientation.md)
- [ADR-005](../adr/ADR-005-scheduled-agent-execution.md)

View File

@@ -0,0 +1,90 @@
# Event Payload: `kaizen.schedule.prepared`
**Status:** design — for **future event-driven runs**. v1 of WP-0006 is
cron-driven (activity-core fires the schedule). This event lets a runner or
activity-core react when a `schedule prepare` bundle has been assembled, without
polling.
kaizen-agentic does **not** publish this event today; the `prepare` command
writes to stdout. This spec fixes the contract so an emitter (a runner wrapper
or a thin `--emit` flag in a later iteration) and consumers agree on the shape.
## Subject
```
kaizen.schedule.prepared
```
NATS/event-bus subject, sibling to the existing `kaizen.metrics.recorded` and
`kaizen.agent.installed` subjects (Pattern 2).
## Payload
```json
{
"event": "kaizen.schedule.prepared",
"version": "1",
"occurred_at": "2026-06-17T09:00:12Z",
"repo": "kaizen-agentic",
"root": "/home/worsch/kaizen-agentic",
"agent": "coach",
"cadence": "weekly",
"prepare_command": "kaizen-agentic schedule prepare coach --target /home/worsch/kaizen-agentic",
"bundle": {
"format": "markdown",
"agent_prompt_found": true,
"has_memory": true,
"has_metrics": true,
"pointers": ["scope", "todo"],
"bytes": 8421
},
"session_close": [
"kaizen-agentic metrics record coach --success --time <s> --quality <0-1>"
]
}
```
### Fields
| Field | Type | Notes |
|-------|------|-------|
| `event` | string | Always `kaizen.schedule.prepared` |
| `version` | string | Payload schema version |
| `occurred_at` | RFC3339 | When the bundle was assembled |
| `repo` | string | State Hub slug |
| `root` | string | Absolute checkout path |
| `agent` | string | Agent the bundle orients |
| `cadence` | string | `daily` \| `weekly` \| `monthly` |
| `prepare_command` | string | Exact CLI that produced the bundle |
| `bundle.format` | string | `markdown` \| `json` |
| `bundle.agent_prompt_found` | bool | Mirrors `schedule prepare --format json` |
| `bundle.has_memory` | bool | Memory file present |
| `bundle.has_metrics` | bool | Metrics summary present |
| `bundle.pointers` | string[] | Repo pointer labels found (`scope`, `todo`) |
| `bundle.bytes` | int | Rendered bundle size |
| `session_close` | string[] | Suggested close commands |
The `bundle.*` flags map 1:1 to the JSON output of
`kaizen-agentic schedule prepare <agent> --format json`, so an emitter can build
this payload from the existing command without new computation.
## Consumers (illustrative)
- **activity-core** — close the loop: mark the scheduled task `in_progress` when
a bundle is prepared.
- **artifact-store** — archive large bundles by reference.
- **dashboards** — fleet view of which scheduled runs have been prepared vs.
executed.
## Boundary
- The payload carries **metadata and a command**, never secrets or full repo
contents.
- kaizen-agentic owns the schema; emission wiring (NATS publish) is a future
iteration and belongs to the runner / activity-core integration.
## Related
- [discover-kaizen-scheduled-repos.md](discover-kaizen-scheduled-repos.md)
- [INTEGRATION_PATTERNS.md Pattern 2](../INTEGRATION_PATTERNS.md)
- [ADR-005](../adr/ADR-005-scheduled-agent-execution.md)

View File

@@ -0,0 +1,93 @@
# `.kaizen/schedule.yml` Schema
The schedule manifest declares which kaizen agents run on what cadence in an
opted-in repo. It is the repo-local half of the scheduled-agent-execution
contract (ADR-005). activity-core reads it (via the roster resolver) to fire
recurring tasks; `kaizen-agentic schedule prepare` reads it indirectly by
preparing per-agent orientation.
Canonical example: [`docs/examples/.kaizen/schedule.yml`](../examples/.kaizen/schedule.yml).
## Location
```
<project-root>/.kaizen/schedule.yml
```
Lives alongside `.kaizen/agents/` (memory) and `.kaizen/metrics/`. Like those,
its presence is the **opt-in signal** for fleet scheduling.
## Fields
| Key | Required | Type | Default | Notes |
|-----|----------|------|---------|-------|
| `version` | yes | string | — | Must be `"1"` |
| `timezone` | no | string | from ActivityDefinition | IANA tz, e.g. `Europe/Berlin` |
| `agents` | yes | mapping | — | `agent-name → settings` |
| `agents.<name>.cadence` | yes | enum | — | `daily` \| `weekly` \| `monthly` |
| `agents.<name>.cron` | no | string | cadence default | 5-field cron expression |
| `agents.<name>.enabled` | no | bool | `true` | Set `false` to declare but pause |
## Example
```yaml
version: "1"
timezone: Europe/Berlin
agents:
coach:
cadence: weekly
cron: "0 9 * * 1"
enabled: true
optimization:
cadence: weekly
cron: "0 10 * * 1"
enabled: true
tdd-workflow:
cadence: monthly
enabled: false
```
## Validation
```bash
kaizen-agentic schedule validate
```
Errors are emitted with actionable messages and a non-zero exit code:
- Missing or non-`"1"` `version`.
- `agents` not a mapping, or no agents declared.
- An agent name that is **not** installed or packaged (typo guard).
- A `cadence` outside `daily` / `weekly` / `monthly`.
- Duplicate agent entries.
Only agents available to the project (installed under `agents/` or packaged in
the distribution) may appear in a schedule.
## Scaffolding
```bash
kaizen-agentic schedule init # defaults: coach + optimization weekly
kaizen-agentic schedule init --timezone UTC # override timezone
kaizen-agentic schedule init --force # overwrite existing
```
The default scaffold enables `coach` and `optimization` weekly and declares
`tdd-workflow` monthly but **disabled** (operator opts in deliberately).
## Listing
```bash
kaizen-agentic schedule list # enabled entries only
kaizen-agentic schedule list --all # include disabled
```
## Relationship to activity-core
The `cron` field is an **optional per-repo override**. When omitted, the cadence
maps to the default cron declared in the matching ActivityDefinition (e.g.
`weekly-coach-orientation` fires Mon 09:00). This keeps fleet-wide timing in one
place while letting individual repos shift their slot.
See [ADR-005](../adr/ADR-005-scheduled-agent-execution.md) and
[INTEGRATION_PATTERNS.md Pattern 2](../INTEGRATION_PATTERNS.md).

View File

@@ -0,0 +1,64 @@
# State Hub Roster Fields for Kaizen Scheduling (Design)
**Status:** design only — implemented in `the-custodian/state-hub`, not here
(repo boundary). This document specifies what kaizen-agentic and activity-core
need from the hub so the State Hub team can add the fields and filter.
## Problem
activity-core's resolver needs to answer: *which registered repos participate in
kaizen fleet scheduling, and where do they live on disk?* Today state-hub knows
the canonical repo list and `host_paths` but has no notion of schedule opt-in.
## Existing hub data (sufficient for v1)
`GET /repos/` already returns, per repo:
| Field | Use |
|-------|-----|
| `slug` | Canonical repo identifier (`target_repo` in tasks) |
| `host_paths[hostname] → local_path` | Where the repo is checked out on a runner |
| `domain` | Scope filter (e.g. `custodian`) |
For **v1**, opt-in is detected **in the repo** (`.kaizen/schedule.yml` exists and
validates). The resolver clones/reads each candidate path and checks for the
file. No hub schema change is strictly required to ship the pilot.
## Proposed hub fields (v2, optional)
To let operators query eligibility **without touching every checkout**, add an
optional repo-metadata flag:
| Field | Type | Default | Meaning |
|-------|------|---------|---------|
| `kaizen_schedule_enabled` | bool | `false` | Operator-confirmed fleet participation |
| `kaizen_schedule_updated_at` | timestamp | null | Last time schedule.yml was synced/seen |
### Suggested filter
```
GET /repos/?kaizen_schedule_enabled=true&domain=custodian
```
Returns only schedule-eligible repos with their `host_paths`, so the resolver
skips repos that have not opted in — cheaper than scanning every checkout.
### Write path
The flag is set by an operator (or a future `kaizen-agentic schedule register`
that calls the hub). It is **advisory**: the authoritative opt-in remains the
presence of a valid `.kaizen/schedule.yml` in the repo, re-checked by the
resolver at run time. The flag is an index, not a source of truth.
## Boundary
- kaizen-agentic does **not** write these fields in WP-0006.
- state-hub schema migration is tracked in `the-custodian`.
- The resolver (activity-core) treats the hub flag as a pre-filter and the repo
file as the decision.
## Related
- [discover-kaizen-scheduled-repos.md](discover-kaizen-scheduled-repos.md)
- [schedule-schema.md](schedule-schema.md)
- [ADR-005](../adr/ADR-005-scheduled-agent-execution.md)

View File

@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
[project]
name = "kaizen-agentic"
version = "1.2.0"
version = "1.3.0"
description = "AI agent development framework embracing continuous improvement (kaizen)"
readme = "README.md"
license = {file = "LICENSE"}

View File

@@ -9,7 +9,7 @@ It also includes a comprehensive agent distribution system for sharing
specialized agents across projects via CLI tools and package management.
"""
__version__ = "1.2.0"
__version__ = "1.3.0"
__author__ = "Kaizen Agentic Team"
from .core import Agent, AgentConfig

View File

@@ -18,6 +18,13 @@ from .integrations.artifact_store import (
from .integrations.helix import HelixCorrelationAdapter, enrich_helix_correlation
from .metrics import MetricsStore, OptimizerStore, performance_summary_markdown
from .optimization import OptimizationLoop, MIN_SAMPLES_FOR_RECOMMENDATIONS
from .schedule import (
ScheduleError,
default_schedule_yaml,
load_schedule,
schedule_path,
validate_schedule,
)
def safe_cli_wrapper():
@@ -1360,6 +1367,204 @@ def protocols_show(agent_name: str, slug: str):
click.echo(protocol_path.read_text())
@cli.group()
def schedule():
"""Prepare and validate scheduled agent runs (.kaizen/schedule.yml, ADR-005).
kaizen-agentic does not run cron schedules or invoke Claude. activity-core
fires the cron and creates a task per (repo, agent); a coding-agent session
runs `schedule prepare <agent>` to assemble orientation, then executes the
agent instructions.
"""
pass
@schedule.command("validate")
@click.option("--target", "-t", default=".", help="Project root (default: current)")
def schedule_validate(target: str):
"""Validate .kaizen/schedule.yml against the ADR-005 schema."""
path = schedule_path(_project_root(target))
try:
parsed = load_schedule(path)
except ScheduleError as exc:
click.echo(f"{exc}", err=True)
click.echo(" Run: kaizen-agentic schedule init", err=True)
sys.exit(1)
known_agents = _get_registry().agent_names()
errors = validate_schedule(parsed, known_agents=known_agents)
if errors:
click.echo(f"❌ Schedule validation failed ({path}):")
for error in errors:
click.echo(f"{error}")
sys.exit(1)
enabled = parsed.enabled_entries()
click.echo(f"✅ Schedule valid: {path}")
click.echo(f" {len(parsed.entries)} agent(s), {len(enabled)} enabled")
@schedule.command("init")
@click.option("--target", "-t", default=".", help="Project root (default: current)")
@click.option(
"--timezone", default="Europe/Berlin", show_default=True, help="Schedule timezone"
)
@click.option("--force", is_flag=True, help="Overwrite an existing schedule.yml")
def schedule_init(target: str, timezone: str, force: bool):
"""Scaffold a default .kaizen/schedule.yml (coach + optimization weekly)."""
path = schedule_path(_project_root(target))
if path.exists() and not force:
click.echo(f"Schedule already exists: {path}")
click.echo(" Use --force to overwrite.")
return
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text(default_schedule_yaml(timezone=timezone), encoding="utf-8")
click.echo(f"Initialized schedule: {path}")
click.echo(" Validate with: kaizen-agentic schedule validate")
@schedule.command("list")
@click.option("--target", "-t", default=".", help="Project root (default: current)")
@click.option("--all", "show_all", is_flag=True, help="Include disabled entries")
def schedule_list(target: str, show_all: bool):
"""Show enabled schedule entries from .kaizen/schedule.yml."""
path = schedule_path(_project_root(target))
try:
parsed = load_schedule(path)
except ScheduleError as exc:
click.echo(f"No schedule found: {exc}")
click.echo(" Run: kaizen-agentic schedule init")
return
entries = parsed.entries if show_all else parsed.enabled_entries()
if not entries:
click.echo("No enabled schedule entries (use --all to see disabled).")
return
click.echo(f"Scheduled agents ({path}):")
if parsed.timezone:
click.echo(f" Timezone: {parsed.timezone}")
for entry in entries:
flag = "" if entry.enabled else ""
cron = f" cron={entry.cron}" if entry.cron else ""
click.echo(f" {flag} {entry.agent}: {entry.cadence}{cron}")
@schedule.command("prepare")
@click.argument("agent_name")
@click.option("--target", "-t", default=".", help="Project root (default: current)")
@click.option(
"--format",
"output_format",
type=click.Choice(["markdown", "json"]),
default="markdown",
show_default=True,
help="Output format for the orientation bundle",
)
def schedule_prepare(agent_name: str, target: str, output_format: str):
"""Assemble an orientation bundle for a scheduled agent run.
Bundles the agent prompt, project memory, metrics summary, and repo
pointers into a single payload. Works offline from local `.kaizen/` state;
no State Hub required. Pass the output to a coding-agent session.
"""
bundle = _build_prepare_bundle(agent_name, _project_root(target))
if output_format == "json":
click.echo(json.dumps(bundle, indent=2))
return
click.echo(_render_prepare_markdown(bundle))
def _build_prepare_bundle(agent_name: str, project_root: Path) -> dict:
"""Collect the orientation bundle pieces for `schedule prepare`."""
registry = _get_registry()
agent_path = registry.get_agent_path(agent_name)
agent_prompt = agent_path.read_text(encoding="utf-8") if agent_path else None
memory_path = project_root / ".kaizen" / "agents" / agent_name / "memory.md"
memory = memory_path.read_text(encoding="utf-8") if memory_path.exists() else None
metrics_store = MetricsStore(project_root, agent_name)
metrics_summary = metrics_store.read_summary()
if metrics_summary is None and metrics_store.executions_path.exists():
metrics_summary = metrics_store.write_summary()
pointers = {}
for label, filename in (("scope", "SCOPE.md"), ("todo", "TODO.md")):
candidate = project_root / filename
if candidate.exists():
pointers[label] = str(candidate)
return {
"agent": agent_name,
"project": project_root.name,
"generated": _today(),
"agent_prompt": agent_prompt,
"agent_prompt_found": agent_prompt is not None,
"memory": memory,
"metrics_summary": metrics_summary,
"pointers": pointers,
"session_close": [
f"kaizen-agentic metrics record {agent_name} --success "
f"--time <seconds> --quality <0-1>",
f"Update memory: kaizen-agentic memory show {agent_name}",
],
}
def _render_prepare_markdown(bundle: dict) -> str:
agent = bundle["agent"]
lines = [
f"# Scheduled Run Orientation: {agent}",
f"Project: {bundle['project']}",
f"Generated: {bundle['generated']}",
"",
]
summary = bundle.get("metrics_summary")
block = performance_summary_markdown(summary or {})
if block:
lines.append(block)
lines.append("## Agent Prompt")
if bundle["agent_prompt_found"]:
lines.append(bundle["agent_prompt"])
else:
lines.append(
f"(agent '{agent}' not found in registry — " f"run: kaizen-agentic list)"
)
lines.append("")
lines.append("## Project Memory")
if bundle.get("memory"):
lines.append(bundle["memory"])
else:
lines.append(f"(none — run: kaizen-agentic memory init {agent})")
lines.append("")
pointers = bundle.get("pointers") or {}
lines.append("## Repo Pointers")
if pointers:
for label, path in pointers.items():
lines.append(f"- {label}: {path}")
else:
lines.append("- (no SCOPE.md / TODO.md found)")
lines.append("")
lines.append("## Session Close")
for cmd in bundle["session_close"]:
lines.append(f"- `{cmd}`")
return "\n".join(lines)
def _project_root(target: str) -> Path:
return Path(target).resolve()

View File

@@ -0,0 +1,185 @@
"""Repo-local scheduled agent execution manifest (.kaizen/schedule.yml).
ADR-005 defines the schedule contract: which agents run on what cadence in an
opted-in repo. kaizen-agentic owns parsing, validation, and preparing an
orientation bundle for a scheduled run. It does **not** run cron schedules or
invoke Claude — activity-core fires the cron and a coding-agent session executes
the prepared bundle.
"""
from __future__ import annotations
from dataclasses import dataclass, field
from pathlib import Path
from typing import Any, Dict, List, Optional
import yaml
SCHEDULE_RELATIVE_PATH = Path(".kaizen") / "schedule.yml"
SCHEDULE_VERSION = "1"
VALID_CADENCES = ("daily", "weekly", "monthly")
# Sensible defaults for `schedule init` — coach + optimization weekly, the
# heavier tdd-workflow review monthly and disabled until an operator opts in.
DEFAULT_AGENTS: Dict[str, Dict[str, Any]] = {
"coach": {"cadence": "weekly", "cron": "0 9 * * 1", "enabled": True},
"optimization": {"cadence": "weekly", "cron": "0 10 * * 1", "enabled": True},
"tdd-workflow": {"cadence": "monthly", "enabled": False},
}
DEFAULT_TIMEZONE = "Europe/Berlin"
class ScheduleError(Exception):
"""Raised when a schedule manifest cannot be parsed."""
@dataclass
class ScheduleEntry:
"""One scheduled agent run declaration."""
agent: str
cadence: str
enabled: bool = True
cron: Optional[str] = None
def to_dict(self) -> Dict[str, Any]:
data: Dict[str, Any] = {"cadence": self.cadence, "enabled": self.enabled}
if self.cron:
data["cron"] = self.cron
return data
@dataclass
class Schedule:
"""Parsed `.kaizen/schedule.yml` manifest."""
version: str
timezone: Optional[str] = None
entries: List[ScheduleEntry] = field(default_factory=list)
source_path: Optional[Path] = None
def entry_for(self, agent: str) -> Optional[ScheduleEntry]:
for entry in self.entries:
if entry.agent == agent:
return entry
return None
def enabled_entries(self) -> List[ScheduleEntry]:
return [e for e in self.entries if e.enabled]
def schedule_path(project_root: Path) -> Path:
"""Return the canonical schedule.yml path for a project root."""
return Path(project_root) / SCHEDULE_RELATIVE_PATH
def parse_schedule(data: Any, source_path: Optional[Path] = None) -> Schedule:
"""Parse a raw mapping into a Schedule (structural errors raise).
Semantic validation (known agents, cadence values) is handled by
:func:`validate_schedule` so callers can collect actionable error lists.
"""
if not isinstance(data, dict):
raise ScheduleError("schedule.yml must be a YAML mapping at the top level")
version = data.get("version")
if version is None:
raise ScheduleError("schedule.yml is missing required key: version")
version = str(version)
timezone = data.get("timezone")
if timezone is not None and not isinstance(timezone, str):
raise ScheduleError("timezone must be a string")
agents = data.get("agents", {})
if not isinstance(agents, dict):
raise ScheduleError("agents must be a mapping of agent-name -> settings")
entries: List[ScheduleEntry] = []
for name, settings in agents.items():
if settings is None:
settings = {}
if not isinstance(settings, dict):
raise ScheduleError(f"agent '{name}' settings must be a mapping")
cron = settings.get("cron")
if cron is not None and not isinstance(cron, str):
raise ScheduleError(f"agent '{name}' cron must be a string")
entries.append(
ScheduleEntry(
agent=str(name),
cadence=str(settings.get("cadence", "")),
enabled=bool(settings.get("enabled", True)),
cron=cron,
)
)
return Schedule(
version=version,
timezone=timezone,
entries=entries,
source_path=source_path,
)
def load_schedule(path: Path) -> Schedule:
"""Load and parse a schedule.yml file (raises ScheduleError)."""
path = Path(path)
if not path.exists():
raise ScheduleError(f"schedule file not found: {path}")
try:
raw = yaml.safe_load(path.read_text(encoding="utf-8"))
except yaml.YAMLError as exc: # pragma: no cover - passthrough message
raise ScheduleError(f"invalid YAML in {path}: {exc}") from exc
return parse_schedule(raw, source_path=path)
def validate_schedule(
schedule: Schedule, known_agents: Optional[List[str]] = None
) -> List[str]:
"""Return a list of human-readable validation errors (empty == valid)."""
errors: List[str] = []
if schedule.version != SCHEDULE_VERSION:
errors.append(
f"unsupported version '{schedule.version}' "
f"(expected '{SCHEDULE_VERSION}')"
)
if not schedule.entries:
errors.append("no agents declared under 'agents:'")
seen: set = set()
known = set(known_agents) if known_agents is not None else None
for entry in schedule.entries:
if entry.agent in seen:
errors.append(f"duplicate agent entry: {entry.agent}")
seen.add(entry.agent)
if entry.cadence not in VALID_CADENCES:
errors.append(
f"agent '{entry.agent}': invalid cadence '{entry.cadence}' "
f"(expected one of {', '.join(VALID_CADENCES)})"
)
if known is not None and entry.agent not in known:
errors.append(
f"agent '{entry.agent}' is not an installed or packaged agent"
)
return errors
def default_schedule_yaml(timezone: str = DEFAULT_TIMEZONE) -> str:
"""Render the default schedule.yml scaffold for `schedule init`."""
document = {
"version": SCHEDULE_VERSION,
"timezone": timezone,
"agents": dict(DEFAULT_AGENTS),
}
header = (
"# Kaizen scheduled agent execution manifest (ADR-005)\n"
"# Declares which agents run on what cadence in this repo.\n"
"# Validate with: kaizen-agentic schedule validate\n"
)
body = yaml.safe_dump(document, sort_keys=False, default_flow_style=False)
return header + body

View File

@@ -13,7 +13,8 @@ DEFINITIONS_DIR = (
def test_activity_definitions_have_required_frontmatter():
files = list(DEFINITIONS_DIR.glob("*.md"))
assert len(files) == 3
# 3 from WP-0004 (metrics) + 2 from WP-0006 (scheduled agent runs)
assert len(files) == 5
for path in files:
text = path.read_text(encoding="utf-8")

166
tests/test_schedule_cli.py Normal file
View File

@@ -0,0 +1,166 @@
"""CLI + module tests for scheduled agent execution (ADR-005, WP-0006)."""
from __future__ import annotations
import json
from pathlib import Path
import pytest
from click.testing import CliRunner
from kaizen_agentic.cli import cli
from kaizen_agentic.schedule import (
ScheduleError,
parse_schedule,
schedule_path,
validate_schedule,
)
@pytest.fixture
def runner() -> CliRunner:
return CliRunner()
@pytest.fixture
def project_dir(tmp_path: Path) -> Path:
root = tmp_path / "demo-project"
root.mkdir()
return root
class TestScheduleModule:
def test_parse_requires_version(self):
with pytest.raises(ScheduleError):
parse_schedule({"agents": {}})
def test_parse_rejects_non_mapping(self):
with pytest.raises(ScheduleError):
parse_schedule(["not", "a", "mapping"])
def test_validate_flags_unknown_agent_and_bad_cadence(self):
schedule = parse_schedule(
{
"version": "1",
"agents": {
"coach": {"cadence": "weekly", "enabled": True},
"made-up": {"cadence": "hourly"},
},
}
)
errors = validate_schedule(schedule, known_agents=["coach", "optimization"])
assert any("hourly" in e for e in errors)
assert any("made-up" in e for e in errors)
def test_validate_clean_schedule(self):
schedule = parse_schedule(
{"version": "1", "agents": {"coach": {"cadence": "weekly"}}}
)
assert validate_schedule(schedule, known_agents=["coach"]) == []
class TestScheduleCli:
def test_init_creates_default_schedule(self, runner: CliRunner, project_dir: Path):
result = runner.invoke(cli, ["schedule", "init", "--target", str(project_dir)])
assert result.exit_code == 0
path = schedule_path(project_dir)
assert path.exists()
assert "coach" in path.read_text()
def test_init_no_overwrite_without_force(
self, runner: CliRunner, project_dir: Path
):
runner.invoke(cli, ["schedule", "init", "--target", str(project_dir)])
result = runner.invoke(cli, ["schedule", "init", "--target", str(project_dir)])
assert result.exit_code == 0
assert "already exists" in result.output
def test_validate_passes_on_default(self, runner: CliRunner, project_dir: Path):
runner.invoke(cli, ["schedule", "init", "--target", str(project_dir)])
result = runner.invoke(
cli, ["schedule", "validate", "--target", str(project_dir)]
)
assert result.exit_code == 0
assert "valid" in result.output
def test_validate_missing_file_errors(self, runner: CliRunner, project_dir: Path):
result = runner.invoke(
cli, ["schedule", "validate", "--target", str(project_dir)]
)
assert result.exit_code == 1
def test_validate_rejects_bad_schema(self, runner: CliRunner, project_dir: Path):
path = schedule_path(project_dir)
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text("version: '1'\nagents:\n not-an-agent:\n cadence: weekly\n")
result = runner.invoke(
cli, ["schedule", "validate", "--target", str(project_dir)]
)
assert result.exit_code == 1
assert "not-an-agent" in result.output
def test_list_shows_enabled(self, runner: CliRunner, project_dir: Path):
runner.invoke(cli, ["schedule", "init", "--target", str(project_dir)])
result = runner.invoke(cli, ["schedule", "list", "--target", str(project_dir)])
assert result.exit_code == 0
assert "coach" in result.output
# tdd-workflow is disabled by default; hidden without --all
assert "tdd-workflow" not in result.output
def test_list_all_shows_disabled(self, runner: CliRunner, project_dir: Path):
runner.invoke(cli, ["schedule", "init", "--target", str(project_dir)])
result = runner.invoke(
cli, ["schedule", "list", "--all", "--target", str(project_dir)]
)
assert "tdd-workflow" in result.output
def test_prepare_markdown_includes_agent_prompt(
self, runner: CliRunner, project_dir: Path
):
result = runner.invoke(
cli, ["schedule", "prepare", "coach", "--target", str(project_dir)]
)
assert result.exit_code == 0
assert "Scheduled Run Orientation: coach" in result.output
assert "## Agent Prompt" in result.output
assert "Coach Agent" in result.output
assert "## Session Close" in result.output
def test_prepare_json_format(self, runner: CliRunner, project_dir: Path):
result = runner.invoke(
cli,
[
"schedule",
"prepare",
"coach",
"--target",
str(project_dir),
"--format",
"json",
],
)
assert result.exit_code == 0
payload = json.loads(result.output)
assert payload["agent"] == "coach"
assert payload["agent_prompt_found"] is True
assert payload["session_close"]
def test_prepare_unknown_agent_notes_missing(
self, runner: CliRunner, project_dir: Path
):
result = runner.invoke(
cli,
["schedule", "prepare", "no-such-agent", "--target", str(project_dir)],
)
assert result.exit_code == 0
assert "not found in registry" in result.output
def test_prepare_includes_memory_when_present(
self, runner: CliRunner, project_dir: Path
):
runner.invoke(cli, ["memory", "init", "coach", "--target", str(project_dir)])
result = runner.invoke(
cli, ["schedule", "prepare", "coach", "--target", str(project_dir)]
)
assert "## Project Memory" in result.output
assert "Project Context" in result.output

View File

@@ -96,7 +96,20 @@ ActivityDefinition reference copies (sync into activity-core to activate):
- [post-install-metrics-scaffold](../docs/integrations/activity-definitions/post-install-metrics-scaffold.md)
- [low-success-rate-review](../docs/integrations/activity-definitions/low-success-rate-review.md)
**Workplan:** KAIZEN-WP-0004 Part 2. Patterns: [docs/INTEGRATION_PATTERNS.md](../docs/INTEGRATION_PATTERNS.md).
**Scheduled agent execution (WP-0006, ADR-005)** — run agents (not just the
metrics optimizer) on a cadence against a preselected repo roster:
- [weekly-coach-orientation](../docs/integrations/activity-definitions/weekly-coach-orientation.md)
- [weekly-optimization-review](../docs/integrations/activity-definitions/weekly-optimization-review.md)
- Resolver spec: [discover-kaizen-scheduled-repos](../docs/integrations/discover-kaizen-scheduled-repos.md)
- Roster fields: [state-hub-roster-fields](../docs/integrations/state-hub-roster-fields.md)
- Handoff checklist: [activity-core-handoff-wp0006](../docs/integrations/activity-core-handoff-wp0006.md)
A repo opts in by committing `.kaizen/schedule.yml` (`kaizen-agentic schedule
init`); activity-core fires the cron and creates a task per `(repo, agent)` that
runs `kaizen-agentic schedule prepare <agent>`.
**Workplan:** KAIZEN-WP-0004 Part 2 + KAIZEN-WP-0006. Patterns: [docs/INTEGRATION_PATTERNS.md](../docs/INTEGRATION_PATTERNS.md).
### artifact-store (P1)
@@ -194,4 +207,4 @@ WP-0001 T04. Assess before depending on it.
Persisted in `history/`:
- `2026-06-16-intent-gap-analysis.md`
- `2026-06-16-ecosystem-assessment.md`
- `2026-06-16-ecosystem-assessment.md`

View File

@@ -9,7 +9,104 @@ owner: kaizen-agentic
topic_slug: custodian
state_hub_workstream_id: 36252a45-f360-4496-bf77-17b5dfb02767
created: "2026-06-16"
updated: "2026-06-18"
updated: "2026-06-17"
tasks:
- id: T01
title: Write ADR-004 project metrics convention
status: done
state_hub_task_id: 4e7b0fd2-38c0-46aa-84a7-bb18366b8c7c
- id: T02
title: Implement MetricsStore in metrics.py
status: done
state_hub_task_id: eeaa99c7-d7a7-403b-a013-364cba45a663
- id: T03
title: Add memory init hook to scaffold metrics directory
status: done
state_hub_task_id: 247c097f-de89-4383-930c-35ee66de9b36
- id: T04
title: Unit tests for MetricsStore
status: done
state_hub_task_id: 3aa14026-6ee3-4384-b409-11300c1302f0
- id: T05
title: Implement metrics CLI command group
status: done
state_hub_task_id: 6b505d29-7d2e-44a2-a4b7-1fe82884390c
- id: T06
title: Integrate metrics record into session-close template
status: done
state_hub_task_id: 84f2a357-f2dd-4fc7-96b6-a4e80d5467a7
- id: T07
title: CLI tests for metrics commands
status: done
state_hub_task_id: 8e9ee64b-b7c4-4dff-ac6e-988fd47ef95d
- id: T08
title: Update CLI cheat sheet and agency-framework with metrics
status: done
state_hub_task_id: 4c41e0db-d5d8-4a1b-b346-06ad004edf4a
- id: T09
title: Add OptimizationLoop.from_metrics_store factory
status: done
state_hub_task_id: 0b374439-6eca-4754-8e15-2a7eece0cd27
- id: T10
title: Implement kaizen-agentic metrics optimize command
status: done
state_hub_task_id: db87a09b-0252-495c-a771-a43b4b98f820
- id: T11
title: Consolidate optimization meta-agent definitions
status: done
state_hub_task_id: 73cb7d73-6fc6-42a9-97aa-d33cdf9ee363
- id: T12
title: Update optimization agent session protocol
status: done
state_hub_task_id: c127eca7-7394-42db-ba5e-721aef0ccb76
- id: T13
title: Unit and integration tests for optimizer recommendations
status: done
state_hub_task_id: f208dc9f-cdf7-47e3-9c03-09097e46eee9
- id: T14
title: Extend memory brief with metrics summary
status: done
state_hub_task_id: d01f969c-bbb1-4eca-a4f1-d79d5c867b35
- id: T15
title: Extend agent-coach.md for metrics context
status: done
state_hub_task_id: 67f791a4-fced-4986-a331-7eb4ea47fe6e
- id: T16
title: E2e test memory brief with metrics sections
status: done
state_hub_task_id: 1fb89b54-8bd2-40bf-9a71-04693cb9f695
- id: T17
title: Add metrics section to agent-tdd-workflow.md
status: done
state_hub_task_id: 1d471a7a-9a98-4805-903e-b4a2b8153717
- id: T18
title: Add session-close metrics record step to tdd-workflow
status: done
state_hub_task_id: abb387f1-86ce-4b9b-a516-2d4efb6aca4c
- id: T19
title: Document tdd-workflow pilot in wiki/AboutKaizenAgents.md
status: done
state_hub_task_id: 67fbc26e-a57d-4133-96e6-3d2cdbd10dc0
- id: T20
title: E2e test full tdd-workflow measure-analyse-orient loop
status: done
state_hub_task_id: fbdd7c8b-e122-48d9-8c8f-de9f82d025e3
- id: T21
title: Sync 4 missing agents into packaged data/
status: done
state_hub_task_id: 9662bcec-34fe-451b-b61f-5d11b9574576
- id: T22
title: Update README orientation links to INTENT and wiki
status: done
state_hub_task_id: 422aae43-5697-4a00-86e9-1569baf09422
- id: T23
title: Update architecture.md agent table
status: done
state_hub_task_id: ba6b3411-d330-4a58-8cd0-62b4fbef8c5f
- id: T24
title: CHANGELOG entry for metrics convention and CLI
status: done
state_hub_task_id: 748be9f3-f6ac-4f26-a844-6330268935b6
---
# KAIZEN-WP-0003 — Measurement Loop: Metrics Convention, Collection, and Optimizer Integration
@@ -249,6 +346,23 @@ A reader of `INTENT.md` can point to this repo and say:
---
## Completion
**Shipped:** v1.1.0 (2026-06-18); measurement loop operational through v1.2.0.
| Milestone | Detail |
|-----------|--------|
| ADR-004 | Project metrics convention (`.kaizen/metrics/`) |
| CLI | `metrics record`, `show`, `list`, `export`, `optimize` |
| Coach bridge | `memory brief` includes `## Performance Summary` |
| Pilot | `tdd-workflow` reference in `wiki/AboutKaizenAgents.md` |
| Tests | `test_metrics*.py`, `test_optimization_metrics.py`, e2e agency tests pass |
All 24 tasks complete. Fleet-wide template conformance and scheduled optimizer runs
remain out of scope (future workplans).
---
## State Hub Task IDs
| Code | UUID |
@@ -286,4 +400,4 @@ A reader of `INTENT.md` can point to this repo and say:
- Retention default: 180 days (per `wiki/AgentKaizenOptimizer.md`); override via project config in a later iteration
- WP-0001 T04 (telemetry) should consume ADR-004 schema rather than inventing a parallel format
- `OptimizationLoop` threshold constants (30s execution, 0.8 success rate) are starting points; expose in config later
- `OptimizationLoop` threshold constants (30s execution, 0.8 success rate) are starting points; expose in config later

View File

@@ -9,7 +9,84 @@ owner: kaizen-agentic
topic_slug: custodian
state_hub_workstream_id: 76be7294-e201-4074-91c0-6421992470fe
created: "2026-06-16"
updated: "2026-06-18"
updated: "2026-06-17"
tasks:
- id: T01
title: Document Helix Forge correlation contract cross-repo
status: done
state_hub_task_id: f365d19e-9619-4453-bebf-f1fd596b1bd1
- id: T02
title: Add HELIX_SESSION_UID to metrics record
status: done
state_hub_task_id: e7f47683-5957-49db-bcbd-3aa47f44a073
- id: T03
title: Add kaizen-agentic metrics correlate command stub
status: done
state_hub_task_id: 6ef8ba99-7d0c-44f4-835d-7a66e9d55984
- id: T04
title: Integration test for helix_session_uid correlation
status: done
state_hub_task_id: 9875422c-a54b-40f1-a444-6b485a9e57d6
- id: T05
title: Update EcosystemIntegration.md with worked example
status: done
state_hub_task_id: 0dc33d13-0e0b-4336-a7ad-371fc533b823
- id: T06
title: Draft weekly metrics optimize ActivityDefinition
status: done
state_hub_task_id: dbaa5f46-f66a-4a74-b4a0-97978e47d1c3
- id: T07
title: Draft post-install metrics scaffold ActivityDefinition
status: done
state_hub_task_id: 161a264a-8f70-4e37-a854-bd5a76a0e54b
- id: T08
title: Draft low success_rate review ActivityDefinition
status: done
state_hub_task_id: 3b58ad38-839c-436a-8d97-ef5a8f9beefe
- id: T09
title: Document activity-core triggers in INTEGRATION_PATTERNS.md
status: done
state_hub_task_id: a004b60f-4e8f-4881-b088-229ac9ab242f
- id: T10
title: Smoke test activity-core activation
status: done
state_hub_task_id: 84866bf1-5830-470d-87a5-9786222332c2
- id: T11
title: Define optimizer artifact package manifest
status: done
state_hub_task_id: 033a19db-fbd2-411f-9d2e-779d210400d4
- id: T12
title: Add kaizen-agentic metrics publish command
status: done
state_hub_task_id: 54517f2b-23e3-433b-a483-c59227625dbc
- id: T13
title: Map raw-evidence retention class in publish manifest
status: done
state_hub_task_id: 3b378789-a761-4472-b072-a346541be239
- id: T14
title: Integration test artifact-store publish
status: done
state_hub_task_id: a3566713-db58-4519-b9c4-5003421c1f1e
- id: T15
title: Document publish workflow in agency-framework.md
status: done
state_hub_task_id: 5d8255aa-fd7a-4fe6-bce2-3a176f954c7f
- id: T16
title: Map KaizenAgentTemplate to info-tech-canon profile outline
status: done
state_hub_task_id: 852c9cbf-0b0c-4f23-8594-905ca280c268
- id: T17
title: Draft info-tech-canon agent brief for tdd-workflow
status: done
state_hub_task_id: 62e05097-9033-401d-bbe0-d5d773da50fe
- id: T18
title: Spike kontextual-engine wiki ingestion manifest
status: done
state_hub_task_id: cd6962c7-aaed-4d7d-81de-37c0e3ed715e
- id: T19
title: Update ecosystem assessment with Part 4 outcomes
status: done
state_hub_task_id: 2c1f66f5-e6ab-4e19-88ca-818acb15a706
---
# KAIZEN-WP-0004 — Ecosystem Integration: Helix Forge, activity-core, and artifact-store
@@ -154,6 +231,21 @@ Estimated effort: 35 sessions after WP-0003 Part 3.
---
## Completion
**Shipped:** v1.1.0v1.2.0 ecosystem integration layer.
| Part | Outcome |
|------|---------|
| 1 Helix | `HELIX_SESSION_UID` on `metrics record`, `metrics correlate`, bidirectional docs |
| 2 activity-core | Three ActivityDefinitions under `docs/integrations/activity-definitions/` |
| 3 artifact-store | `metrics publish` with `raw-evidence` retention manifest |
| 4 Canon/knowledge | Design docs for info-tech-canon and kontextual-engine (no runtime deps) |
All 19 tasks complete. Reciprocal Helix link verified in WP-0005 T16.
---
## State Hub Task IDs
| Code | UUID |
@@ -187,4 +279,4 @@ Estimated effort: 35 sessions after WP-0003 Part 3.
- ADR-004 Helix Forge correlation section is the authoritative field mapping
- WP-0001 T04 (telemetry) should evaluate tele-mcp as adapter candidate
- activity-core ActivityDefinitions live in activity-core repo per ACT-ADR-002/003;
kaizen-agentic commits reference copies or links under `docs/integrations/`
kaizen-agentic commits reference copies or links under `docs/integrations/`

View File

@@ -9,7 +9,72 @@ owner: kaizen-agentic
topic_slug: custodian
state_hub_workstream_id: 88c7b3e6-be98-480c-b47b-936e74a1a31b
created: "2026-06-16"
updated: "2026-06-16"
updated: "2026-06-17"
tasks:
- id: T01
title: Configure PACKAGE_USER and PACKAGE_TOKEN in Gitea
status: done
state_hub_task_id: 1fb6b04e-0854-4cc9-83c7-5abf85fe5bff
- id: T02
title: Smoke-test publish-python-package workflow
status: done
state_hub_task_id: bdb9e463-bdfb-405c-afc4-e93a7d58a18b
- id: T03
title: Add pre-tag release checklist to PACKAGE_RELEASE.md
status: done
state_hub_task_id: 6a2132e7-8b3f-4960-a5e8-85bad81e8b13
- id: T04
title: Update HELLO_WORLD_TUTORIAL.md Gitea install paths
status: done
state_hub_task_id: 553cba3a-dafa-483a-9200-70ac3f5eb2d7
- id: T05
title: Update CLI_CHEAT_SHEET.md Gitea install paths
status: done
state_hub_task_id: 7e6663a5-fedf-4b1c-acd9-6df6b43d8a12
- id: T06
title: Update AGENT_DISTRIBUTION.md Gitea install paths
status: done
state_hub_task_id: fe553788-357f-45c4-8400-f764f68c1cde
- id: T07
title: Update Makefile agents-* install fallback messages
status: done
state_hub_task_id: b131ff67-fe21-4d95-904b-6a0b916c5502
- id: T08
title: Cross-link CONTRIBUTING.md with PACKAGE_RELEASE.md
status: done
state_hub_task_id: 07dd4d25-250c-455c-8363-49269d2ee59f
- id: T09
title: Add make agents-sync-package target
status: done
state_hub_task_id: 7437cedd-5f7e-4c4d-9142-4f67470c9e52
- id: T10
title: Add release-check parity test agents vs data/agents
status: done
state_hub_task_id: ddbe2114-7a47-48fd-a145-b22dca2b581a
- id: T11
title: Refresh SCOPE.md agent-count notes
status: done
state_hub_task_id: 5417524f-03c0-40ed-a48b-a7906e6daf8f
- id: T12
title: Refresh TODO.md for v1.2.0
status: done
state_hub_task_id: 5cfad56c-2664-4b2d-b5f9-4792c958c9a2
- id: T13
title: Open CHANGELOG Unreleased for v1.2.0
status: done
state_hub_task_id: fbca9be4-3d2b-4989-baaf-97e6926bdc66
- id: T14
title: Add flake8 to Gitea CI workflow
status: done
state_hub_task_id: a6966cfa-ca59-4087-8989-2870dc69b13f
- id: T15
title: Document activity-core ActivityDefinition registration handoff
status: done
state_hub_task_id: fbf3f1a8-4818-473e-ae0d-cd80118e5319
- id: T16
title: Verify bidirectional Helix correlation doc link
status: done
state_hub_task_id: 37679ce7-dcb6-42a4-820d-cf8b32c2a248
---
# KAIZEN-WP-0005 — Adoption Polish and Fleet Parity
@@ -154,6 +219,23 @@ Estimated effort: 24 sessions.
---
## Completion
**Shipped:** v1.2.0 on 2026-06-16
| Milestone | Detail |
|-----------|--------|
| Release commit | `297afed` — adoption polish and publish pipeline |
| Tag | `v1.2.0` pushed to Gitea |
| Publish | Gitea Actions run **3044**`kaizen_agentic-1.2.0` wheel + sdist uploaded |
| Publish auth | `PACKAGE_USER=tegwick`, token from OpenBao `inter-hub-pkg-rep` |
| Helix handoff | Reciprocal link in `agentic-resources/docs/DESIGN-session-memory.md` §11 |
All 16 tasks complete. Deferred items (agent wizard, template validation, doc generation)
tracked for **WP-0006** (v1.3.0).
---
## State Hub Task IDs
| Code | UUID |

View File

@@ -0,0 +1,368 @@
---
id: KAIZEN-WP-0006
type: workplan
title: "Scheduled Agent Execution via activity-core (v1.3.0)"
domain: custodian
repo: kaizen-agentic
status: done
owner: kaizen-agentic
topic_slug: custodian
state_hub_workstream_id: d4edb92b-526f-4ee4-8efe-a9fa84ab6dff
depends_on:
- KAIZEN-WP-0003
- KAIZEN-WP-0004
created: "2026-06-17"
updated: "2026-06-17"
tasks:
- id: T01
state_hub_task_id: f513cf74-6e32-4dce-a3bc-2995f98a30de
status: done
title: Write ADR-005 scheduled agent execution contract
- id: T02
state_hub_task_id: dcb8d674-5472-4657-85bc-02ca9890fb92
status: done
title: Define .kaizen/schedule.yml schema and example
- id: T03
state_hub_task_id: 1f9a4959-d200-4d7b-8666-96472e23d820
status: done
title: Add kaizen-agentic schedule validate command
- id: T04
state_hub_task_id: 13ab4b76-ded2-4613-b8e2-15ab206d8c57
status: done
title: Document fleet roster and repo opt-in in INTEGRATION_PATTERNS
- id: T05
state_hub_task_id: 685b35f3-af20-483a-9136-150f5fff68dd
status: done
title: Draft state-hub roster query design for activity-core resolver
- id: T06
state_hub_task_id: 5f0a0859-3ff5-4ec8-b916-35486f045b2b
status: done
title: Draft discover_kaizen_scheduled_repos context resolver spec
- id: T07
state_hub_task_id: 2fd0f00c-5cf1-47bd-9c12-aee65bca5932
status: done
title: Draft weekly-agent-run ActivityDefinition template
- id: T08
state_hub_task_id: cc0565bc-ccd4-4739-9c7e-088adaa9834b
status: done
title: Open activity-core handoff issue for resolver and definitions
- id: T09
state_hub_task_id: 23aeff77-3429-438b-a395-5c7b5dc2824e
status: done
title: Implement kaizen-agentic schedule prepare command
- id: T10
state_hub_task_id: cba9685b-408f-4292-8169-9965e7ad5c5b
status: done
title: Bundle memory brief metrics and agent prompt in prepare output
- id: T11
state_hub_task_id: 7c1b049b-5566-4b5e-9d82-d9c29fab0c84
status: done
title: Add schedule init scaffold for new repos
- id: T12
state_hub_task_id: 80a8e98a-9146-4a58-8fd3-8c37f7893960
status: done
title: Unit tests for schedule validate and prepare
- id: T13
state_hub_task_id: 9aee6348-d5ad-4413-b01c-5588b07c8ede
status: done
title: Pilot ActivityDefinition for weekly coach on custodian repos
- id: T14
state_hub_task_id: 697e612b-7531-4329-82fb-b0423ba86904
status: done
title: Pilot ActivityDefinition for weekly optimization review
- id: T15
state_hub_task_id: 92db5130-2212-4780-ab8f-1de3adf6c6f8
status: done
title: Smoke test end-to-end on two preselected repos
- id: T16
state_hub_task_id: bbecdcbf-42b8-4b48-9f85-e4c10e4ff3ab
status: done
title: Document operator enablement in PACKAGE_RELEASE and agency-framework
- id: T17
state_hub_task_id: a9e91d4b-990a-457a-9591-d1243db5b386
status: done
title: Emit kaizen.schedule.prepared event payload spec for activity-core
- id: T18
state_hub_task_id: 73986472-bf19-4b13-af1b-6505ab944459
status: done
title: Update wiki/EcosystemIntegration.md and CHANGELOG for v1.3.0
---
# KAIZEN-WP-0006 — Scheduled Agent Execution via activity-core
**Status:** done
**Owner:** kaizen-agentic
**Repo:** kaizen-agentic
**Target version:** 1.3.0
**Depends on:** WP-0003 (metrics CLI), WP-0004 Part 2 (ActivityDefinition drafts)
## Goal
Enable kaizen agents to run **on a regular schedule** against **preselected repos**,
orchestrated by **activity-core** and prepared by **kaizen-agentic** — without
this repo owning Temporal workers or LLM runtime.
Today, agents are markdown instruction sets invoked in coding-agent sessions.
WP-0004 committed three metrics-focused ActivityDefinitions (`enabled: false`) but
no general **agent dispatch** path, no **repo roster**, and no **per-repo schedule
manifest**. This workplan closes that gap.
### What “scheduled agent execution” means here
```mermaid
flowchart LR
AC[activity-core cron] --> CR[context resolver]
CR --> ROSTER[preselected repos]
ROSTER --> RULE[ActivityDefinition rule]
RULE --> TASK[hub task per repo+agent]
TASK --> PREP[kaizen-agentic schedule prepare]
PREP --> SESSION[coding-agent session]
```
1. **activity-core** fires on cron (or event).
2. A **context resolver** returns repos from the preselected roster that have a
matching schedule entry and reachable `host_paths`.
3. For each `(repo, agent)` pair, activity-core creates a **task** (State Hub /
issue-core) with labels and a `schedule prepare` command.
4. A coding agent (human or automated session) runs `kaizen-agentic schedule prepare`
to assemble orientation: agent prompt, `memory brief`, metrics summary, repo
context — then executes the agent instructions in that repo.
Kaizen-agentic does **not** invoke Claude directly; it **prepares** and **validates**
the scheduled run contract.
---
## Background
| Layer | WP-0004 state | WP-0006 adds |
|-------|---------------|--------------|
| activity-core | Three proposed definitions (metrics only) | Agent-run definitions + roster resolver |
| kaizen-agentic | CLI for metrics/memory | `schedule` command group + `.kaizen/schedule.yml` |
| state-hub | Registered repos + `host_paths` | Fleet roster opt-in + schedule metadata |
| Execution | Manual session | Cron → task → prepared session bundle |
**Prior WP-0006 placeholder** (agent wizard, template validation, doc generation)
moves to **KAIZEN-WP-0007**.
---
## Part 1 — Schedule Contract (repo-local)
Declare which agents run how often in each opted-in repo.
### `.kaizen/schedule.yml` (draft shape)
```yaml
version: "1"
timezone: Europe/Berlin
agents:
coach:
cadence: weekly
cron: "0 9 * * 1" # optional override; default from ActivityDefinition
enabled: true
optimization:
cadence: weekly
cron: "0 10 * * 1"
enabled: true
tdd-workflow:
cadence: monthly
enabled: false
```
### Tasks
- [x] T01 — Write ADR-005: scheduled agent execution (roster, schedule file, dispatch, boundaries)
- [x] T02 — Add `docs/integrations/schedule-schema.md` + example under `docs/examples/.kaizen/schedule.yml`
- [x] T03 — Implement `kaizen-agentic schedule validate [--target PATH]` (schema + agent name checks)
### Definition of done
- ADR-005 accepted; referenced from `docs/agency-framework.md`
- Invalid schedule files fail validation with actionable errors
- Only agents installed in the project (or fleet defaults) may appear in schedule
---
## Part 2 — Fleet Roster (preselected repos)
Define which registered repos participate in fleet scheduling.
### Roster sources (combined)
| Source | Purpose |
|--------|---------|
| State Hub `GET /repos/` | Canonical slug list + `host_paths` |
| Repo opt-in | `.kaizen/schedule.yml` exists and `version` set |
| Optional hub flag | `kaizen_schedule_enabled: true` in repo metadata (design in T05) |
### Tasks
- [x] T04 — Extend `docs/INTEGRATION_PATTERNS.md` Pattern 2 with roster + schedule model
- [x] T05 — Design doc: state-hub fields/filters for kaizen-scheduled repos (no state-hub code in this repo)
- [x] T06 — Spec `discover_kaizen_scheduled_repos` resolver for activity-core (inputs, output shape, errors)
### Definition of done
- Operators can list which repos are schedule-eligible without reading activity-core code
- Resolver spec is sufficient for activity-core implementers to add adapter (separate repo PR)
---
## Part 3 — activity-core ActivityDefinitions (handoff)
Generalize WP-0004 metrics definitions into **agent-run** definitions.
### New reference definitions (kaizen-agentic commits drafts)
| Definition | Trigger | Agent | Prepare command |
|------------|---------|-------|-----------------|
| `weekly-coach-orientation` | Cron Mon 09:00 | `coach` | `schedule prepare coach` |
| `weekly-optimization-review` | Cron Mon 10:00 | `optimization` | `schedule prepare optimization` |
| `weekly-metrics-optimize` | *(existing)* | — | `metrics optimize` |
### Tasks
- [x] T07 — Add `docs/integrations/activity-definitions/weekly-coach-orientation.md`
- [x] T08 — Open activity-core coordination issue/PR checklist (resolver + sync + `enabled: false` pilot)
- [x] T17 — Document `kaizen.schedule.prepared` event payload (for future event-driven runs)
### Definition of done
- Definition files use `for_each` over resolver output `context.scheduled_runs`
- Handoff checklist mirrors WP-0004 Pattern 2 activation steps
- No scheduling code added to kaizen-agentic
---
## Part 4 — Dispatch Prepare CLI
Bridge schedule intent to session-executable orientation.
### Commands
```
kaizen-agentic schedule validate [--target PATH]
kaizen-agentic schedule init [--target PATH] # scaffold .kaizen/schedule.yml
kaizen-agentic schedule prepare <agent> [--target PATH] [--format markdown|json]
kaizen-agentic schedule list [--target PATH] # show enabled entries from schedule.yml
```
`schedule prepare` outputs a single bundle:
- Agent markdown (from installed or packaged `agents/agent-<name>.md`)
- `memory brief <agent>` output (if memory enabled)
- `metrics show <agent>` summary (if metrics exist)
- Repo SCOPE/TODO pointers when present
- Suggested session-close commands (`metrics record`, memory update)
### Tasks
- [x] T09 — Implement `schedule` CLI command group skeleton
- [x] T10 — Wire `prepare` to memory + metrics + agent loader (reuse existing CLI internals)
- [x] T11 — Implement `schedule init` with sensible defaults (coach + optimization weekly, disabled tdd-workflow)
- [x] T12 — Tests for validate, init, prepare (temp repo fixtures)
### Definition of done
- `schedule prepare coach` prints non-empty orientation for a repo with agents installed
- Prepare works offline (no State Hub required) given local `.kaizen/` state
- CLI cheat sheet updated
---
## Part 5 — Pilot and Enablement
Prove the loop on a small custodian repo set before fleet-wide enable.
### Pilot roster (initial)
- `kaizen-agentic` (dogfood)
- `the-custodian` (hub operator)
- One additional custodian-domain repo with `.kaizen/` state (TBD at pilot time)
### Tasks
- [x] T13 — Commit pilot `weekly-coach-orientation` definition; map to custodian pilot repos
- [x] T14 — Commit pilot `weekly-optimization-review` definition
- [x] T15 — Smoke test: dry-run activity-core → manual `schedule prepare` on two repos → verify task payload
- [x] T16 — Operator docs: credentials, PATH, Gitea index, enabling `enabled: true` in activity-core
- [x] T18 — `wiki/EcosystemIntegration.md`, `CHANGELOG [Unreleased]`, `TODO.md` pointer
### Definition of done
- Two repos run through prepare successfully on a fixed schedule (manual or dry-run cron)
- activity-core owners have a clear PR path to enable one definition in staging
- Progress event recorded in State Hub at pilot completion
---
## Sequencing
```
Part 1 (T01T03) ──→ Part 4 (T09T12) ──→ Part 5 (T13T16)
│ │
Part 2 (T04T06) ──→ Part 3 (T07T08, T17)
```
Parts 12 can start in parallel. Part 4 depends on ADR + schema. Part 5 depends
on Part 3 drafts and Part 4 `prepare`. activity-core resolver implementation
runs in **activity-core** (parallel track after T06 spec).
Estimated effort: 46 sessions (kaizen-agentic) + 12 sessions (activity-core handoff).
---
## Out of Scope
- Implementing Temporal workflows or context resolvers in activity-core (handoff only)
- Headless Claude Code / cloud agent runner integration (future; prepare output is runner-agnostic)
- Scheduling all 20 agents fleet-wide in v1.3.0 (pilot: coach + optimization)
- Replacing human review for high-risk agents (sys-medic, releaseManager)
- WP-0007 items: agent selection wizard, template schema enforcement, doc generation
---
## Success Criteria
1. Operators declare a **preselected repo roster** and per-repo **schedules** without tribal knowledge.
2. activity-core can fire recurring tasks that reference `kaizen-agentic schedule prepare <agent>`.
3. A coding-agent session opened from a scheduled task has full orientation (memory + metrics + prompt).
4. Pilot runs on ≥2 custodian repos demonstrate the cron → task → prepare path.
---
## State Hub Task IDs
| Code | UUID |
|------|------|
| T01 | f513cf74-6e32-4dce-a3bc-2995f98a30de |
| T02 | dcb8d674-5472-4657-85bc-02ca9890fb92 |
| T03 | 1f9a4959-d200-4d7b-8666-96472e23d820 |
| T04 | 13ab4b76-ded2-4613-b8e2-15ab206d8c57 |
| T05 | 685b35f3-af20-483a-9136-150f5fff68dd |
| T06 | 5f0a0859-3ff5-4ec8-b916-35486f045b2b |
| T07 | 2fd0f00c-5cf1-47bd-9c12-aee65bca5932 |
| T08 | cc0565bc-ccd4-4739-9c7e-088adaa9834b |
| T09 | 23aeff77-3429-438b-a395-5c7b5dc2824e |
| T10 | cba9685b-408f-4292-8169-9965e7ad5c5b |
| T11 | 7c1b049b-5566-4b5e-9d82-d9c29fab0c84 |
| T12 | 80a8e98a-9146-4a58-8fd3-8c37f7893960 |
| T13 | 9aee6348-d5ad-4413-b01c-5588b07c8ede |
| T14 | 697e612b-7531-4329-82fb-b0423ba86904 |
| T15 | 92db5130-2212-4780-ab8f-1de3adf6c6f8 |
| T16 | bbecdcbf-42b8-4b48-9f85-e4c10e4ff3ab |
| T17 | a9e91d4b-990a-457a-9591-d1243db5b386 |
| T18 | 73986472-bf19-4b13-af1b-6505ab944459 |
**Hub workstream:** `kaizen-wp-0006-scheduled-agent-execution` (`d4edb92b-526f-4ee4-8efe-a9fa84ab6dff`)
---
## Notes
- WP-0004 `weekly-metrics-optimize` remains complementary; optimization agent schedule
may chain `schedule prepare optimization` then `metrics optimize` in task description
- `schedule prepare` output should be stable enough for activity-core task `description` templates
- Repo boundary: state-hub schema changes tracked in the-custodian; kaizen-agentic owns ADR + CLI + definition drafts
- Previous WP-0005 deferrals (wizard, validate schema, doc gen) → **KAIZEN-WP-0007**