Contributing to Fukuii¶
Thank you for your interest in contributing to Fukuii! This document provides guidelines and instructions to help you contribute effectively.
Table of Contents¶
- Code of Conduct
- Getting Started
- Development Workflow
- Code Quality Standards
- Pre-commit Hooks
- Testing
- Submitting Changes
- Guidelines for LLM Agents
Code of Conduct¶
We are committed to providing a welcoming and inclusive environment for all contributors. Please be respectful and professional in all interactions.
Getting Started¶
Prerequisites¶
To contribute to Fukuii, you'll need:
- JDK 21 - Required for building and running the project
- sbt - Scala build tool (version 1.10.7 or higher)
- Git - For version control
- Optional: Python (for auxiliary scripts)
Scala Version Support¶
Fukuii is built with Scala 3.3.4 (LTS), the latest long-term support version of Scala 3, providing modern language features, improved type inference, and better tooling support.
Setting Up Your Development Environment¶
-
Fork and clone the repository:
-
Update submodules:
-
Verify your setup:
Quick Start with GitHub Codespaces¶
For the fastest setup, use GitHub Codespaces which provides a pre-configured development environment. See Codespaces Setup for details.
Development Workflow¶
-
Create a feature branch:
-
Make your changes following our Code Quality Standards
-
Test your changes thoroughly
-
Run pre-commit checks (see below)
-
Commit your changes with clear, descriptive commit messages
-
Push and create a Pull Request
Code Quality Standards¶
Fukuii uses several tools to maintain code quality and consistency:
Code Formatting with Scalafmt¶
We use Scalafmt for consistent code formatting. Configuration is in .scalafmt.conf.
Format your code:
Check formatting without changes:
Static Analysis with Scalafix¶
We use Scalafix for automated code refactoring and linting. Configuration is in .scalafix.conf.
Apply Scalafix rules:
Check Scalafix rules without changes:
Static Bug Detection with Scapegoat¶
We use Scapegoat for static code analysis to detect common bugs, anti-patterns, and code smells. Configuration is in build.sbt.
Run Scapegoat analysis:
This generates both XML and HTML reports in target/scala-3.3/scapegoat-report/. The HTML report is especially useful for reviewing findings in a browser.
Note: Scapegoat automatically excludes generated code (protobuf files, BuildInfo, etc.) from analysis.
Code Coverage with Scoverage¶
We use Scoverage for measuring code coverage during test execution. Configuration is in build.sbt.
Run tests with coverage:
This will:
1. Enable coverage instrumentation
2. Run all tests across all modules
3. Generate coverage reports in target/scala-3.3.4/scoverage-report/
4. Aggregate coverage across all modules
Coverage reports locations:
- HTML report: target/scala-3.3.4/scoverage-report/index.html
- XML report: target/scala-3.3.4/scoverage-report/cobertura.xml
Coverage thresholds: - Minimum statement coverage: 70% - Coverage check will fail if minimum is not met
Note: Scoverage automatically excludes: - Generated protobuf code - BuildInfo generated code - All managed sources
Combined Commands¶
Format and fix all code (recommended before committing):
Check all formatting and style (runs in CI):
Prepare for PR submission (format, style, and test):
Scala 3 Development¶
Fukuii uses Scala 3.3.4 (LTS) and JDK 21 (LTS) exclusively. The migration from Scala 2.13 and JDK 17 was completed in October 2025.
Key Scala 3 Features in Use:
- Native given/using syntax for implicit parameters
- Union types for flexible type modeling
- Opaque types for zero-cost abstractions
- Improved type inference
- Native derivation (no Shapeless dependency)
Build and Test:
Notes: - The project is Scala 3 only (no cross-compilation) - All dependencies are Scala 3 compatible - CI pipeline tests on Scala 3.3.4 with JDK 21 - See INF-001: Scala 3 Migration for the architectural decision - See Migration History for details on the completed migration
Pre-commit Hooks¶
To ensure code quality, we strongly recommend setting up pre-commit hooks that automatically check your code before each commit.
Option 1: Manual Git Hook (Recommended)¶
Create a pre-commit hook that runs formatting and style checks:
-
Create the hook file:
cat > .git/hooks/pre-commit << 'EOF' #!/bin/bash echo "Running pre-commit checks..." # Run scalafmt check echo "Checking code formatting with scalafmt..." sbt scalafmtCheckAll if [ $? -ne 0 ]; then echo "❌ Code formatting check failed. Run 'sbt scalafmtAll' to fix." exit 1 fi # Run scalafix check echo "Checking code with scalafix..." sbt "scalafixAll --check" if [ $? -ne 0 ]; then echo "❌ Scalafix check failed. Run 'sbt scalafixAll' to fix." exit 1 fi echo "✅ All pre-commit checks passed!" EOF -
Make it executable:
Option 2: Auto-fix Pre-commit Hook¶
This variant automatically fixes formatting issues before committing:
cat > .git/hooks/pre-commit << 'EOF'
#!/bin/bash
echo "Running pre-commit auto-fix..."
# Auto-format code
echo "Auto-formatting with scalafmt..."
sbt scalafmtAll
# Auto-fix with scalafix
echo "Auto-fixing with scalafix..."
sbt scalafixAll
# Add any formatted files back to the commit
git add -u
echo "✅ Pre-commit auto-fix complete!"
EOF
chmod +x .git/hooks/pre-commit
Option 3: Quick Check Hook (Faster)¶
For a faster pre-commit check that only validates changed files:
cat > .git/hooks/pre-commit << 'EOF'
#!/bin/bash
echo "Running quick pre-commit checks..."
# Get list of staged Scala files
STAGED_SCALA_FILES=$(git diff --cached --name-only --diff-filter=ACM | grep '\.scala$')
if [ -z "$STAGED_SCALA_FILES" ]; then
echo "No Scala files to check."
exit 0
fi
echo "Checking formatting of staged files..."
for file in $STAGED_SCALA_FILES; do
if [ -f "$file" ]; then
# Check if file is formatted (scalafmt will exit non-zero if formatting would change it)
if ! sbt "scalafmt --test $file" > /dev/null 2>&1; then
echo "❌ $file is not formatted. Run 'sbt scalafmtAll' to fix."
exit 1
fi
fi
done
echo "✅ Quick pre-commit checks passed!"
EOF
chmod +x .git/hooks/pre-commit
Bypassing Pre-commit Hooks¶
If you need to bypass the pre-commit hook in an emergency (not recommended):
IDE Integration¶
Most IDEs support automatic formatting on save:
IntelliJ IDEA¶
- Install the Scalafmt plugin
- Go to
Settings → Editor → Code Style → Scala - Select "Scalafmt" as the formatter
- Enable "Reformat on file save"
VS Code¶
- Install the Metals extension
- Enable format on save in settings:
Testing¶
Always run tests before submitting your changes:
Run all tests:
Run tests by tier (TEST-002):
# Tier 1: Essential tests (< 5 min)
sbt testEssential
# Tier 2: Standard tests with coverage (< 30 min)
sbt testCoverage
# Tier 3: Comprehensive tests (< 3 hours)
sbt testComprehensive
Run specific module tests:
Run integration tests:
Async Testing Best Practices¶
When writing tests for actor-based code using Pekko/Akka TestKit, follow these patterns to avoid flaky tests:
✅ DO: Use TestKit patterns for waiting
// Wait for a message with timeout
probe.expectMsg(5.seconds, expectedMessage)
// Wait for any message of a type
probe.expectMsgClass(classOf[MyMessage])
// Wait for a condition to become true
awaitCond(someCondition, 5.seconds)
// Verify no messages are received
// Note: Use this on probes that receive messages FROM the actor under test
// to verify it doesn't send unexpected messages
probe.expectNoMessage(1.second)
❌ DON'T: Use Thread.sleep
Why? Thread.sleep makes tests:
- Flaky: Timing can vary based on system load
- Slow: You wait the full duration even if the condition is met earlier
- Unreliable: No guarantee the actor has finished processing
Use ScalaTest's eventually for polling conditions:
import org.scalatest.concurrent.Eventually._
import org.scalatest.time.{Seconds, Span}
eventually(timeout(Span(5, Seconds))) {
// Condition that should eventually become true
stateChecker() shouldBe expectedValue
}
Actor IO Error Handling with Cats Effect¶
When using Cats Effect IO with actors, follow this pattern to ensure deterministic error propagation:
✅ DO: Use explicit error handling with IO.attempt and Status.Failure
import org.apache.pekko.actor.Status
private def pipeToRecipient[T](recipient: ActorRef)(task: IO[T]): Unit = {
implicit val ec = context.dispatcher
// Convert IO[T] into Future[Either[Throwable, T]] for explicit error handling
val attemptedF = task.attempt.unsafeToFuture()
// Map Left(ex) -> Status.Failure(ex) so recipients get a clear Failure message
val mappedF = attemptedF.map {
case Right(value) => value
case Left(ex) => Status.Failure(ex)
}
mappedF.pipeTo(recipient)
}
// Usage: piping to external actors (e.g., sender)
case GetSomething =>
pipeToRecipient(sender())(fetchSomething())
// Usage: piping to self (requires Status.Failure handler)
case StartAsyncOperation =>
pipeToRecipient(self)(performOperation())
case Status.Failure(ex) =>
log.warning("Async operation failed: {}", ex.getMessage)
// Handle failure appropriately
❌ DON'T: Use onError with unsafeToFuture().pipeTo()
// NEVER do this - creates race conditions and flaky tests
task
.onError(ex => IO(log.error(ex, "Error message")))
.unsafeToFuture()
.pipeTo(recipient)
Why? The onError approach causes:
- Race conditions: Logging and error delivery timing is non-deterministic
- Flaky tests: Tests that simulate errors may pass or fail unpredictably
- Unclear contract: The error handling isn't explicit in the code
For more information: - Actor IO Error Handling Pattern (INF-004)
For more information on test strategy and KPI baselines: - Test Suite Strategy and KPIs (TEST-002) - Testing Documentation - KPI Baselines - KPI Monitoring Guide
Submitting Changes¶
-
Ensure all checks pass:
-
Commit your changes:
- Use clear, descriptive commit messages
- Reference relevant issue numbers (e.g., "Fix #123: Description")
-
Keep commits focused and atomic
-
Push your branch:
-
Create a Pull Request:
- Provide a clear description of your changes
- Reference any related issues
- Ensure all CI checks pass
- Be responsive to review feedback
Pull Request Guidelines¶
- Title: Clear and descriptive (e.g., "Add support for EIP-1559" or "Fix memory leak in RPC handler")
- Description: Explain what changes were made and why
- Testing: Describe how you tested your changes
- Documentation: Update relevant documentation if needed
- Breaking Changes: Clearly mark any breaking changes
Continuous Integration¶
Our CI pipeline automatically runs on Scala 3.3.4:
- ✅ Compilation (compile-all)
- ✅ Code formatting checks (formatCheck - includes scalafmt + scalafix)
- ✅ Static bug detection (runScapegoat)
- ✅ Test suite with code coverage (testCoverage)
- ✅ Coverage reports (published as artifacts)
- ✅ Build artifacts (assembly, dist)
All checks must pass before a PR can be merged.
Releases and Supply Chain Security¶
Fukuii uses an automated one-click release process with full traceability.
When a release is created (via git tag vX.Y.Z), the release workflow automatically:
- ✅ Builds distribution package (ZIP) and assembly JAR
- ✅ Generates CHANGELOG from commits since last release
- ✅ Creates Software Bill of Materials (SBOM) in CycloneDX format
- ✅ Attaches all artifacts to GitHub release
- ✅ Builds and publishes container images to ghcr.io/chippr-robotics/chordodes_fukuii
- ✅ Signs images with Cosign (keyless, GitHub OIDC)
- ✅ Generates SLSA Level 3 provenance attestations
- ✅ Outputs immutable digest references for tamper-proof deployments
- ✅ Closes matching milestone
Release Artifacts: Each release includes: - Distribution ZIP with scripts and configs - Standalone assembly JAR - CHANGELOG.md with categorized changes - SBOM (Software Bill of Materials) - Signed Docker images with provenance
Making a Release:
Verify Release Images:
cosign verify \
--certificate-identity-regexp=https://github.com/chippr-robotics/fukuii \
--certificate-oidc-issuer=https://token.actions.githubusercontent.com \
ghcr.io/chippr-robotics/chordodes_fukuii:v1.0.0
Release Drafter:
Release notes are automatically drafted as PRs are merged. Use descriptive commit messages with prefixes:
- feat: for features
- fix: for bug fixes
- security: for security fixes
- docs: for documentation
See the CI/CD Documentation for detailed release process documentation.
Guidelines for LLM Agents¶
This section provides rules, reminders, and prompts for LLM agents (AI coding assistants) working on this codebase to ensure consistency and quality.
Agent Roles¶
We have specialized agents with different areas of expertise: - wraith 👻: Hunts down compilation errors and Scala 3 migration issues - mithril ✨: Transforms code using modern Scala 3 features - ICE 🧊: Manages large-scale migrations and strategic planning - eye 👁️: Ensures comprehensive testing and validation - forge 🔨: Handles consensus-critical code (EVM, mining, crypto) - herald 🧭: Fixes network protocol and peer communication issues - Morgoth 🎯: Shepherds all agents with process discipline and quality verification
See Agent Labels for detailed descriptions and Agent Definitions for full agent instructions.
Core Principles (Guided by Morgoth)¶
- Keep Documentation Essential: Focus on clarity and brevity. Avoid unnecessary verbosity or redundant explanations.
- Consistency Over Innovation: Follow existing patterns in the codebase rather than introducing new approaches.
- Minimal Changes: Make the smallest possible changes to achieve the goal. Don't refactor unrelated code.
- Verify Before Proceeding: When anything fails, stop and analyze before trying another approach.
- Incremental Progress: Make 3 changes, then verify. Don't accumulate unverified work.
Rules¶
- Code Style
- Always run
sbt formatAllbefore committing - Follow existing Scala idioms and patterns in the codebase
- Use the same naming conventions as surrounding code
-
Keep line length under 120 characters (configured in
.scalafmt.conf) -
Testing
- Write tests that match the existing test structure and style
- Run
sbt testAllto verify all tests pass - Don't modify unrelated tests unless fixing a bug
-
Integration tests go in
src/it/, unit tests insrc/test/ -
Documentation
- Update documentation when changing public APIs
- Keep comments concise and focused on "why" not "what"
- Don't add comments for self-explanatory code
-
Update README.md for user-facing changes
-
Package Structure
- All code uses package prefix
com.chipprbots.ethereum - Previously used
io.iohk.ethereum(from Fukuii project) - update if found -
Configuration paths use
.fukuii/not.fukuii/ -
Dependencies
- Don't add dependencies without justification
- Check for security vulnerabilities before adding dependencies
- Prefer libraries already in use in the project
Reminders¶
- JDK Compatibility: Code must work on JDK 21
- Scala Version: Code must compile on Scala 3.3.4 (LTS)
- Logging: Use structured logging with appropriate levels (DEBUG, INFO, WARN, ERROR)
- Logger Configuration: Update logback configurations when adding new packages
- Rebranding: This is a rebrand from "Fukuii" to "Fukuii" - update any remaining "fukuii" or "io.iohk" references
- Commit Messages: Use clear, descriptive commit messages in imperative mood
- Git Hygiene: Don't commit build artifacts, IDE files, or temporary files
Prompts for Common Tasks¶
When working with Scala 3 code:
1. Use Scala 3 native features (given/using, union types, opaque types)
2. Leverage improved type inference
3. Avoid Scala 2-style implicit conversions
4. Use native derivation instead of macro-based approaches
5. Follow Scala 3 best practices and idioms
When fixing tests:
1. Identify the root cause of the failure
2. Check if it's related to rebranding (fukuii→fukuii, io.iohk→com.chipprbots)
3. Check logger configurations in src/test/resources/ and src/it/resources/
4. Run the specific test to verify the fix
5. Run full test suite to ensure no regressions
When adding new features:
1. Follow existing patterns in similar features
2. Add comprehensive tests (unit + integration if needed)
3. Update documentation (README, scaladoc)
4. Run formatCheck and linters
5. Ensure JDK 21 compatibility
When refactoring:
1. Keep changes minimal and focused
2. Don't mix refactoring with feature work
3. Ensure all tests pass before and after
4. Maintain backward compatibility unless breaking changes are approved
When updating dependencies:
1. Always use the latest stable versions to avoid future update cycles
2. Check the GitHub Advisory Database for known vulnerabilities
3. Verify compatibility with project requirements:
- JDK 21 compatibility
- Scala 3.3.4 support (primary version)
4. Test thoroughly on JDK 21
5. Update version numbers in project/Dependencies.scala
6. Document any breaking changes or migration steps
7. Update security-sensitive dependencies (Netty, BouncyCastle, etc.) to latest patch versions
Quality Checklist¶
Before submitting a PR, verify:
- [ ] sbt formatCheck passes
- [ ] sbt compile-all succeeds
- [ ] sbt testAll passes (on JDK 21)
- [ ] sbt "IntegrationTest / test" passes for integration tests
- [ ] No new compiler warnings introduced
- [ ] Documentation updated for user-facing changes
- [ ] Commit messages are clear and descriptive
- [ ] No debugging code or print statements left in
Additional Resources¶
- 📖 Hosted Documentation - Browsable documentation site
- CI/CD Documentation
- Getting Started
- Branch Protection
- Architectural Decision Records
- Migration History
- Static Analysis
- Scalafmt Documentation
- Scalafix Documentation
Questions or Issues?¶
If you have questions or run into issues: 1. Check the GitHub Issues 2. Review existing discussions 3. Open a new issue with a clear description of your question or problem
Thank you for contributing to Fukuii! 🚀