mirror of
https://github.com/nearai/ironclaw.git
synced 2026-09-03 08:06:01 +08:00
* chore(ci): dev metrics + composition mass ratchet gate
Adds a three-tier development-metrics tool and a guardrail that stops the
ironclaw_reborn_composition crate from accreting more of the codebase.
scripts/dev_metrics.py — three tiers from git + GitHub + working tree:
- Tier 1 flow/speed: PR lead time, size distribution, merge cadence
- Tier 2 quality/stability: change-failure proxy, rework, test share
- Tier 3 codebase health: composition mass, v1 src burndown, file sprawl,
abstraction density, boundary-test coverage
Composition mass ratchet — the dependency-boundary tests police edges
*between* crates but are blind to mass piling up *inside* one crate.
ironclaw_reborn_composition is charter-bound to assembly-only wiring yet is
now ~26.7% of all production crate code. This gate is that missing guard:
- scripts/ci/composition-budget.toml — committed ceiling (enforce +
tolerance), modeled on the existing coverage-floor ratchet
- scripts/ci/check-composition-budget.sh — pure-bash gate; one-directional
(fails only on growth past the ceiling), emits a down-ratchet nudge as
carve-outs free up slack
- scripts/ci/test-check-composition-budget.sh — 22 assertions / 10 fixture
cases incl. a guard that the real tree passes the committed budget
Wiring:
- CI: new composition-budget job in code_style.yml (runs the gate + self-
tests it, registered in the aggregating code-style gate)
- Local: pre-commit-safety.sh runs the gate when composition or the gate
itself is staged; dev-setup.sh install message updated
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix(ci): address review — production-only metric, script hardening, dev-metrics tests
Review feedback on #6167 (gemini, ironloopai, coderabbit):
Blocking — gate counted test-only code despite its documented "tests
excluded" contract. Exclude test-only FILES (tests.rs/test_*.rs/*_tests.rs
and /tests/ dirs) from both numerator and denominator; rebaseline the
ceiling 2670 -> 2398 bp (26.70% -> 23.98%). Inline #[cfg(test)] modules
remain a documented, symmetric residual (a line-counter can't parse them).
Added a regression case proving test files are excluded.
check-composition-budget.sh: toml_get no longer aborts under set -e +
pipefail when a key is missing (|| true) so schema validation is reached;
added a missing-key regression case.
test-check-composition-budget.sh: set -euo pipefail (repo invariant);
SIGPIPE-safe capture + fixture generation; pure-bash asserts (no pipes).
dev_metrics.py: bound `gh` with a 30s timeout and treat non-JSON output as
unavailable; fix the trait-impl density regex to count `impl<T> ... for`
generics; harden find/grep/wc probes with pipefail + rc checks (no more
false-zero metrics); UTF-8 file writes; surface the gate-aligned production
share as the ratchet metric and relabel the byte-based trend as a distinct,
coarser measurement; extract a pure classify_commit helper.
New scripts/test_dev_metrics.py — caller-level unit tests for
classification, percentiles, change-failure bucketing, rendering, and the
test-file/impl regexes; wired into the composition-budget CI job.
pre-commit hook: trigger on any staged crates/**.rs change (the metric is a
ratio) and document the working-tree/CI-authoritative limitation.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix(ci): harden PR classifier against transient GitHub API flakes
The classify job (#6167 CI) failed with `invalid character '<' looking
for beginning of value`: a transient API error returned an HTML page,
`gh --jq` aborted, and under `set -e` the whole labels-only job failed
and blocked the PR.
pr-labeler.sh now:
- routes every gh call through a `gh_retry` wrapper (retry + linear
backoff), and
- treats each classifier as best-effort — a step that still can't fetch
after retries only emits a `::warning::` and the script exits 0, so
labeling never gates a merge.
Two bash traps fixed along the way, both caught by the new test:
- a bare `if cmd; then …; fi` resets `$?` to 0 after `fi`, so gh_retry's
give-up looked like success — capture rc in the `else`;
- `set -e` is suppressed inside a function on the left of `||`, so the
classifiers check their own fetches explicitly instead of relying on
errexit.
Regression test: .github/scripts/test-pr-labeler.sh (retry/backoff,
give-up, and end-to-end non-fatal + happy-path via a fake `gh`), wired
into the code_style "Static-check self-tests" step and the has_code
path filter so it runs when the labeler or its test changes.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* feat(ci): add dispatch (Arc<dyn>) ratchet + dev-metrics dispatch signals
Companion to the mass ratchet for the "reduce traits & dispatch" goal
(#6168 / runtime-decomposition plan #4471).
check-composition-budget.sh now enforces TWO metrics: composition's share of
production crate code (existing) AND its Arc<dyn> dispatch count. The dispatch
count is scoped to composition production files EXCLUDING src/slack and
src/extension_host — those are owned by the separate channel/extension
refactor, so this gate must not govern or trip on their work. One-directional
like the mass ratchet: only trips on growth; nudges when slack accrues.
composition-budget.toml: arc_dyn_ceiling = 1093 (current governed count),
tolerance 15.
test harness: +6 dispatch cases (within / breach / dry-run / slack+extension
exclusion / missing-key schema error); budget() helper carries the dispatch
keys; count_arc_dyn tolerates no-match under set -e + pipefail. 36 cases pass.
dev_metrics.py: Tier-3 reports governed Arc<dyn> count and distinct dyn-trait
count (the dispatch-breadth trend), matching the ratchet scope.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
89 lines
3.4 KiB
Bash
Executable File
89 lines
3.4 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Developer setup script for IronClaw.
|
|
#
|
|
# Gets a fresh checkout ready for development without requiring
|
|
# Docker, PostgreSQL, or any external services.
|
|
#
|
|
# Usage:
|
|
# ./scripts/dev-setup.sh
|
|
#
|
|
# After running, you can:
|
|
# cargo check # default features (postgres + libsql)
|
|
# cargo test # default test suite (uses libsql temp DB)
|
|
# cargo test --all-features # full test suite (requires Node.js 22 + Corepack/pnpm for WebUI bundle)
|
|
|
|
set -euo pipefail
|
|
|
|
cd "$(dirname "$0")/.."
|
|
|
|
echo "=== IronClaw Developer Setup ==="
|
|
echo ""
|
|
|
|
# 1. Check rustup
|
|
if ! command -v rustup &>/dev/null; then
|
|
echo "ERROR: rustup not found. Install from https://rustup.rs"
|
|
exit 1
|
|
fi
|
|
echo "[1/6] rustup found: $(rustup --version 2>/dev/null | head -1)"
|
|
|
|
# 2. Add WASM target (required by build.rs for channel compilation)
|
|
echo "[2/6] Adding wasm32-wasip2 target..."
|
|
rustup target add wasm32-wasip2
|
|
|
|
# 3. Install wasm-tools (required by build.rs for WASM component model)
|
|
echo "[3/6] Installing wasm-tools..."
|
|
if command -v wasm-tools &>/dev/null; then
|
|
echo " wasm-tools already installed: $(wasm-tools --version)"
|
|
else
|
|
cargo install wasm-tools --locked
|
|
fi
|
|
|
|
# 4. Verify the project compiles
|
|
echo "[4/6] Running cargo check..."
|
|
cargo check
|
|
|
|
# 5. Run tests using libsql temp DB (no Docker/external DB needed)
|
|
echo "[5/6] Running tests (no external DB required)..."
|
|
cargo test
|
|
|
|
# 6. Install git hooks
|
|
echo "[6/6] Installing git hooks..."
|
|
HOOKS_DIR=$(git rev-parse --git-path hooks 2>/dev/null) || true
|
|
if [ -n "$HOOKS_DIR" ]; then
|
|
mkdir -p "$HOOKS_DIR"
|
|
SCRIPTS_ABS="$(cd "$(dirname "$0")" && pwd)"
|
|
ln -sf "$SCRIPTS_ABS/commit-msg-regression.sh" "$HOOKS_DIR/commit-msg"
|
|
echo " commit-msg hook installed (regression test enforcement)"
|
|
ln -sf "$SCRIPTS_ABS/pre-commit-safety.sh" "$HOOKS_DIR/pre-commit"
|
|
echo " pre-commit hook installed (UTF-8, case-sensitivity, /tmp, redaction, composition-mass ratchet)"
|
|
REPO_ROOT="$(git rev-parse --show-toplevel)"
|
|
ln -sf "$REPO_ROOT/.githooks/pre-push" "$HOOKS_DIR/pre-push"
|
|
echo " pre-push hook installed (quality gate + optional delta lint)"
|
|
else
|
|
echo " Skipped: not a git repository"
|
|
fi
|
|
|
|
echo ""
|
|
# Codebase knowledge graph (codebase-memory MCP) — powers agent code discovery.
|
|
# Single static binary, no deps, no API keys, 100% local. See CLAUDE.md -> "Code Discovery".
|
|
if command -v codebase-memory-mcp &>/dev/null; then
|
|
echo "[graph] codebase-memory-mcp found: $(command -v codebase-memory-mcp)"
|
|
else
|
|
echo "[graph] Installing codebase-memory-mcp (agent code-discovery graph)..."
|
|
if curl -fsSL https://raw.githubusercontent.com/DeusData/codebase-memory-mcp/main/install.sh | bash; then
|
|
echo " installed. The repo's .mcp.json wires it into Claude Code automatically."
|
|
else
|
|
echo " WARN: install failed — agents will fall back to grep."
|
|
echo " Install manually: https://github.com/DeusData/codebase-memory-mcp"
|
|
fi
|
|
fi
|
|
|
|
echo ""
|
|
echo "=== Setup complete ==="
|
|
echo ""
|
|
echo "Quick start:"
|
|
echo " cargo run # Run with default features"
|
|
echo " cargo test # Test suite (libsql temp DB)"
|
|
echo " cargo test --all-features # Full test suite (requires Node.js 22 + Corepack/pnpm for WebUI bundle)"
|
|
echo " cargo clippy --all-features # Lint all code (requires Node.js 22 + Corepack/pnpm for WebUI bundle)"
|