kazam 1.30.1

Local infrastructure for coding agents: context, visibility, durable execution. One Rust binary, no cloud.
# Contributing to kazam

Thanks for the interest. kazam is small on purpose - Rust CLI, YAML in, HTML out - and the goal is to keep it that way. This guide covers how to propose a change, what we value in a PR, and how contributors can safely use coding agents alongside their own work.

## What kind of contributions are valued

- **Bug fixes** with a reproducer in the description.
- **New components** that compose with existing ones. A component earns its place by unlocking a real page type; a one-off CSS trick usually doesn't.
- **Theme tokens / print / accessibility improvements** to existing components.
- **Docs** - the hosted site lives in `docs/`, authored in kazam itself. Adding examples is always welcome.
- **CI / dev ergonomics.**

If you're unsure whether a change fits, open a small issue first and describe the use case.

## Getting set up

```bash
git clone https://github.com/YOUR-FORK/kazam
cd kazam
git config core.hooksPath .githooks   # enable pre-commit checks
cargo build --release
cargo test --release
./target/release/kazam dev docs --port 3002   # live-edit the docs site
```

The `core.hooksPath` line activates the repo's pre-commit hook (`.githooks/pre-commit`), which runs `cargo fmt --check` and `cargo clippy` before every commit. Use the latest stable Rust toolchain via [rustup](https://rustup.rs). The repo pins nothing - if stable works, we support it.

## Fork + PR flow

1. Fork on GitHub and clone your fork.
2. Branch off `main`: `git checkout -b feature/short-name`.
3. Make changes. Keep the diff focused - one concern per PR is easiest to review.
4. Run the local checks before pushing:
   ```bash
   cargo test --release
   cargo fmt --check
   cargo clippy --release -- -D warnings
   ```
5. Push your branch and open a PR against `tdiderich/kazam:main`.
6. A maintainer reviews. Expect small turnaround and occasional pushback on scope.

## PR checklist

- [ ] `cargo test --release` passes
- [ ] `cargo fmt --check` passes
- [ ] `cargo clippy --release -- -D warnings` passes (or justify any exception in the PR)
- [ ] If you changed the output HTML or CSS, eyeball the docs site (`kazam dev docs --port 3002`) to confirm nothing regressed.
- [ ] If you added a component or config field, update `AGENTS.md.template` and the relevant page under `docs/components/`.
- [ ] If you added or changed a subcommand or its args, run `kazam cli-reference --write` and commit the README diff.
- [ ] Commit messages are in the imperative mood ("add X", not "added X").

## Code style

- Prefer small, well-named functions over macros or generics.
- Keep components self-contained: one render fn in `src/render/components.rs`, matching styles in `src/theme.rs`, type in `src/types.rs`.
- Don't introduce a new runtime dependency without a good reason. kazam's value is partly that it ships as one tiny binary.
- Inline scripts for interactivity go in `src/render/scripts.rs`. We don't ship a JS build system and don't intend to.
- Theme-aware colors use CSS custom props (`var(--accent-rgb)`, `var(--text-rgb)`, etc.), not hardcoded rgba literals. If you find a hardcoded color, fix it.

## Using coding agents

kazam is fine territory for LLM-assisted contributions. A couple of expectations:

- **Point the agent at `AGENTS.md`** when it's writing kazam YAML (pages, examples, docs content). `kazam agents` dumps the same guide.
- **Review the agent's diff yourself before opening a PR.** Autonomous-mode commits that the contributor hasn't read are the usual source of low-quality PRs we'll close.
- **Don't paste secrets or third-party code** into agent prompts or into the repo. See `SECURITY.md` for more.
- **Disclose agent usage in the PR body** if a meaningful portion was agent-authored. We're not against it; we just want the review to focus on the right things.

## Architecture - where things live

```
src/
  main.rs                 CLI entry + subcommands
  build.rs / dev.rs       Batch build and watch-serve
  render/
    mod.rs                Page render orchestration
    shells.rs             Shell chrome (standard, document, deck)
    components.rs         Each component's render fn
    scripts.rs            Bundled inline JS (deck nav, tabs, etc.)
  theme.rs                Theme tokens + STATIC_CSS
  types.rs                All YAML-facing types (serde structs)
  annotations.rs          Sidecar annotation system (load, save, decay)
  audit.rs                Site health auditing
  freshness.rs            Freshness tracking + drift + notify
  ingest.rs               Notion (and future) content ingestion
  mcp/
    mod.rs                MCP server dispatch (stdio + HTTP transports)
    protocol.rs           JSON-RPC types
    tools.rs              MCP tool implementations (8 tools)
  workspace.rs            Agent workspace init + status
  track.rs / ctx.rs       Task tracking + context intelligence
  wish.rs                 Wish registry (list, init from recipes)
  llms.rs                 llms.txt emission
  init.rs / agents.rs     `kazam init` / `kazam agents` scaffolding
  minify.rs               Release-mode HTML/CSS/JS minification
wishes/                   Portable agent recipes (deal-360, debrief, etc.)
docs/                     The hosted docs site (itself a kazam site)
AGENTS.md.template        Authoring guide bundled into the binary
tests/                    Integration tests
```

Most component additions touch: `types.rs` (struct), `render/components.rs` (HTML), `theme.rs` (CSS), plus a `docs/components/*.yaml` example.

## Agent Graph Language (`.agl`), the `~/.kazam/agl` hub

`.agl` specs and their importable fragments live in one place on a machine,
by convention rather than any hub-management subcommand:

```
~/.kazam/agl/
  specs/      authored .agl specs, one per task
  shared/     importable fragments (invariant and/or cache blocks)
  cache/      <name>.jsonl per named cache block - never touched by
              kazam agl load, so regenerating a skill can't lose data
  templates/  <name>.md boilerplate + known-good examples, referenced
              by name from a state's own evaluate(...) text, no grammar
```

A bare name with no `/` and no `.agl` extension, passed to `validate`,
`export`, `flow`, or `skill`, is shorthand for `~/.kazam/agl/specs/<name>.agl`.
An `import "some/path.agl"` line inside a spec resolves relative to the
importing file first, then falls back to `~/.kazam/agl/shared/<path>`.

Grammar beyond what's in `PRODUCT.md`/`README.md`:

- `import "path.agl"`, zero or more, before the `spec` keyword. Pulls a
  fragment's `invariant { ... }` rules into the importing spec. Fragments
  can nest imports; cycles are a hard error.
- `requires: Server.method, Server.other_method`, optional, inside the
  spec block after `out:`. Declares the dotted tool names the flow depends
  on. `kazam agl validate` cross-checks this against every `call()`/`map()`
  in the flow (`undeclared-tool-dependency` / `unused-tool-dependency`
  warnings) so the list stays trustworthy. `kazam agl skill` renders it as
  a preflight instruction: confirm every tool is available before executing
  any state, abort immediately if one is missing, rather than discovering
  the gap mid-graph after other states already ran.
- `cache NAME { field: type, ... }`, zero or more, after `requires:`/
  `skill:`, in a spec and/or a fragment it imports. Two blocks landing on
  the same name with different fields is a hard error. `kazam agl skill`
  renders a `## Cache` section per block naming its file
  (`~/.kazam/agl/cache/NAME.jsonl`), its schema, and the check-before-
  resolve / append-after-resolve convention. `kazam agl cache-migrate
  <path> [--name NAME]` backfills an existing cache file's lines with a
  type-appropriate default for any field the schema has since gained.

Templates aren't grammar at all, just files: `~/.kazam/agl/templates/NAME.md`,
`<!--spec-->` marks the boilerplate shape, `<!--samples-->` marks known good
examples, no marker means the whole file is the shape. A state's own
`evaluate(...)` text names one directly, like `evaluate(draft vs
activity-summary)`. `kazam agl skill`/`load` check every distinct word
across a spec's `evaluate(...)` expressions against real files in that
directory and embed each match into a `## Templates` section.

- `fan(SpecName, iterable)`, one primitive for composition and bounded
  looping. `iterable` is a bare ident (an existing collection variable) or
  a quoted count (`fan(SpecName, "5")`, a bound with nothing to iterate
  over). `validator::has_gate_protected_writes` treats any spec containing
  a `fan()` as gate-protected unconditionally - it never resolves the
  fanned spec to check whether it actually has gates, every real fan
  target in practice already does - so a fanning spec always refuses
  `--isolated` and always runs inline. `kazam agl load` warns (doesn't
  fail) if `SpecName` has no matching `~/.kazam/agl/specs/<name>.agl`.
- `watch(CONDITION)`, a distinct action from `gate()`: polls an external
  condition (CI status, a build finishing) rather than waiting on a human.
  If `CONDITION`'s text names a time bound and it's exceeded, the executor
  stops and reports rather than waiting indefinitely.

`kazam agl flow <spec>` prints a plain ASCII rendering of the graph, states,
actions, transitions, branch fan-out, meant as a quick "what does this
actually do" read for a human, separate from `kazam agl skill`'s per-target
compiled output (which embeds the same diagram after its preflight section,
before the resolved source).

## License

By submitting a PR you agree that your contribution is licensed under the repo's MIT license.