Get a fresh contributor (human or agent) from a clean machine to a green local build, signed-commit-ready, in one pass. Pairs with
release.md,rollback.md, andengineering-standards.md.
- Repo cloned at
~/projects/codeiqwith the offline build path verified. - Java 25 + Maven 3.9 on PATH.
- A signed-commit configuration (ssh) bound to your
id_ed25519key. mvn verifyexits 0 onmain.codeiqCLI runs end-to-end against this repo as a smoke target.
If any step fails, stop and follow the troubleshooting note inline — do not "fix forward" against a partially-set-up machine.
| Tool | Min version | Notes |
|---|---|---|
| Java | 25 | Required by pom.xml maven-enforcer-plugin ([25,)). Use Adoptium / Temurin. |
| Maven | 3.9.x | Newer minor versions are fine; do not use 4.x snapshots. |
| Git | 2.34+ | Required for commit signing in any of the supported formats (gpg.format = ssh, openpgp / gpg, or x509). |
| OpenSSH | 8.0+ | Required only for gpg.format=ssh (the default; bundles ssh-keygen -Y verify). Skip if you sign with OpenPGP or x509. |
| GnuPG | 2.2+ | Required only for gpg.format=openpgp / gpg. Skip if you sign with SSH or x509. |
| Node.js | 20.x LTS | Only needed for the bundled React UI — mvn package shells out to it via the frontend Maven plugin. |
gh CLI |
2.40+ | For PR/release plumbing. |
Verify in one shot:
java --version | head -1 # openjdk 25 ...
mvn -v | head -1 # Apache Maven 3.9.x
git --version # git version 2.x
ssh -V # OpenSSH_8.x or newer
node --version # v20.x
gh --version | head -1 # gh version 2.xgit clone git@github.com:RandomCodeSpace/codeiq.git ~/projects/codeiq
cd ~/projects/codeiqApply the repo-local signed-commit config (this is what RAN-46 AC #2 codifies):
./scripts/setup-git-signed.shThat script is idempotent and is the single SSoT for the per-repo git config --local block. It writes user.name, user.email, user.signingkey, gpg.format, commit.gpgsign=true, tag.gpgsign=true, then verifies the configured key resolves in your keychain.
The script picks up your preferred signing format from (in order) the GIT_GPG_FORMAT env var, your global git config gpg.format, or the ssh default. Per-format expectations:
ssh(default) —user.signingkeymust be a path on disk to your public key (typically~/.ssh/id_ed25519.pub). If you do not have an ed25519 keypair, generate one (ssh-keygen -t ed25519 -C "you@example.com") and upload the public key to your GitHub account underSettings → SSH and GPG keys → New SSH key → Key type: Signing Keybefore re-running.openpgp/gpg—user.signingkeymust be a key id or fingerprint thatgpg --list-secret-keysknows about. Generate / import the key first (gpg --full-generate-key), thengit config --global user.signingkey <KEY_ID>andgit config --global gpg.format openpgpbefore running this script.x509—user.signingkeymust be a key id or fingerprint thatgpgsm --list-secret-keysknows about. Configure x509 signing keys ingpgsmfirst.
Sanity-check the config:
git config --local --get user.signingkey # ssh: a .pub path; openpgp/x509: a key id or fingerprint
git config --local --get gpg.format # ssh | openpgp | gpg | x509
git config --local --get commit.gpgsign # should print "true"
# Produce a throwaway signed commit object (no refs touched) and verify it.
sig_commit=$(echo "verify-signing" | git commit-tree HEAD^{tree} -S)
git verify-commit "$sig_commit" # expect "Good ... signature"
git log -1 --pretty=%G? "$sig_commit" # expect: Ggit verify-commit operates on a commit object id, not stdin — capturing the
output of git commit-tree -S first and then verifying that id is the right
shape. If the verification line errors with "no principal matched", point git
at an allowed_signers file: see scripts/setup-git-signed.sh output for the
canonical template.
The standard offline path is:
mvn -B -ntp -DskipTests=false clean verifyThis runs the full pipeline: unit tests, integration tests, jacoco coverage gate (≥85%), SpotBugs, OWASP Dependency-Check, and the executable CLI JAR build. Expect ~2-3 min on a warm cache.
For a faster inner loop while iterating:
mvn -B -ntp test \
-Dspotbugs.skip=true -Ddependency-check.skip=true # unit tests only (Surefire), no static analysis / CVE plugins
mvn -B -ntp -Dtest=SomeDetectorTest test # single unit test class
mvn -B -ntp -DskipTests=true package # JAR only, no tests
mvn -B -ntp verify \
-Dspotbugs.skip=true -Ddependency-check.skip=true # unit + integration tests (Surefire + Failsafe), no static analysis / CVE pluginsThe first command does run tests — earlier drafts incorrectly passed -DskipTests here, which would have skipped them. Reviewer finding cf64b44d (RAN-47, R5-3): Maven's test phase only runs Surefire (unit tests). This repo's integration tests are wired through Failsafe at the integration-test / verify phases — use the fourth form above when you need both unit + integration in the inner loop. Use -Dspotbugs.skip / -Ddependency-check.skip to keep things fast without dropping test coverage.
Smoke-test the CLI end-to-end against this repo:
java -jar target/code-iq-*-cli.jar version
java -jar target/code-iq-*-cli.jar index .
java -jar target/code-iq-*-cli.jar enrich .
java -jar target/code-iq-*-cli.jar serve . & # opens http://localhost:8080
curl -fsS http://localhost:8080/api/stats > /dev/null && echo OK
kill %1If you want to mirror the CI gate before pushing:
mvn -B -ntp clean verify # tests + jacoco
mvn -B -ntp spotbugs:check # static analysis gate
mvn -B -ntp dependency-check:check -DfailBuildOnCVSS=7 # CVE gateSonar runs only in CI (the token is not on local machines by design).
Create branches off main:
git fetch origin main
git switch -c <type>/<short-slug> origin/mainConventional-commit subjects (feat:, fix:, chore:, refactor:, test:, docs:). One logical change per commit. Sign every commit (the local config makes this automatic). Push and open a PR:
git push -u origin HEAD
gh pr create --fill --base mainBranch protection on main requires:
- A Codex review approval from TechLead (or delegate).
- CI green on the PR:
ci-java.yml(build + jacoco 85% + dependency-check + Sonar), the repo-level CodeQL default-setup checks (Analyze (java-kotlin),Analyze (javascript-typescript),Analyze (actions)), Socket Security, SonarCloud Code Analysis. - All commits in the PR signed (branch protection rejects unsigned commits — there is no separate "signed-commits" status check).
- OpenSSF Scorecard runs on push-to-
mainand a weekly cron, not on PRs, and is intentionally non-gating perengineering-standards.md§1.
Force-push to main is disabled. Direct pushes are disabled. Squash-merge is the default and only path.
- Architecture, layout, and convention SSoT:
/CLAUDE.md. - Coverage / Sonar / CVE policy:
engineering-standards.md. - Releasing:
release.md. - Rolling back a bad release:
rollback.md. - Security reporting:
/SECURITY.md.
If you hit anything that looks like a runtime gap (missing tool, broken hook, weird auth), open a Paperclip issue against type:devx rather than working around it locally — the bootstrap is meant to be reproducible.