--- name: video-editing-build-and-env description: Load this skill when reproducing or repairing the build environment on macOS, Linux/VPS, or a cloud build runner; when Maven, Java 21, FFmpeg/ffprobe, Python runtimes, local model files, executable permissions, architecture compatibility, offline dependency resolution, clean-checkout reproducibility, or test working-directory assumptions are involved; or when designing the dependency-locked and network-isolated build supply chain. Do not load it for an already-built service's runtime symptom. --- # Build and Environment Use this runbook from the repository root. Treat every path and version below as a verified description of `HEAD` on **2026-07-21**, unless it is explicitly labeled `TARGET`. ## Use this skill for - Recreating a build environment on macOS, Linux/VPS, or a cloud build runner. - Deciding whether a failure comes from Java, Maven, FFmpeg, Python, a missing local model, permissions, CPU architecture, or an unclean workspace. - Running focused tests, the current Maven gate, or a clean archived-checkout experiment. - Designing the future reproducible, dependency-locked, offline build and runtime supply chain. ## Do not use this skill for | Need | Load instead | |---|---| | Starting schedulers, processing media, locating outputs, or deployment operation | `video-editing-run-and-operate` | | Changing application properties or worker flags | `video-editing-config-and-flags` | | Deciding what evidence proves media or creative quality | `video-editing-validation-and-qa` | | Diagnosing a runtime symptom after the environment is known good | `video-editing-debugging-playbook` | | Learning why the clean-checkout and local-asset traps exist | `video-editing-failure-archaeology` | | Promoting a toolchain, dependency, image, model, or default change | `video-editing-change-control` | Do not use a successful compile or test run as proof of cinematic quality, production readiness, security, or operability. Terms: **SBOM** means Software Bill of Materials; **OCI** means Open Container Initiative image format. ## Non-negotiable environment boundary Enforce these rules in development, CI, image construction, and production: 1. Do not allow application startup or validation to install a package, fetch a model, contact an external AI service, or access the network. 2. Do not run `tools/run_local_cv_worker.sh` or `tools/run_local_asset_worker.sh` as setup commands. Their default `BOOTSTRAP_MODE=auto` can create virtual environments and invoke `pip`; the CV launcher can also cause Ultralytics to fetch YOLO weights. 3. Provision Maven artifacts, Python wheels, FFmpeg, local model weights, fonts, LUTs, music, and sound effects only in an approved build/image process. Record version, SHA-256 checksum, origin, license, target OS, target CPU architecture, and approval for every non-source artifact. 4. Run the delivered service and its validation offline. Missing dependencies or models must fail closed; do not replace them with downloads, silence, tones, host speech utilities, heuristics, or unlicensed assets. 5. Do not change production-facing defaults to make a build pass. Route such a change through `video-editing-change-control`. The current source still violates parts of this boundary: the standalone launchers bootstrap automatically and local CV can fall back to heuristics. Asset generation itself now rejects missing local models and placeholder output, and strict asset readiness fails startup. Treat the remaining launcher/CV behavior as open defects, not approved procedures. ## Current baseline and gaps | Component | Current repository fact | Production interpretation | |---|---|---| | Java | `pom.xml` sets `java.version` to `21`; compilation uses Java release 21. | Use a supported Java 21 LTS JDK for the current code. Do not infer vendor or patch level from the POM. | | Spring Boot | Parent is `org.springframework.boot:spring-boot-starter-parent:3.3.2`. | This is the implemented version, not a claim that it is the latest supported release. Upgrade only through change control with compatibility evidence. | | Build tool | Maven project with `pom.xml`; no `mvnw`, Maven wrapper metadata, or Gradle files exist. | A host Maven installation is currently required and its version is not repository-controlled. | | Project version | `org.example:video-editing:1.0-SNAPSHOT`. | The application artifact itself is a snapshot. The POM contains no snapshot/prerelease dependency version, but no automated enforcer proves that property. | | Dependency management | Spring Boot manages most versions; AWS SDK uses BOM `2.28.29`; JaCoCo is `0.8.12`. | There is no dependency lock, repository mirror policy, SBOM plugin, vulnerability gate, or update automation in the POM. | | Test runner | Surefire activates Spring profile `test`; JaCoCo checks 100% instruction, line, and branch coverage only for `org.example.videoclips.folder` during `verify`. | `test` does not execute the JaCoCo check. No project-wide coverage threshold is implemented. | | FFmpeg | Application defaults call `ffmpeg` and `ffprobe` from `PATH`. | Version, build flags, codecs, and checksum are unpinned. Some real-media tests skip when these tools are missing. | | CV Python | Four top-level packages are version-pinned in `tools/local_cv_requirements.txt`; transitive dependencies and hashes are not locked. | `.venv-local-cv` and YOLO weights are local, platform-specific, untracked state. | | Asset Python | `torch`, `audiocraft`, `soundfile`, and `numpy` are unpinned in `tools/local_asset_requirements.txt`. | `.venv-local-asset`, Piper, and music/SFX/voice models are not reproducibly provisioned. | | Packaging/deploy | No Dockerfile, Compose file, Maven wrapper, CI workflow, or deployment manifest is tracked. | There is no certified Linux/VPS/cloud build path or OCI image yet. | ## Inspect before building Run only read-only checks first: ```bash pwd test -f pom.xml git status --short java -version javac -version mvn -version python3 --version command -v ffmpeg command -v ffprobe ffmpeg -version | sed -n '1,4p' ffprobe -version | sed -n '1,3p' uname -s uname -m git ls-files -s tools/run_local_cv_worker.sh tools/run_local_asset_worker.sh ``` Require these observations: | Check | Accept now | If different | |---|---|---| | Repository root | `pom.xml`, `src/`, and `tools/` are present. | Stop and change to the repository root. Relative worker and data paths depend on the process working directory. | | Java | Runtime and compiler both report major version 21. | Select a Java 21 LTS JDK. Do not silently compile with a newer release. | | Maven | A host Maven is available. | Stop. There is no wrapper to recover a missing or incompatible Maven. Record the selected Maven version in evidence. | | Media tools | Both commands resolve and report versions. | Unit tests may still pass, while real FFmpeg integration tests skip. Do not accept that as media validation. | | OS/CPU | Record, do not normalize away. | Build or select Python wheels, FFmpeg, and model runtime packages for this exact OS/architecture. | | Script modes | CV launcher is `100755`; asset launcher is `100644` at current `HEAD`. | The asset bootstrap cannot be directly executed by `ProcessBuilder` on POSIX. Do not fix locally with `chmod` and call the environment reproducible; change the tracked mode through change control. | Inspect source declarations without invoking Maven plugins: ```bash sed -n '1,180p' pom.xml sed -n '1,120p' tools/local_cv_requirements.txt sed -n '1,120p' tools/local_asset_requirements.txt sed -n '1,120p' tools/run_local_cv_worker.sh sed -n '1,120p' tools/run_local_asset_worker.sh ``` Do not run `mvn dependency:*` or `mvn help:*` as an offline preflight unless the corresponding plugin is already present in the approved Maven cache. On the observed workstation, `mvn -o help:evaluate` fails because the help plugin is absent from the local cache. ## Platform setup contract Provision tools outside application startup. This section names the required result; it intentionally does not use `brew`, `apt`, `curl`, `pip`, or a model hub. ### macOS development Provide all of the following before running Maven: - A supported Java 21 LTS JDK and a known Maven distribution. - `ffmpeg` and `ffprobe` from the same approved FFmpeg build. - Python runtimes and wheel sets matching `uname -m` (`arm64` or `x86_64`). Never reuse a virtual environment created for the other architecture. - Pre-provisioned, licensed local model files. Configure explicit absolute paths; do not rely on a model name that a library may resolve online. - A network-denied validation environment. Do not rely on macOS `say`. The former host-dependent fallback was removed; it is not the approved local voiceover engine and is unavailable on Linux. ### Linux/VPS production Build and validate on the same Linux CPU architecture and compatible runtime family used in production. Provide Java 21, Maven only in the build stage, FFmpeg/ffprobe, Python runtimes, wheels, Piper, and model files from the approved artifact store. Keep the runtime artifact set read-only where practical. Do not rely on `espeak`. The former fallback was removed and was never a production voiceover contract. Do not copy a macOS virtual environment, native Python wheel, FFmpeg binary, or Maven build output that embeds host-specific paths into Linux. ### Cloud build and image pipeline Split acquisition from verification: | Stage | Network | Required output | |---|---|---| | Approved acquisition | Restricted to approved artifact repositories | Versioned Maven cache, hashed Python wheelhouse, hashed FFmpeg distribution, hashed model/asset bundle, licenses, SBOM inputs. | | Build | Denied | Compiled and tested application from immutable inputs. | | Runtime image assembly | Denied | Java runtime, application, media tools, Python runtime, models, assets, and manifest for one OS/CPU target. | | Runtime/smoke validation | Denied | Fail-closed startup and functional evidence; no cache writes or downloads. | Build distinct artifacts for `linux/amd64` and `linux/arm64` until cross-platform equivalence is demonstrated. GPU, CUDA, Metal/MPS, and CPU model runtimes are not interchangeable. Record device/runtime selection and numerical or quality acceptance results; never assume model availability means equivalent output. ## Safe build commands All Maven commands write under `target/`. They must run with network access denied. Maven `-o` requests offline resolution but is not itself a network sandbox. ### Compile without executing tests Use this only to isolate compilation: ```bash mvn -o -DskipTests package ``` Expected current artifact name after success: `target/video-editing-1.0-SNAPSHOT.jar`. This is not a quality gate. ### Run a focused test Use a focused class while developing a narrow change: ```bash mvn -o -Dtest=EditPlanValidatorTest test ``` Replace the class name only after locating it under `src/test/java`. Focused tests are evidence for that scope only. Tests that directly construct production process adapters may invoke host tools even though Surefire activates the `test` profile. ### Run the current full Maven gate The current repository-wide command is: ```bash mvn -o verify ``` `verify` compiles main and test sources, runs Surefire tests, applies the folder-package JaCoCo check, and creates a coverage report. It does **not** provide dependency locking, formatting, static analysis, architecture enforcement, vulnerability scanning, secret scanning, API compatibility, container scanning, SBOM generation, signing, or deployment validation. Do not report this gate as green from the current source. A clean archived checkout fails as documented below. A pass in a long-lived workspace can be caused by untracked `.venv-local-asset` state and may invoke a model library capable of downloading weights. ## Reproduce the clean-checkout gate Use an archive so untracked virtual environments, models, generated media, and local ignore rules cannot contaminate the result. Point Maven at an explicitly approved, pre-populated cache. The command performs no Git mutation and no source-tree write: ```bash repo_root="$(git rev-parse --show-toplevel)" archive_root="$(mktemp -d "${TMPDIR:-/tmp}/video-editing-clean.XXXXXX")" git -C "$repo_root" archive --format=tar HEAD | tar -xf - -C "$archive_root" ( cd "$archive_root" test ! -e .venv-local-cv test ! -e .venv-local-asset test -d "${MAVEN_REPO:?set MAVEN_REPO to the approved offline Maven cache}" mvn -o -Dmaven.repo.local="$MAVEN_REPO" verify ) ``` Interpret the result: | Observation | Meaning | Action | |---|---|---| | Maven cannot resolve an artifact or plugin in offline mode | The approved cache is incomplete. | Fix the approved acquisition manifest/cache. Do not remove `-o` or enable network. | | Both FFmpeg integration tests are skipped | `ffmpeg` or `ffprobe` is unavailable. | Fail media-capable validation; provision the approved pair. | | `LocalAssetGenerationStageTest.reusesExistingSharedAssetsAndSynthesizesMissingVoiceover` fails | This is the valid verified clean-archive result when Maven runs from inside the archive. | Do not seed an untracked virtual environment to hide it. Make the test hermetic and make the runtime fail closed through change control. | | The clean archive passes but the workspace fails | Workspace-generated state or source changes affect the result. | Compare tracked changes and environment; do not delete user work. | | The workspace passes but the clean archive fails | The workspace relies on untracked state. | Treat clean reproducibility as failed. | ### Verified clean result on 2026-07-21 With Java `21.0.10`, Maven `3.6.3`, FFmpeg/ffprobe `7.1.1`, and a populated host Maven cache, the valid run changed directory into the archived checkout, compiled 157 main sources, and ran 216 tests in 56 test classes. It finished with **one failed assertion**: `LocalAssetGenerationStageTest.reusesExistingSharedAssetsAndSynthesizesMissingVoiceover` expected `voiceover.wav` to exist. An earlier run reported two failures because it invoked Maven with `-f` from the long-lived workspace. That violated the test's process-working-directory assumption and is not valid clean-checkout evidence. The workspace's 216 tests passed while `.venv-local-asset` existed locally but was untracked. Together these observations establish a reproducibility defect, not the exact behavior of every clean machine. The macOS, Maven, Java, and FFmpeg patch versions are observations from one machine, not repository requirements. ## Working-directory and executable traps The defaults contain repository-relative paths such as `./tools/run_local_cv_worker.sh`, `./tools/local_asset_worker.py`, and `./.venv-local-asset/bin/python`. Java converts some of these to absolute paths relative to the process working directory. Follow these rules: 1. Run current development Maven commands from the repository root. 2. Do not start the packaged JAR from an arbitrary directory while retaining relative worker paths. 3. In a production artifact, configure absolute paths inside the immutable runtime layout. 4. Verify every directly executed POSIX script with `test -x`; a shebang does not compensate for a missing execute bit. 5. Invoke `.py` files through the approved Python interpreter. Do not make source scripts executable as an ad hoc workaround. Use these diagnostics without starting workers: ```bash test -r tools/local_asset_worker.py test -x tools/run_local_cv_worker.sh test -x tools/run_local_asset_worker.sh bash -n tools/run_local_cv_worker.sh bash -n tools/run_local_asset_worker.sh git ls-files .venv-local-cv .venv-local-asset ``` At current `HEAD`, the third command is expected to fail and the final command prints nothing. That is evidence about tracked state, not permission to alter it locally. ## Known test signals and warnings | Signal | Current interpretation | |---|---| | `Standard Commons Logging discovery... remove commons-logging.jar` | Observed classpath warning. Track it as dependency hygiene; do not suppress it as a build fix. | | Byte Buddy dynamic-agent warning | Mockito currently loads an agent dynamically; a future JDK may disallow this default. Java 21 tests currently continue. | | Flyway warns that H2 `2.2.224` is newer than its tested H2 support | Current tests use H2 for Spring contexts. This warning does not prove PostgreSQL behavior. | | `spring.jpa.open-in-view is enabled by default` during a test context | Investigate effective test configuration; main `application.properties` declares it false. Do not dismiss the mismatch. | | Local-CV fallback warnings in unit tests | Some tests intentionally exercise fallback behavior. They do not certify a production local CV model. | | FFmpeg test skipped | The two `@EnabledIf` integration classes skip when tools are unavailable. A green count with skips is weaker evidence. | ## TARGET: reproducible, dependency-locked build campaign Nothing in this section is implemented merely because it is listed. Complete and promote each phase through `video-editing-change-control`. ### Phase 1: pin the build toolchain - [ ] Add a Maven wrapper with an exact Maven distribution URL and verified distribution checksum. - [ ] Pin the Java 21 vendor/distribution and patch policy in CI/image metadata; enforce Java major version and Maven version at build start. - [ ] Centralize deliberate plugin and dependency version overrides; preserve Spring Boot dependency management unless an ADR proves why an override is required. - [ ] Reject dependency versions containing `SNAPSHOT`, milestone, RC, or other prerelease markers. Treat the project's own `1.0-SNAPSHOT` separately and replace it with traceable release versioning before release. - [ ] Set reproducible archive metadata and prove two isolated builds of the same commit and inputs produce identical artifact hashes. Gate: a clean checkout executes one documented wrapper command with no host Maven dependency, and the build records Java, Maven, OS, CPU, commit, and artifact hash. ### Phase 2: freeze dependency acquisition - [ ] Resolve Maven only through an approved immutable repository mirror; capture the complete dependency/plugin graph and checksums. - [ ] Produce a Python lock per supported OS/CPU/runtime, including transitive versions and hashes. - [ ] Build an approved wheelhouse; install with offline and hash-required semantics. Never run unconstrained `pip install` in service startup. - [ ] Generate an SBOM and license inventory for Java, Python, FFmpeg, native libraries, models, fonts, LUTs, music, and SFX. - [ ] Add vulnerability and license policy gates. Zero unresolved critical/high findings may ship without documented risk acceptance. Gate: remove all repository and model-hub access, delete mutable caches, rebuild only from the approved inputs, and obtain the same dependency inventory. ### Phase 3: provision local models and media tools - [ ] Give every model an immutable identifier, exact file list, SHA-256 checksums, source, license/usage rights, architecture/runtime compatibility, and acceptance evidence. - [ ] Configure models by explicit local paths. Prohibit library shorthand such as `yolov8n.pt` or `musicgen-small` when it can trigger online resolution. - [ ] Pin FFmpeg/ffprobe to one approved build per platform, including configure flags and codec/filter inventory. - [ ] Remove or fail closed on automatic bootstrap, heuristic substitution, host speech fallback, silence, and tone generation. - [ ] Verify local runtime readiness before accepting work; absence or checksum mismatch must produce a non-ready state and actionable error. Gate: startup and a representative highlight run succeed with egress denied and read-only dependency/model directories; removing one required model causes a deterministic readiness failure and no placeholder output. ### Phase 4: make tests hermetic and cross-platform - [ ] Replace `LocalAssetGenerationStageTest` host-process coupling with controlled test doubles or checked test fixtures; separately test the real packaged local runtimes. - [ ] Require explicit FFmpeg integration execution instead of silently accepting skips in the full gate. - [ ] Test PostgreSQL behavior with a real approved PostgreSQL test environment; current Spring tests use H2. - [ ] Run the same build portfolio on macOS developer architectures and supported Linux production architectures. - [ ] Add architecture tests, formatting, static analysis, API checks, security scans, secrets scanning, and deterministic end-to-end smoke tests only where each closes a stated acceptance criterion. Gate: the clean archive passes from an empty workspace on every supported target without user-home state, network, host speech tools, or untracked files. ### Phase 5: certify the release artifact - [ ] Build an OCI-compatible, non-root runtime image or equivalent immutable artifact for each supported architecture. - [ ] Keep build tools out of the runtime; include only the approved Java runtime, application, FFmpeg/ffprobe, Python runtime, models, and licensed assets needed for operation. - [ ] Generate provenance linking commit, dependency/model manifests, SBOM, tests, scans, and image digest. - [ ] Sign the release artifact and verify the signature before deployment. - [ ] Validate offline startup, graceful shutdown, readiness, resource limits, and representative media execution in the production-like environment. Gate: promotion consumes the already-built digest; it does not rebuild per environment. Rollback and roll-forward use known digests and compatible data migrations. ## Evidence checklist Attach this information to any environment or build claim: - [ ] Commit identifier and `git status --short` output. - [ ] `java -version`, `javac -version`, and `mvn -version`. - [ ] OS and CPU architecture. - [ ] FFmpeg and ffprobe versions plus build configuration. - [ ] Maven cache manifest/digest and confirmation that offline mode/network denial were active. - [ ] Python lock/wheelhouse digest and exact interpreter version, if local workers were in scope. - [ ] Model and licensed-asset manifest/digest, if cinematic processing was in scope. - [ ] Exact Maven command, test totals, skips, failures, and JaCoCo gate result. - [ ] Application JAR/image digest and SBOM/provenance references, when implemented. - [ ] A clear `CURRENT FAILURE`, `CANDIDATE`, or `PROMOTED` label. Never call an unimplemented target production-ready. ## Provenance and maintenance Re-verify the Java, Spring Boot, AWS BOM, project, and JaCoCo declarations: ```bash rg -n '|spring-boot-starter-parent|aws.sdk.version|1.0-SNAPSHOT|jacoco-maven-plugin|1.00' pom.xml ``` Re-verify build-system and delivery gaps: ```bash find . -maxdepth 3 -type f \( -name mvnw -o -name mvnw.cmd -o -name maven-wrapper.properties -o -name 'Dockerfile*' -o -name 'compose*.yml' -o -path './.github/workflows/*' -o -name '*.lock' \) -print ``` Re-verify Python pins, bootstrap/download paths, placeholders, and test coupling: ```bash rg -n '^[A-Za-z0-9_.-]+(\[.*\])?(==.*)?$|pip install|YOLO\(|get_pretrained|write_silence|write_fallback_tone|fallbackTone|runSpeechFallback|LocalAssetSynthesizer' tools src/main/java src/test/java/org/example/videoclips/editing/LocalAssetGenerationStageTest.java ``` Re-verify relative paths, startup defaults, and test safety overrides: ```bash rg -n 'auto-start:|enabled:|render-enabled:|fallback-to-heuristic:|bootstrap-script:|python-binary:|script:' src/main/resources/application.yml src/test/resources/application.properties src/main/java/org/example/videoclips/config/VideoClippingProperties.java ``` Re-verify tracked permissions and untracked-runtime assumptions: ```bash git ls-files -s tools/run_local_cv_worker.sh tools/run_local_asset_worker.sh tools/local_asset_worker.py git ls-files .venv-local-cv .venv-local-asset ``` Re-run the archived offline experiment from **Reproduce the clean-checkout gate** after build, test, Python, model, or worker changes. Update the dated result only from that isolated evidence; do not copy counts or versions from a long-lived workspace.