Skip to content

Commit e9da669

Browse files
Merge pull request #69 from PromptExecution/feat/wrkflw-docgen-pipeline
feat(wrkflw): add local docgen visualization pipeline test workflow
2 parents cbd7ff9 + e0652a1 commit e9da669

7 files changed

Lines changed: 349 additions & 5 deletions

File tree

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
# wrkflw-local-docgen: local visualization pipeline test workflow
2+
# Run with: wrkflw run .github/workflows/wrkflw-docgen.yml
3+
#
4+
# IMPORTANT:
5+
# - Uses `emulation` runtime (Docker not required) — steps run as host processes
6+
# - Assumes host has: Rust toolchain, cargo, node, just, mdBook toolchain installed
7+
# - wrkflw copies the repo into a sandboxed temp dir — use relative file paths
8+
# - Each stage does fresh `cargo build` in sandbox — no shared target dir
9+
# - Expected runtime for full 9-stage run: 20-60+ minutes
10+
# - ${{ }} expressions, `needs.<id>.result`, `toJSON(needs)` NOT supported in wrkflw
11+
name: wrkflw-local-docgen
12+
13+
on:
14+
workflow_dispatch:
15+
16+
env:
17+
CARGO_TERM_COLOR: always
18+
RUST_BACKTRACE: "1"
19+
20+
defaults:
21+
run:
22+
shell: bash
23+
24+
jobs:
25+
# Stage 1: Rust unit tests for mdbook-rhai-mermaid parser/emitter
26+
stage-1-rhai-parser-tests:
27+
name: "S1 Rhai Parser Tests"
28+
runs-on: ubuntu-latest
29+
steps:
30+
- uses: actions/checkout@v4
31+
- name: Run mdbook-rhai-mermaid unit tests
32+
run: |
33+
cargo test -p mdbook-rhai-mermaid 2>&1 | tee parser-test-output.txt
34+
35+
# Stage 2: ledger-core iso/isometric lint tests
36+
stage-2-iso-lint:
37+
name: "S2 Iso Lint Tests"
38+
needs: [stage-1-rhai-parser-tests]
39+
runs-on: ubuntu-latest
40+
steps:
41+
- uses: actions/checkout@v4
42+
- name: Run iso lint tests
43+
run: |
44+
cargo test -p ledger-core --test iso_lint --features legal-z3 2>&1 | tee iso-lint-output.txt
45+
46+
# Stage 3: ledger-core visualization tests (LayoutSolver, to_mermaid, to_html)
47+
stage-3-viz-tests:
48+
name: "S3 Viz/Derive Tests"
49+
needs: [stage-1-rhai-parser-tests]
50+
runs-on: ubuntu-latest
51+
steps:
52+
- uses: actions/checkout@v4
53+
- name: Run ledger-core visualization tests
54+
run: |
55+
cargo test -p ledger-core --features legal-z3 2>&1 | tee viz-test-output.txt
56+
57+
# Stage 4: ledger-core Z3 legal solver integration tests
58+
stage-4-legal-z3:
59+
name: "S4 Legal Z3 Integration"
60+
needs: [stage-2-iso-lint, stage-3-viz-tests]
61+
runs-on: ubuntu-latest
62+
steps:
63+
- uses: actions/checkout@v4
64+
- name: Run legal-z3 integration test
65+
run: |
66+
cargo test -p ledger-core --test legal_z3_integration --features legal-z3 2>&1 | tee legal-z3-output.txt
67+
68+
# Stage 5: Build mdBook docs with rhai→mermaid injection
69+
stage-5-docgen-build:
70+
name: "S5 Docgen Build"
71+
needs: [stage-1-rhai-parser-tests]
72+
runs-on: ubuntu-latest
73+
steps:
74+
- uses: actions/checkout@v4
75+
- name: Build docs
76+
run: |
77+
just docgen 2>&1 | tee docgen-build-output.txt
78+
79+
- name: Verify Mermaid injection
80+
run: |
81+
echo "=== Checking Mermaid injection ==="
82+
grep -q 'class="mermaid"' book/book/theory.html && echo "✓ theory.html: Mermaid OK" || { echo "✗ theory.html: NO MERMAID"; exit 1; }
83+
grep -q 'class="language-rhai"' book/book/theory.html && echo "✓ theory.html: Rhai blocks OK" || { echo "✗ theory.html: NO RHAI"; exit 1; }
84+
grep -q 'class="mermaid"' book/book/visualize.html && echo "✓ visualize.html: Mermaid OK" || { echo "✗ visualize.html: NO MERMAID"; exit 1; }
85+
86+
# Stage 6: Kasuari constraint solver tests from ledger-core
87+
stage-6-kasuari-constraints:
88+
name: "S6 Kasuari Constraint Tests"
89+
needs: [stage-2-iso-lint]
90+
runs-on: ubuntu-latest
91+
steps:
92+
- uses: actions/checkout@v4
93+
- name: Run constraint solver tests
94+
run: |
95+
cargo test -p ledger-core -- constraints::test 2>&1 | tee kasuari-output.txt
96+
cargo test -p ledger-core -- pipeline::test 2>&1 | tee -a kasuari-output.txt
97+
98+
# Stage 7: Iso object lint — verify all HasVisualization impls produce valid specs
99+
stage-7-iso-objects:
100+
name: "S7 Iso Objects HasVisualization"
101+
needs: [stage-2-iso-lint]
102+
runs-on: ubuntu-latest
103+
steps:
104+
- uses: actions/checkout@v4
105+
- name: Run iso_objects tests
106+
run: |
107+
cargo test -p ledger-core --features legal-z3 -- --test-threads=1 2>&1 | tee iso-objects-output.txt
108+
109+
# Stage 8: Live-editor JS unit tests
110+
stage-8-live-editor-js:
111+
name: "S8 Live Editor JS Tests"
112+
needs: [stage-5-docgen-build]
113+
runs-on: ubuntu-latest
114+
steps:
115+
- uses: actions/checkout@v4
116+
- name: Run live-editor unit tests
117+
run: |
118+
node --test book/theme/rhai-live-core.test.js 2>&1 | tee js-test-output.txt
119+
120+
- name: Run JS syntax checks
121+
run: |
122+
node -c book/theme/rhai-live-core.js
123+
node -c book/theme/rhai-live.js
124+
125+
# Stage 9: Xero MCP smoke test (build + unit tests, no live API calls)
126+
stage-9-xero-mcp:
127+
name: "S9 Xero MCP Smoke"
128+
needs: [stage-1-rhai-parser-tests]
129+
runs-on: ubuntu-latest
130+
steps:
131+
- uses: actions/checkout@v4
132+
- name: Build MCP server
133+
run: |
134+
cargo build -p ledgerr-mcp --bin ledgerr-mcp-server 2>&1 | tee xero-mcp-output.txt
135+
136+
- name: Run MCP tests
137+
run: |
138+
cargo test -p ledgerr-mcp 2>&1 | tee -a xero-mcp-output.txt

AGENTS.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,29 @@ Treat this as a standing operational gate, not a one-time migration task.
384384
- Protocol module (`protocol.rs`): Z3/Kasuari-style constraint system for protocol encoding optimality (`O = P XOR B`), `KASUARI_SHORTHAND == ( && === and , || === or )`. `evaluate_protocol()`, `has_unrecoverable_violations()`, `classify_violations()` with dialect comparison table.
385385
- Tomllmd module (`tomllmd.rs`): `.tomllmd` compiler with `SectionLevels` (verbatim/executive/epigram), `EntanglementRef` with type validation, compounding metadata.
386386
- Ralph loop surface (`b00t-iface/src/ralph.rs`): `RalphLoopSurface<R: Researcher>` with typed `RalphLoopProperties` (TTL, cadence, crash_budget, max_iterations), `iterate()` lifecycle, governance harmonized to existing `ProcessSurface`/`SurfaceMachine`/`SurfaceHarness`.
387+
- 2026-05-03: wrkflw integration for local docgen visualization pipeline testing.
388+
- `wrkflw` (`cargo install wrkflw`) runs GitHub Actions workflows locally without Docker via `--runtime secure-emulation`.
389+
- `.github/workflows/wrkflw-docgen.yml` defines a 9-stage pipeline testing all visualization layers: Rhai parser tests (S1), iso lint (S2), viz/derive tests (S3), legal Z3 integration (S4), mdBook docgen build (S5), Kasuari constraint tests (S6), iso objects HasVisualization impls (S7), live-editor JS tests (S8), Xero MCP smoke (S9).
390+
- Justfile recipes: `wrkflw-docgen-test`, `wrkflw-validate`, `wrkflw-list`, `wrkflw-job`, `wrkflw-tui`, `wrkflw-full-test`.
391+
- `scripts/wrkflw_test.sh` — test harness with `--validate`, `--stage S<N>`, `--list`, `--full` modes.
392+
- Use `just wrkflw-docgen-test` to run the full pipeline. Individual stages with `just wrkflw-job stage-5-docgen-build`.
393+
- wrkflw validates workflow YAML first (`wrkflw validate .github/workflows/wrkflw-docgen.yml`), then executes.
394+
- Secure emulation mode avoids needing Docker/Podman — wrkflw executes steps as sandboxed host processes.
395+
- Important wrkflw limitations discovered:
396+
- `actions/checkout@v4` is REQUIRED in each job even for local emulation (wrkflw volume-mounts empty dirs)
397+
- `uses:` with composite actions (like `dtolnay/rust-toolchain@stable`) fails under emulation — use inline commands
398+
- `continue-on-error: ${{ }}` expressions unsupported — use literal `true`/`false` only
399+
- `needs.<id>.result` and `toJSON(needs)` expressions not supported in summary jobs
400+
- Each stage does a fresh `cargo build` from scratch in its sandbox — no shared `target/` cache
401+
- wrkflw secure emulation blocks `curl | sh` dangerous patterns — use `emulation` runtime instead
402+
- Expected full 9-stage run: 20-60+ minutes due to recompilation
403+
- During integration, wrkflw surfaced a pre-existing compilation error in `crates/ledger-core/src/observability.rs:192` (`ParseIntError``ObservabilityError` type mismatch, fixed).
404+
- Non-obvious emergent capabilities from the Z3/Kasuari `HasVisualization` invariant:
405+
- **Dual solver topology testable in one pipeline**: S4 exercises Z3 (hard legal SAT) and S6 exercises Kasuari (soft Cassowary constraints) — the `ConstraintSolver` trait bridges them, and both produce `Z3Result`/`ConstraintEvaluation` that share the same `HasVisualization` impl contract.
406+
- **Z-layer stack consistency**: The 6-layer Z stack (Document→Pipeline→Constraint→Legal→FormalProof→Attestation) and the 21+ `HasVisualization` impls can be validated across all layers without needing a real ledger dataset — S2+S7 cover the full impl surface via `--test iso_lint` and `--test-threads=1`.
407+
- **Cross-stage composition coverage**: The `ConstraintSolver` trait (KasuariSolver in pipeline.rs), `LayoutSolver` (visualize.rs), and `LegalSolver` (legal.rs, Z3-gated) are independent solver engines that share `Issue`, `MetaCtx`, and `CommitGate` types — wrkflw stages independently validate each while the summary signals overall contract consistency.
408+
- **Docgen as integration test**: S5 (mdBook build) indirectly tests the `mdbook-rhai-mermaid` preprocessor, which uses the same `parser::Graph` types exported as a library (lib.rs) — proving the parser works both as an mdBook plugin and as a standalone library for b00t synergy_viz.
409+
- **What's NOT tested**: McpProviderRegistry initialization, Xero live API calls, crash recovery/idempotency, concurrency groups, service containers, negative testing with malformed inputs, and cross-stage artifact sharing.
387410
- 2026-04-24: README/product framing is bookkeeping-first with visual workflow graph as the organizing model.
388411
- Describe `l3dg3rr` as a strongly typed, ontologically linked graph of scriptable visual-first workflows for supervised AI/LLM ETL into CPA-auditable bookkeeping artifacts.
389412
- Keep README structure MECE: bookkeeping truth, typed domain model, ontology graph, scriptable policy, workflow control, visualization, MCP/agent boundary, and operator host.

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Dockerfile

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,13 @@
33
# ── dependency cache layer (cargo-chef) ──────────────────────────────────────
44
FROM rust:1-bookworm AS chef
55
RUN apt-get update \
6-
&& apt-get install -y --no-install-recommends libz3-dev \
6+
&& apt-get install -y --no-install-recommends \
7+
libz3-dev \
8+
libgtk-3-dev \
9+
libwebkit2gtk-4.1-dev \
10+
libayatana-appindicator3-dev \
11+
librsvg2-dev \
12+
patchelf \
713
&& rm -rf /var/lib/apt/lists/*
814
RUN cargo install cargo-chef --locked
915
WORKDIR /app
@@ -26,8 +32,8 @@ COPY docs ./docs
2632
COPY rules ./rules
2733
COPY scripts ./scripts
2834

29-
RUN cargo test --workspace --all-features
30-
RUN cargo build -p ledgerr-mcp --release --bin ledgerr-mcp-server
35+
RUN cargo test --workspace --features 'audit,autoresearch,b00t,classification,core,default,events,full,hsm,legacy,legal-z3,llm,local-llm,mistralrs-llm,ontology,reconciliation,self-update,tax,xero'
36+
RUN cargo build -p ledgerr-mcp --release --bin ledgerr-mcp-server --features 'audit,autoresearch,b00t,classification,core,default,events,full,hsm,legacy,legal-z3,llm,local-llm,mistralrs-llm,ontology,reconciliation,self-update,tax,xero'
3137

3238
# ── runtime ───────────────────────────────────────────────────────────────────
3339
FROM debian:bookworm-slim AS runtime

Justfile

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -466,3 +466,45 @@ docgen-check:
466466
@echo "Running live-editor unit tests..."
467467
@node --test book/theme/rhai-live-core.test.js
468468
@echo "All documentation diagrams validated!"
469+
470+
# ─── wrkflw: local CI pipeline runner ──────────────────────────────────────
471+
472+
# Run the wrkflw-local-docgen workflow locally using emulation mode (no Docker).
473+
# Tests all visualization pipeline stages: Rhai parser, iso lint, viz derive,
474+
# legal Z3, docgen build, Kasuari constraints, iso objects, live-editor JS.
475+
# Requires: cargo install wrkflw
476+
wrkflw-docgen-test emulation="secure-emulation":
477+
@if ! command -v wrkflw >/dev/null 2>&1; then echo "error: wrkflw not found — run: cargo install wrkflw"; exit 1; fi
478+
@echo "=== wrkflw: Running docgen visualization pipeline ==="
479+
wrkflw run --runtime {{emulation}} .github/workflows/wrkflw-docgen.yml
480+
@echo "=== wrkflw-docgen-test complete ==="
481+
482+
# Validate the wrkflw workflow definition for syntax correctness
483+
wrkflw-validate:
484+
@if ! command -v wrkflw >/dev/null 2>&1; then echo "error: wrkflw not found — run: cargo install wrkflw"; exit 1; fi
485+
wrkflw validate --verbose .github/workflows/wrkflw-docgen.yml
486+
@echo "✓ wrkflw-docgen workflow validates"
487+
488+
# List all workflows wrkflw can discover
489+
wrkflw-list:
490+
@if ! command -v wrkflw >/dev/null 2>&1; then echo "error: wrkflw not found — run: cargo install wrkflw"; exit 1; fi
491+
wrkflw list
492+
493+
# Run specific stages of the docgen pipeline via wrkflw with job selection
494+
wrkflw-job job="stage-1-rhai-parser-tests" emulation="secure-emulation":
495+
@if ! command -v wrkflw >/dev/null 2>&1; then echo "error: wrkflw not found — run: cargo install wrkflw"; exit 1; fi
496+
wrkflw run --job "{{job}}" --runtime {{emulation}} .github/workflows/wrkflw-docgen.yml
497+
498+
# Open wrkflw TUI to inspect and run workflows interactively
499+
wrkflw-tui:
500+
@if ! command -v wrkflw >/dev/null 2>&1; then echo "error: wrkflw not found — run: cargo install wrkflw"; exit 1; fi
501+
wrkflw tui
502+
503+
# Full wrkflw test: validate first, then run the full docgen pipeline
504+
wrkflw-full-test emulation="secure-emulation":
505+
@if ! command -v wrkflw >/dev/null 2>&1; then echo "error: wrkflw not found — run: cargo install wrkflw"; exit 1; fi
506+
@echo "=== Step 1: Validate ==="
507+
wrkflw validate .github/workflows/wrkflw-docgen.yml
508+
@echo ""
509+
@echo "=== Step 2: Run docgen pipeline ==="
510+
wrkflw run --runtime {{emulation}} .github/workflows/wrkflw-docgen.yml

crates/ledger-core/src/observability.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,8 @@ impl TryFrom<&otlp_json::LogRecord> for OTelLogRecord {
189189
type Error = ObservabilityError;
190190

191191
fn try_from(record: &otlp_json::LogRecord) -> Result<Self, Self::Error> {
192-
let time_unix_nano = record.time_unix_nano.parse()?;
192+
let time_unix_nano = record.time_unix_nano.parse()
193+
.map_err(|e| ObservabilityError::InvalidRule(format!("parse time_unix_nano: {e}")))?;
193194
let severity = OTelSeverityNumber::try_from(record.severity_number)?;
194195
let body = record.body.string_value.clone().unwrap_or_default();
195196
Ok(Self::new(time_unix_nano, severity, body))

scripts/wrkflw_test.sh

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
#!/usr/bin/env bash
2+
# wrkflw test harness — validate all docgen visualization pipeline stages locally.
3+
#
4+
# Usage:
5+
# ./scripts/wrkflw_test.sh # full pipeline
6+
# ./scripts/wrkflw_test.sh --validate # validate workflow YAML only
7+
# ./scripts/wrkflw_test.sh --stage S1 # run single stage
8+
# ./scripts/wrkflw_test.sh --list # list stages
9+
#
10+
# Exit codes:
11+
# 0 — all stages pass
12+
# 1 — one or more stages fail
13+
# 2 — usage error or missing prerequisites
14+
15+
set -euo pipefail
16+
export PATH="${HOME}/.cargo/bin:${PATH}"
17+
18+
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
19+
WRKFLW="${WRKFLW:-wrkflw}"
20+
STAGES_YAML="${ROOT}/.github/workflows/wrkflw-docgen.yml"
21+
DEFAULT_EMULATION="secure-emulation"
22+
23+
# ---- Color helpers ----
24+
green() { printf "\033[32m%s\033[0m\n" "$*"; }
25+
red() { printf "\033[31m%s\033[0m\n" "$*"; }
26+
yellow() { printf "\033[33m%s\033[0m\n" "$*"; }
27+
28+
# ---- Prerequisites ----
29+
check_prereqs() {
30+
if ! command -v "$WRKFLW" >/dev/null 2>&1; then
31+
red "error: wrkflw not found (set WRKFLW env or install via: cargo install wrkflw)"
32+
exit 2
33+
fi
34+
if [ ! -f "$STAGES_YAML" ]; then
35+
red "error: workflow file not found: $STAGES_YAML"
36+
exit 2
37+
fi
38+
}
39+
40+
# ---- List stages ----
41+
list_stages() {
42+
echo "wrkflw-docgen pipeline stages:"
43+
echo ""
44+
echo " S1 stage-1-rhai-parser-tests — mdbook-rhai-mermaid unit tests"
45+
echo " S2 stage-2-iso-lint — ledger-core iso lint tests"
46+
echo " S3 stage-3-viz-tests — ledger-core visualization/derive tests"
47+
echo " S4 stage-4-legal-z3 — legal Z3 solver integration tests"
48+
echo " S5 stage-5-docgen-build — mdBook build with rhai→mermaid injection"
49+
echo " S6 stage-6-kasuari-constraints — Kasuari constraint solver tests"
50+
echo " S7 stage-7-iso-objects — HasVisualization impl lint"
51+
echo " S8 stage-8-live-editor-js — browser-side live-editor JS tests"
52+
echo " S9 stage-9-xero-mcp — Xero MCP smoke test"
53+
echo ""
54+
echo "Commands:"
55+
echo " ./scripts/wrkflw_test.sh — full pipeline (all stages)"
56+
echo " ./scripts/wrkflw_test.sh --validate — YAML validation only"
57+
echo " ./scripts/wrkflw_test.sh --stage S5 — single stage (e.g. docgen build)"
58+
echo " ./scripts/wrkflw_test.sh --list — this list"
59+
}
60+
61+
# ---- Stage name mapper ----
62+
stage_name() {
63+
case "$1" in
64+
S1|s1) echo "stage-1-rhai-parser-tests" ;;
65+
S2|s2) echo "stage-2-iso-lint" ;;
66+
S3|s3) echo "stage-3-viz-tests" ;;
67+
S4|s4) echo "stage-4-legal-z3" ;;
68+
S5|s5) echo "stage-5-docgen-build" ;;
69+
S6|s6) echo "stage-6-kasuari-constraints" ;;
70+
S7|s7) echo "stage-7-iso-objects" ;;
71+
S8|s8) echo "stage-8-live-editor-js" ;;
72+
S9|s9) echo "stage-9-xero-mcp" ;;
73+
*) echo "unknown-stage-$1" ;;
74+
esac
75+
}
76+
77+
# ---- Main ----
78+
main() {
79+
check_prereqs
80+
81+
local mode="full"
82+
local stage_arg=""
83+
84+
while [ $# -gt 0 ]; do
85+
case "$1" in
86+
--validate|-v)
87+
mode="validate"
88+
shift
89+
;;
90+
--stage|-s)
91+
mode="stage"
92+
stage_arg="$(stage_name "$2")"
93+
shift 2
94+
;;
95+
--list|-l)
96+
list_stages
97+
exit 0
98+
;;
99+
--help|-h)
100+
list_stages
101+
exit 0
102+
;;
103+
*)
104+
red "unknown option: $1"
105+
list_stages
106+
exit 2
107+
;;
108+
esac
109+
done
110+
111+
case "$mode" in
112+
validate)
113+
yellow "=== Validating workflow: $STAGES_YAML ==="
114+
"$WRKFLW" validate "$STAGES_YAML"
115+
green "✓ Workflow validates"
116+
;;
117+
stage)
118+
yellow "=== Running single stage: $stage_arg ==="
119+
"$WRKFLW" run --job "$stage_arg" --runtime "$DEFAULT_EMULATION" "$STAGES_YAML"
120+
green "✓ Stage $stage_arg complete"
121+
;;
122+
full)
123+
yellow "=== wrkflw-docgen pipeline (full) ==="
124+
yellow "Step 1: Validate workflow"
125+
"$WRKFLW" validate "$STAGES_YAML"
126+
echo ""
127+
yellow "Step 2: Run all stages sequentially"
128+
"$WRKFLW" run --runtime "$DEFAULT_EMULATION" "$STAGES_YAML"
129+
green "✓ wrkflw-docgen pipeline complete"
130+
;;
131+
esac
132+
}
133+
134+
main "$@"

0 commit comments

Comments
 (0)