STIG Help

Source cleanup and static checks

STIG exposes one mutating source-maintenance entry point and one read-only gate:

./gradlew --no-configuration-cache cleanup ./gradlew --no-configuration-cache cleanupCheck

cleanup regenerates both third-party notice files through generateThirdPartyNotices, applies deterministic, reviewable fixes, and then runs cleanupCheck. Notice generation finishes before IDEA formatting and structural Markdown checks. Some analyzers only report problems; their changes require developer review. Full IntelliJ IDEA Code Cleanup and Optimize Imports remain periodic interactive operations because IDEA's format.sh CLI only reformats files.

Correct local order

For a fully verified commit, use this order:

./gradlew --no-configuration-cache cleanup # Review generated notices and every source mutation. PYTHONHASHSEED=0 graphify update . ./gradlew --no-daemon --stacktrace --no-configuration-cache preReleaseCheck

No additional build, test, integrationTest, or cleanupCheck invocation is needed. cleanup already ends with cleanupCheck; preReleaseCheck depends on releaseCoreVerification, cleanupCheck, Dokka, Writerside container inspection, IDEA-plugin verification, and Qodana. The release core explicitly builds the root and every subproject, which reaches the unit, functional, analyzer integration, and browser-render test suites.

Keep these as two sequential Gradle invocations. The first intentionally mutates sources and must finish before the second verifies the resulting revision. The read-only preReleaseCheck must not depend on cleanup, so verification reports drift without rewriting sources. cleanupCheck and verifyThirdPartyNotices do not schedule notice generation; their standalone invocations check the existing files. Formatting and formatting comparisons run only on developer machines. CI runs ciBuildAndTest, which includes releaseCoreVerification and the non-formatting static checks, and its specialized documentation/plugin jobs; it invokes neither cleanup nor cleanupCheck.

The rendered IDEA editor tests require an X11 display. In a shell without a desktop display, run the verification command or scripts/submit.sh --interactive under xvfb-run --auto-servernum --server-args="-screen 0 1920x1080x24". Install the host's Xvfb and Xauthority packages first; do not disable the GUI tests to accommodate a headless shell. The self-contained :stig-idea-plugin:modelEditorUiTest suite participates in automatic coverage and release gates. The separate :stig-idea-plugin:analysisDemoUiTest task generates evidence from an external checkout selected with -PstigUiDemoRoot=/absolute/path/to/stig-pth-ui-demo; invoke it explicitly. Coverage does not schedule that local demo task.

Qodana imports Gradle through the IDE tooling API, which bypasses the wrapper launcher. qodanaPrepare registers the approved Gradle JVM as STIG approved Java in build/qodana/config, and qodana.yaml selects that name. The scan passes that private configuration through Qodana's QODANA_CONF environment variable. Its IDE cache is keyed by the approved Java home, so a serialized workspace model cannot restore SDKs from an earlier runtime. The registration uses the current pinned Java home and its module inventory; it is refreshed after Java pin changes. It does not change the developer's global IDEA SDK table or ask Qodana to download a second JDK by feature number. The normal settings validation still rejects any different Gradle runtime. Consumers without their own Qodana configuration receive the packaged recommended profile and approved SDK selection. A consumer's authored qodana.yaml should also select projectJDK: "STIG approved Java"; an explicit contradictory Java selection remains subject to the normal runtime guard.

Desktop IDEA Code Cleanup and Optimize Imports may be run before ./gradlew --no-configuration-cache cleanup. They apply interactive inspection fixes that the headless formatter cannot apply. If they are skipped, ideaFormat still enforces formatting but does not substitute for those inspection-based operations.

Task ownership

Owner

cleanup

cleanupCheck

IDEA 2026.2

Reformats version-controlled and unignored new Kotlin, Kotlin scripts, Java, Gradle scripts, JavaScript, MJS, XML, HTML, Writerside CFG, FreeMarker, Markdown, JSON, YAML, TOML, properties, and SVG in one process

Formats temporary copies with the same IDEA and fails if their bytes differ

Shell

Runs shfmt

Runs shfmt -d and ShellCheck

C/C++ analyzer

Runs the host ClangFormat

Runs host-matched ClangFormat and ClangTidy, plus the warning-as-error CMake build using its generated compile_commands.json

Viewer web sources

Runs ESLint and Stylelint safe fixes

Runs ESLint and Stylelint with zero warnings

Markdown

Uses IDEA as the only formatter

Runs structural markdownlint rules; the normal Writerside pre-release/CI build performs semantic documentation inspection

JSON/YAML

Uses IDEA as the only formatter

Strict Kotlin parsing rejects malformed input, duplicate keys, unsafe YAML construction, excessive aliases, and excessive nesting

GitLab CI

Uses IDEA's YAML formatter

Strict YAML is local; GitLab performs its semantic CI lint while creating the pipeline

The pinned formatter and desktop IDEA share .idea/codeStyles/Project.xml. IDEA owns JavaScript and MJS formatting; ESLint remains the semantic web-source fixer and runs before IDEA when both mutating tasks are scheduled. There is no second Markdown formatter, ShellCheck and ClangTidy do not rewrite files, and IDEA's mask excludes shell, C/C++, and CSS. Both the project code style and the Gradle cleanup input filter exclude .kte files: JTE Kotlin templates mix JTE directives with C++, Markdown, Gradle Kotlin DSL, or another output language, while IDEA treats the whole file as Kotlin and can split or reindent the generated-language syntax. Template authors therefore own their exact layout. The headless formatter does not load the Writerside file type, so the cleanup wrapper presents writerside.cfg to the same IDEA formatter as XML while preserving the original file name in the repository.

IDEA receives files discovered by git ls-files --cached --others --exclude-standard. A recursive formatter invocation over the repository root is intentionally not used: IDEA's formatter traverses ignored node_modules, Gradle outputs, generated Dokka HTML, and machine-local .idea state. The input selector ignores a tracked path that has already been deleted from the working tree but remains in the Git index until the pending deletion is committed; shared tracked-file cleanup checks apply the same existing-file rule. IDEA continues to include existing untracked, non-ignored files. The Dokka page and viewer bundles (stig-bundle.* and stig-viewers.*) are ignored outputs of stigDokkaBundle, so the cleanup input omits them. Their authored JavaScript and CSS remain covered by the formatter and web-source checks as applicable. The shared IDEA code-style file excludes checked-in generated release notes, third-party notices, and the icon sprite from both desktop and headless formatting: their producing Gradle tasks own their exact bytes and the release gate verifies them independently. The entire graphify-out/ tree is excluded for the same reason: run the deterministic Graphify refresh after the final cleanup mutation, then verify that revision once with preReleaseCheck. Structural Markdown and JSON checks still validate applicable Graphify artifacts without rewriting them. These generated notices, release notes, and the icon sprite are also omitted from the formatter's input list, so their generated layout remains unchanged.

The exact tracked paths .idea/gradle.xml, .idea/misc.xml, and .idea/kotlinc.xml are excluded from both formatter selection and the shared code style. Gradle import and the IDE project store, including Qodana's cached project, own their project and compiler-settings serialization. Qodana and ordinary IDEA imports use the shared STIG approved Java SDK name; the approved installation path belongs to each IDE's own SDK table. The input selector also omits .idea/vcs.xml and .idea/codeStyles/Project.xml, whose serialization the IDE project store owns. Reformatting these files can make a later IDE save change them back and invalidate the submission fingerprint. Their settings remain tracked and included in submission fingerprints; this is not a Git ignore or a verification waiver. The shared code-style file remains a formatter configuration input, so its settings still govern formatting and changes invalidate the task. Other tracked .idea XML remains formatter input.

ideaFormatCheck formats a temporary mirror instead of using IDEA's -d switch. IDEA 2026.2 can report Kotlin Gradle scripts as needing reformatting even when a normal formatter run makes no byte change. Comparing normal formatter output keeps the check aligned with what ideaFormat can actually fix and avoids that CLI dry-run false positive.

Tooling

Run scripts/setup.sh on a new developer machine, or scripts/setup.sh --cleanup-tools-only when the normal build toolchain is already installed. It installs ShellCheck, shfmt, and ClangFormat/ClangTidy matching the host compiler. CI does this once while building the STIG toolchain image; ordinary build jobs do not run a package manager. The analyzer's stig-code-analyzer/scripts/setup.sh installs the remaining native toolchain, including the separately pinned LLVM 18 libraries. Pinned Node/npm dependencies provide ESLint, Stylelint, and markdownlint. The pinned IDEA distribution is resolved through the IntelliJ Platform Gradle Plugin and reused by plugin compilation, verification, and cleanup.

All repository-owned Kotlin/Java and analyzer C/C++ compiler warnings are errors. Third-party IDE layout warnings and diagnostics emitted from system or dependency headers are not reclassified as STIG source warnings.

The root .clang-tidy is the single profile for analyzer-source checks in editors, local Gradle runs, and CI. It selects the established analyzer, bugprone, performance, portability, and modernization checks applicable to STIG. The profile does not enable unrelated project conventions such as LLVM libc, Fuchsia, or FPGA-specific rules. The scan includes production and unit-test translation units from the analyzer's compile_commands.json, with diagnostics from their project headers. Separately compiled LLVM IR input fixtures and third-party translation units are outside this scan; system-header diagnostics remain disabled. All reported warnings fail the gate. Findings require review before being treated as confirmed defects. The task never applies fixes.

The host Clang generation must match the compiler recorded in compile_commands.json; LLVM 18 remains the separate linked-library and analyzed-bitcode pin. The sibling PhASAR repository owns its separate check selection in its root .clang-tidy, used by the check-phasar-cpp CMake target.

The normal :stig-code-analyzer:cleanupCppTidyCheck deliberately remains host-matched, including ClangTidy 22 on a Clang 22 developer host. The separate, opt-in ciToolchainCheck runs the complete shared ciBuildAndTest aggregate inside the content-addressed Fedora 44 CI image. This covers builds, tests and static checks against CI's actual compiler and system headers. Matching the distribution name alone does not establish tool-version parity. New path-2/3 submissions leave local image preparation and this check off; use submit.sh --local-container-checks on only when the user requests local CI reproduction. Host checks and GitLab release gates remain required. See submission options. For a focused native lint investigation, run:

./gradlew --no-daemon --stacktrace --no-configuration-cache ciToolchainTidyCheck

When explicitly selected, both container check tasks always execute; the former stig.ciToolchainTidy property does not skip them. Missing images, container startup failures, test failures, and lint diagnostics fail the selected gate. They snapshot Git-tracked and unignored files, including unstaged edits, new files, deletions, executable permissions, symbolic links, and the current Git revision. Current files are staged only in the snapshot's private Git index, so Git-based checks also inspect new files that are not yet tracked in the developer's checkout. Each check mounts that snapshot read-only at /source and copies it into a writable /workspace inside the disposable container. Gradle 9.5 requires writable project directories even when the selected task only reports findings. The source checkout and its Git index remain unchanged. Each task removes its temporary snapshot after success or failure. On Linux it defaults to Podman; select Docker with -Pstig.ciToolchainContainerRuntime=docker.

When image inputs have changed and the new tag has not been published, build the matching image locally with ./gradlew ciToolchainImageBuild before an explicit ciToolchainCheck or ciToolchainTidyCheck. This uses the same Dockerfile and input hash as GitLab, and never pushes an image. A missing image must not turn the verification task into a successful skip.

preReleaseCheck depends on the complete host cleanupCheck. GitLab CI and the optional local Fedora container run the same ciBuildAndTest aggregate, as documented in Build and test. Developer-side cleanup and preReleaseCheck remain the authoritative format gates. Writerside and IDEA plugin verification remain separate jobs because they use specialized environments.

23 October 2026