= STATE.scm Cookbook
:toc: left
:toclevels: 3
:source-highlighter: highlight.js
:icons: font
:sectanchors:
:sectlinks:

Comprehensive recipes for CLI commands, Justfile tasks, and Nickel configurations.

== Quick Reference

[cols="1,2,3"]
|===
|Tool |Purpose |Common Command

|<<cli,CLI>>
|Direct Guile operations
|`guile -L lib -c '(use-modules (state))'`

|<<just,Just>>
|Task automation
|`just test`

|<<must,Must>>
|Required checks
|`just -f Mustfile all`

|<<nickel,Nickel>>
|Configuration schemas
|`nickel eval state.ncl`
|===

[[cli]]
== CLI Commands

Direct command-line operations using Guile and shell commands.

=== Module Loading

[source,bash]
----
# Load all STATE modules
guile -L lib -c '(use-modules (state))'

# Load specific modules
guile -L lib -c '(use-modules (state-core))'
guile -L lib -c '(use-modules (state-graph))'
guile -L lib -c '(use-modules (state-history))'
guile -L lib -c '(use-modules (state-kanren))'

# Interactive REPL with modules
guile -L lib -l lib/state.scm
----

=== Querying State

[source,bash]
----
# Get current focus
guile -L lib -c '
  (use-modules (state) (state-core))
  (load "STATE.scm")
  (display (get-current-focus state))'

# List blocked projects
guile -L lib -c '
  (use-modules (state) (state-core))
  (load "STATE.scm")
  (for-each
    (lambda (p)
      (display (cdr (assoc '\''name p)))
      (newline))
    (get-blocked-projects state))'

# Get critical next actions
guile -L lib -c '
  (use-modules (state) (state-core))
  (load "STATE.scm")
  (for-each
    (lambda (a) (display a) (newline))
    (get-critical-next state))'
----

=== Visualization CLI

[source,bash]
----
# Generate DOT and render to PNG
guile -L lib -c '
  (use-modules (state) (state-graph))
  (load "STATE.scm")
  (display (generate-dot state))' | dot -Tpng -o deps.png

# Generate Mermaid for markdown
guile -L lib -c '
  (use-modules (state) (state-graph))
  (load "STATE.scm")
  (display (generate-mermaid state))' > deps.mmd

# Generate SVG
guile -L lib -c '
  (use-modules (state) (state-graph))
  (load "STATE.scm")
  (display (generate-dot state))' | dot -Tsvg -o deps.svg
----

=== minikanren Queries

[source,bash]
----
# Find all blocked projects
guile -L lib -c '
  (use-modules (state) (state-kanren))
  (load "STATE.scm")
  (display (run* (q) (statuso q "blocked" state)))'

# Find dependencies of a project
guile -L lib -c '
  (use-modules (state) (state-kanren))
  (load "STATE.scm")
  (display (run* (q) (dependso "MyProject" q state)))'

# Find projects depending on X
guile -L lib -c '
  (use-modules (state) (state-kanren))
  (load "STATE.scm")
  (display (run* (q) (dependso q "BaseLibrary" state)))'
----

=== History and Velocity

[source,bash]
----
# Create snapshot
guile -L lib -c '
  (use-modules (state) (state-history))
  (load "STATE.scm")
  (display (create-snapshot state))'

# Calculate velocity
guile -L lib -c '
  (use-modules (state) (state-history))
  (load "STATE.scm")
  (display (project-velocity "MyProject" state))'

# Estimate completion
guile -L lib -c '
  (use-modules (state) (state-history))
  (load "STATE.scm")
  (display (estimate-completion-date "MyProject" state))'
----

=== Pipeline Combinations

[source,bash]
----
# Full pipeline: load, query, visualize
guile -L lib -c '
  (use-modules (state) (state-core) (state-graph))
  (load "STATE.scm")
  (display "Focus: ") (display (get-current-focus state)) (newline)
  (display "Blocked: ") (display (length (get-blocked-projects state))) (newline)
  (display (generate-mermaid state))'

# JSON-style output (for piping)
guile -L lib -c '
  (use-modules (state) (state-core))
  (load "STATE.scm")
  (format #t "{\"focus\": \"~a\", \"blocked\": ~a}~%"
    (get-current-focus state)
    (length (get-blocked-projects state)))'

# Export to multiple formats
for fmt in dot mermaid; do
  guile -L lib -c "
    (use-modules (state) (state-graph))
    (load \"STATE.scm\")
    (display (generate-$fmt state))" > "state.$fmt"
done
----

[[just]]
== Justfile Recipes

Task automation using https://just.systems[just].

=== Testing

[source,bash]
----
# Basic test
just test

# Verbose test output
just test-verbose

# End-to-end tests
just test-e2e

# Run all tests
just test-all

# Test in container
just container-test
----

=== Development

[source,bash]
----
# Start REPL
just repl

# REPL with example loaded
just repl-example

# Lint all files
just lint

# Run all checks
just check

# Check minikanren availability
just check-minikanren
----

=== Visualization

[source,bash]
----
# Generate GraphViz DOT
just dot

# Generate DOT to file
just dot-file output=my-graph.dot

# Generate Mermaid
just mermaid

# Generate Mermaid to file
just mermaid-file output=my-diagram.mmd

# Render DOT to PNG
just render-dot output=deps.png

# Status-grouped graph
just dot-status
----

=== Reports

[source,bash]
----
# Velocity report
just velocity

# Progress report
just progress

# List blocked projects
just blocked

# List in-progress projects
just in-progress

# Critical next actions
just critical

# Critical path for project
just critical-path MyProject

# Session health
just health
----

=== minikanren Queries

[source,bash]
----
# Query blocked projects
just query-blocked

# Query in-progress projects
just query-in-progress

# Query project dependencies
just query-deps MyProject
----

=== Documentation

[source,bash]
----
# Build main docs
just docs

# Build spec docs
just docs-spec

# Build all docs
just docs-all
----

=== Containers

[source,bash]
----
# Build with podman
just container

# Build with nerdctl
just container-nerdctl

# Run interactive container
just container-run

# Run tests in container
just container-test
----

=== Package Management

[source,bash]
----
# Enter Guix shell
just guix-shell

# Build with Guix
just guix-build

# Enter Nix shell
just nix-shell

# Build with Nix
just nix-build
----

=== Security

[source,bash]
----
# Check for secrets
just check-secrets

# Check for HTTP URLs
just check-urls

# Run all security checks
just security
----

=== CI/CD

[source,bash]
----
# Run full CI pipeline
just ci

# Pre-commit checks
just pre-commit
----

=== Recipe Combinations

[source,bash]
----
# Full development cycle
just lint && just test-all && just docs

# Pre-release checklist
just ci && just docs-all && just container-test

# Clean rebuild
just clean-all && just guix-build && just test

# Generate all visualizations
just dot-file && just mermaid-file && just render-dot
----

[[must]]
== Mustfile Recipes

Required checks that MUST pass. Run with `just -f Mustfile <recipe>`.

=== Critical Requirements

[source,bash]
----
# All modules must load
just -f Mustfile must-load

# Core queries must work
just -f Mustfile must-query

# Visualization must work
just -f Mustfile must-visualize

# History must work
just -f Mustfile must-history

# Valid syntax everywhere
just -f Mustfile must-syntax
----

=== Security Requirements

[source,bash]
----
# No hardcoded secrets
just -f Mustfile must-no-secrets

# HTTPS only
just -f Mustfile must-https

# All security checks
just -f Mustfile security
----

=== Documentation Requirements

[source,bash]
----
# Required files exist
just -f Mustfile must-docs

# SPDX headers present
just -f Mustfile must-spdx

# All documentation checks
just -f Mustfile docs
----

=== Build Requirements

[source,bash]
----
# Valid Containerfile
just -f Mustfile must-container

# Valid Guix definition
just -f Mustfile must-guix
----

=== Composite Checks

[source,bash]
----
# ALL requirements (default)
just -f Mustfile all

# Quick pre-commit check
just -f Mustfile quick

# Full validation pipeline
just -f Mustfile all && just ci
----

[[nickel]]
== Nickel Configurations

Nickel provides typed configuration language. See https://nickel-lang.org[Nickel docs].

=== State Schema

.state.ncl
[source,nickel]
----
# STATE.scm Nickel Schema
# Validates STATE file structure

let StateSchema = {
  metadata = {
    format-version | String,
    schema-version | String,
    created-at | String,
    last-updated | String,
    generator | String | optional,
  },

  user = {
    name | String,
    roles | Array String | optional,
    preferences | {
      languages-preferred | Array String | optional,
      languages-avoid | Array String | optional,
      tools-preferred | Array String | optional,
      values | Array String | optional,
    } | optional,
  },

  session = {
    conversation-id | String,
    started-at | String,
    messages-used | Number | optional,
    messages-remaining | Number | optional,
    token-limit-reached | Bool | optional,
  },

  focus = {
    current-project | String,
    current-phase | String | optional,
    deadline | String | Null | optional,
    blocking-projects | Array String | optional,
  },

  projects | Array {
    name | String,
    status | [| 'in-progress, 'blocked, 'paused, 'complete, 'abandoned |],
    completion | Number,
    category | String | optional,
    phase | String | optional,
    dependencies | Array String,
    blockers | Array String,
    next | Array String,
    chat-reference | String | Null | optional,
    notes | String | optional,
  },

  critical-next | Array String | optional,
}
in StateSchema
----

=== Project Validation

.validate-project.ncl
[source,nickel]
----
# Validate a single project entry

let Project = {
  name | String | not_empty,
  status | [| 'in-progress, 'blocked, 'paused, 'complete, 'abandoned |],
  completion
    | Number
    | contract.from_predicate (fun x => x >= 0 && x <= 100)
    | doc "Completion percentage 0-100",
  dependencies | Array String | default = [],
  blockers | Array String | default = [],
  next | Array String | default = [],
}
in Project
----

=== Configuration Generator

.generate-config.ncl
[source,nickel]
----
# Generate STATE configuration from templates

let make_project = fun name status completion deps =>
  {
    name = name,
    status = status,
    completion = completion,
    dependencies = deps,
    blockers = [],
    next = [],
  }
in

let make_state = fun user_name projects =>
  {
    metadata = {
      format-version = "2.0",
      schema-version = "2025-12-22",
      created-at = "2025-12-22T00:00:00Z",
      last-updated = "2025-12-22T00:00:00Z",
    },
    user = { name = user_name },
    session = {
      conversation-id = "generated",
      started-at = "2025-12-22T00:00:00Z",
    },
    focus = {
      current-project = (std.array.first projects).name,
    },
    projects = projects,
  }
in

{
  make_project = make_project,
  make_state = make_state,
}
----

=== Nickel CLI Examples

[source,bash]
----
# Evaluate schema
nickel eval state.ncl

# Type check configuration
nickel typecheck state.ncl

# Export to JSON
nickel export state.ncl > state.json

# Query specific value
nickel query state.ncl --field metadata.format-version

# Validate against contract
nickel eval --contract StateSchema my-state.ncl
----

[[hooks]]
== Git Hooks

Pre-commit and other git hooks for automation.

=== Pre-commit Hook

.pre-commit
[source,bash]
----
#!/usr/bin/env bash
# .git/hooks/pre-commit
set -e

echo "Running pre-commit checks..."

# Quick must checks
just -f Mustfile quick

# Lint
just lint

# Basic tests
just test

echo "✓ Pre-commit checks passed"
----

=== Pre-push Hook

.pre-push
[source,bash]
----
#!/usr/bin/env bash
# .git/hooks/pre-push
set -e

echo "Running pre-push checks..."

# Full must requirements
just -f Mustfile all

# Full test suite
just test-all

# Security checks
just security

echo "✓ Pre-push checks passed"
----

=== Commit-msg Hook

.commit-msg
[source,bash]
----
#!/usr/bin/env bash
# .git/hooks/commit-msg
# Validate conventional commits

commit_msg=$(cat "$1")

# Regex for conventional commits
regex="^(feat|fix|docs|style|refactor|perf|test|build|ci|chore|revert)(\(.+\))?: .{1,72}"

if ! [[ $commit_msg =~ $regex ]]; then
  echo "ERROR: Commit message doesn't follow Conventional Commits"
  echo "Format: type(scope): description"
  echo "Types: feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert"
  exit 1
fi
----

[[cicd]]
== CI/CD Integration

=== GitHub Actions Integration

[source,yaml]
----
# Example job using Justfile
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: extractions/setup-just@v2
      - run: just ci
----

=== GitLab CI Integration

[source,yaml]
----
# Example job using Justfile
test:
  image: debian:bookworm
  before_script:
    - apt-get update && apt-get install -y guile-3.0 just
  script:
    - just ci
----

== Permutations & Combinations

=== Full Workflow Matrix

[source,bash]
----
# Development cycle
for action in lint test docs; do
  just $action
done

# All report types
for report in velocity progress blocked in-progress critical; do
  echo "=== $report ===" && just $report
done

# All visualization formats
for fmt in dot mermaid dot-status; do
  just $fmt > "output.$fmt"
done

# Environment matrix
for env in guix nix container; do
  case $env in
    guix) just guix-shell ;;
    nix) just nix-shell ;;
    container) just container-run ;;
  esac
done
----

=== Validation Pipeline

[source,bash]
----
# Complete validation
{
  echo "=== Syntax ===" && just lint &&
  echo "=== Must ===" && just -f Mustfile all &&
  echo "=== Tests ===" && just test-all &&
  echo "=== Security ===" && just security &&
  echo "=== Docs ===" && just docs
} && echo "✓ ALL VALIDATIONS PASSED"
----

== Troubleshooting

=== Common Issues

[cols="1,2"]
|===
|Error |Solution

|Module not found
|`export GUILE_LOAD_PATH=$PWD/lib:$GUILE_LOAD_PATH`

|Just not found
|Install: `cargo install just` or `guix install just`

|Nickel not found
|Install: `cargo install nickel-lang-cli`

|Container build fails
|Check `podman` or `nerdctl` is installed

|Permission denied on hook
|`chmod +x .git/hooks/pre-commit`
|===

=== Debug Commands

[source,bash]
----
# Verbose Guile output
guile -L lib -c '(debug-enable '\''backtrace)' -l lib/state.scm

# Just dry-run
just --dry-run test

# Nickel debug
nickel eval --trace state.ncl
----
