%% Werkator, planned with Werkbaum (https://werkbaum.javagil.de): what exists, what was dropped, what comes next. %% Status: [^] live on mih09 or in use, [x] merged but not in use, [~] in work, [ ] planned, [?] idea, [-] dropped. %% Each PR updates this file; see docs/agentic-workflow.md. The block behind --- explains the nodes with an id. %% mih09 deploys every merge to main itself, so a merged node is [^]. [~] #wk: Werkator https://git.javagil.de/mi/werkator - [~] #exec: Build execution and executor - [^] Async executor, worktrees, logs, cancel (L) " Plan steps 01 and 04, v0.9.0. " Builds run in .git/werkator/worktrees per branch. - [^] Shutdown marks builds INTERRUPTED, recovery re-runs them (S) " v0.9.5 - [^] "Build current head" on the Branches view (S) " PR#3, v1.0.1 - [^] Configurable executor.buildTimeout (S) " PR#48; default 30 minutes. - [^] A push during a running build is not lost (S) " PR#57 - [^] Processor time per build (M) " PR#67, PR#68, PR#71, PR#73 " Docker builds record none: the work runs under the daemon. - [^] Phase timing and executor.overheadBudget (M) " PR#70, plan step 14 - [^] Cancel replaces delete for active builds (S) " PR#95, PR#98; a cancelled queued build is recorded at once. - [^] executor.maxConcurrentPerRepository (S) " PR#103 - [^] Executor decisions split into classes (M) " PR#99, PR#106, PR#108, PR#109: BuildSlots, ActiveBuilds, CommandProcess, BuildLogs. - [^] One werkdock import per image (S) " PR#121; new status "build environment failed". - [^] CI=true in every build (XS) " PR#132; part of RFC 0006 step 2. - [ ] Ownership repair after Docker builds (S) " Plan step 14 item 3; Docker only (vm4006). " Needs a container test. - [?] Cancel on a new commit instead of queue-behind (S) " Deferred in plan step 06. - [?] Warning when a build nears its timeout (XS) " PR#48 - [~] #sandbox: Sandboxes: Docker, bwrap and werkdock - [^] Docker build runtime (M) " Plan step 11 - [^] Read-only git metadata in Docker builds (S) " Plan step 16 - [^] Nightly Docker prune timer (S) " PR#80 removes anonymous volumes; PR#83 keeps the build images. - [^] bwrap user-namespace runtime for Managed Webspaces (L) " PR#4, ADR 0008, plan step 17 - [^] Werkdock in its own repository; Werkator uses its CLI (L) " PR#6, PR#7, PR#15, plan step 21 - [^] Config section bwrap renamed werkdock (S) " PR#19, PR#131; the old name is read with a warning. - [^] werkdock import verb and stale-binary rebuild (M) " PR#50 - [^] Testcontainers over the werkdock API socket on the webspace (S) " PR#53 - [^] One shared Gradle home: werkdock.gradleHome (S) " PR#76 - [^] Build environments that no configuration names are removed (S) " PR#77 - [^] docker.socket opt-in and pinned (S) " PR#55; PR#72 made it settable per build. - [^] docker.env host override wins; rootlesskit host override (S) " PR#85, PR#86 - [ ] Drop the "load -i --name" fallback (XS) " PR#50; when every werkdock has import. - [ ] #sandbox.alias: Drop the bwrap alias (XS) :#config.step18 " PR#19; together with plan step 18. - [?] Disposable Docker daemon per build (M) " PR#55; audit finding 3 is half fixed. " DinD needs a rootful host daemon. - [?] Bind mount for credential files in Docker follow-ups (S) " PR#23 - [?] Shared .konan directory like gradleHome (XS) " PR#76, PR#77 - [?] MemoryMax and TasksMax on the webspace unit (XS) " PR#4 - [?] werkdock library mode: rootfs building blocks on the HDD (L) - [-] #sandbox.proot: proot and fakechroot - [-] #sandbox.native: Plain native builds with hand-installed toolchains - [-] #sandbox.levels: Werkdock RFC 0002 levels 2 and 3 - [~] #config: Configuration, build definitions and pinning - [^] Layered YAML config: machine, project, branch (M) " v0.9.0 - [^] Build definitions: builds, trigger, ! excludes, statusContext (L) " ADR 0007, v0.9.14 to v0.9.20 - [^] werkator.version since and below in config files (S) " v0.9.18 - [^] init --apply fragment layer and control-token command (M) " PR#8, PR#9, plan step 23 - [^] init reads its config from the repository root (XS) " PR#22 - [^] A blank credential does not shadow an inherited one (S) " PR#51 - [^] Shape check and pinned values written back after merge (S) " PR#55 - [^] Config checks split for Mutation-CRAP (S) " PR#112, PR#120, PR#131 - [ ] #config.step18: Remove the legacy branches section, set FORMAT_BROKE_IN (M) " Plan step 18, the last open plan step. " Needs every hs.hsadmin.ng branch config free of a top-level branches key. - [ ] #config.gittally: Remove the .gittally.yml name fallback (S) :#config.step18 " PR#1; the old name is then rejected. - [?] Should a branch be able to remove a build definition? (S) " PR#15 - [?] Pin docker.env too (XS) " Security audit TODO 6. - [?] Gradle 9 upgrade (S) " ADR 0002; waits for openapi-generator and ktlint support. - [-] #config.autobuild: Keep extending autoBuild - [-] #config.parallel: autoBuild and builds in parallel forever - [-] #config.pinbuilds: Pin the whole builds section against the branch layer - [-] #config.maxconc: builds.maxConcurrent - [-] #config.secrets: Mark secrets in the WerkatorConfig schema - [~] #watch: Watcher, triggers and follow-up builds - [^] Branch polling, atTimes schedules, startup recovery (M) " Plan step 06 - [^] Hourly ??:MM slots; local refs fast-forwarded (S) " v0.9.11, v0.9.16 - [^] Watcher health banner for an unreachable origin (S) " Plan step 19 - [^] Follow-up builds: trigger.afterSuccessOf (L) " PR#23; a deployment is a build that follows a green build. - [^] Branch-owned sandboxed follow-ups (S) " PR#74 - [ ] #watch.list: afterSuccessOf as a list, like needs (S) " PR#23; the same work as part of RFC 0006 step 3. - [~] #multi: Multi-repository instance - [^] ADR 0009, RepoContext, registry in ~/.werkator.yml, --repo (XL) " PR#10, PR#11, PR#12, plan step 22 A to C - [^] Repository-scoped routes /repos/ and /api/repos/ (M) " PR#13, plan step 22 D - [^] Rollout on mih09 (S) " Plan step 22 E - [?] Round-robin fairness across repositories (S) " FIFO was decided on 2026-09-02. - [?] Share buildenv rootfs trees across repositories (M) " Waits for the Werkdock image store. - [-] #multi.federation: Federation dashboard over single-repository instances - [-] #multi.prefix: Repository prefix on artifactKey - [~] #pr: Pull-request builds - [^] requirePullRequest gate: build only branches with a PR (S) - [^] Open PR shown as PR#n, then in its own column (S) " PR#81, PR#82 - [^] Pull-request target builds: onPullRequestTarget, fresh home, own pool (L) " PR#117, PR#118, PR#119, PR#120, PR#122 - [^] A commit status lost on a dead connection is sent once more (XS) " PR#155; werkcrappit PR#68 stayed pending: ai-review/gate never got its success. - [ ] Show the pull request target in the UI and the API DTOs (S) " PR#117 - [?] Rebuild a reopened PR with an unchanged head (XS) " PR#117 - [?] PR targets tile only where a target definition exists (XS) " PR#119 - [~] #ui: Web UI - [^] Thymeleaf pages and werkator.js polling; release-notes page (M) " Plan step 08 - [^] Kin design: IBM Plex, logo, header, imprint and privacy links (L) " RFC 0001; PR#34, PR#35, PR#38, PR#39 - [^] Repositories page /repos, GET /api/repos, repository line (M) " PR#37 - [^] Instance home page and switchable dark mode (L) " PR#54, RFC 0003 - [^] Mobile nav icons; control-token feedback (S) " PR#56, PR#47 - [^] Build-duration trend per definition (M) " PR#49, plan step 20 - [^] "Restarting" indicator during self-deployment (XS) " PR#75 - [^] #restart2: Two restarts per row: same commit, newest commit (M) " PR#150; follow-ups, also those a branch defines, and pull-request targets refuse the newest commit. " PR#151 split BuildsApiController.restart again: the nightly gate measured 15.64. - [^] A failure overtaken by a newer run or a deleted branch is shown as outdated (S) " PR#156; grey in the History and the home strip, the reason in the tag's title. - [^] Builds panel on the home page: running, queued, failed; five tiles per row (S) " PR#160; pages 1440 px wide, failures of the last week that no build of the same name answers or runs again. - [?] Three-state theme switch: light, dark, follow browser (XS) " PR#54 - [?] Relative timestamps on cards (S) " PR#54 - [?] History paging or range selector (S) " PR#59 - [?] Duration trend shows CPU time; slow-drift detection (S) " PR#67, PR#49 - [-] #ui.rfc0001: RFC 0001 options A to F - [-] #ui.trendbranch: Duration trend per branch - [^] #artifacts: Artifacts and history retention - [^] File artifact store, retentionPerBranch (M) " Plan step 05 - [^] Age-based retentionMaxAge (S) - [^] Permanent latest-green links (S) - [^] History survives its branch: branchGoneAt (M) " PR#59 - [^] Run history outlives artifacts: artifactsPrunedAt (S) " PR#84 - [^] Markdown reports in the artifact index (S) " PR#88, PR#90 - [^] Artifact CORS; private artifacts, builds..publicArtifacts (L) " PR#96, PR#114 - [-] #artifacts.sqlite: SQLite instead of JSON files - [~] #metrics: System page and metrics - [^] Metrics page; critical utilization highlighted (M) " Plan step 09 - [^] Quota-aware disk metrics (M) " PR#16; PR#63: an unreadable quota is not the volume. - [^] Health page: PSI, load, swap, three-tier history (L) " PR#27, merged as PR#29 - [^] Multiple disks: metrics.disks (M) " PR#33 - [^] Charts, disk breakdown dialog, physical-headroom marker (L) " PR#40, PR#41, RFC 0002 - [^] Storage pressure sampled from /proc/pressure/io (S) " PR#69 - [^] Swap thresholds and verdict colours (S) " PR#100, PR#101, PR#102 - [^] Sampling and view split into steps; disk verdict judges budget and volume (M) " PR#111, PR#116 - [^] Swap-out card with history; cards in one row (M) " PR#146 - [^] OOM kills tile; tiles in two rows of four (S) " PR#147 - [?] Charts for load and pressure on /system (S) " PR#54 - [?] Fill the CPU value from history right after a restart (XS) - [?] Feed the pressure figures into the verdict or the sizing (S) " PR#69; needs about a month of pressure history. - [?] Per-repository disk breakdown (S) " RFC 0002 decision 4 - [?] Slice palette: buildenv and other differ (XS) - [-] #metrics.a2: RFC 0002 A2: stacked bar in the disk card - [-] #metrics.b2: RFC 0002 B2: second card - [-] #metrics.switch: metrics.disk quota or filestore switch - [~] #sizing: Capacity sizing - [^] Capacity advice (M) " PR#30, merged as PR#32 - [^] Sizing corrections and Hostsharing order mail (M) " PR#42, PR#44 - [^] Sizing by waiting, in bookable steps (L) " PR#58, RFC 0004 - [^] Disk sized by the level it holds; RAM downsize without the 40 % gate (S) " PR#78, PR#79 - [^] CPU, RAM and disk advice split into steps (S) " PR#113, PR#123 - [ ] Read oom_kill into the RAM verdict (S) " RFC 0004, PR#58; waits for data, not for a node. " Needs experience with the machine-wide counter. - [ ] RAM sizing rule on swap-out (S) " PR#102, PR#146; waits for data, not for a node. " Needs weeks of the swapOut series, recorded since 2026-10-10. - [?] Bookable steps from a Hostsharing API (M) " RFC 0004 B1 - [~] #selfdeploy: Self-deployment - [^] Static maintenance page during restarts (S) " PR#17 - [^] RFC 0005 step 1: tools/self-deploy, staged swap, watchdog (M) " PR#61 - [^] Adoptium toolchain: the runtime starts on the glibc of Debian 12 (S) " PR#62 - [^] Temurin 25 in the toolchain and in the runtime bundle (S) " PR#152, werkregie ADR 0001; Kotlin 2.4.21, Gradle stays 8.14.5. - [^] Runtime swapped only while the service is down (S) " PR#64 - [^] restartsInstance: the instance drains and ends itself (M) " PR#65, PR#66, RFC 0005 step 2 - [^] Restart only from a repository with selfDeploys: true (S) " PR#87 - [?] Self-deployment on a Docker host with a system unit (M) " Needs a new RFC. - [-] #selfdeploy.pathunit: Option C: systemd path unit as deployer - [-] #selfdeploy.mainonly: runtimeBundle on main only - [-] #selfdeploy.temurin: Temurin baked into the rootfs - [~] #security: Security and privacy - [^] Security audit: bindAddress 127.0.0.1, control token not in pages (M) " v0.9.9, v0.9.10 - [^] robots.txt served by Werkator (XS) " PR#25, merged as PR#26 - [^] Token-dependent responses never cached (S) " PR#45 - [^] Private repositories obscured; metadata, not content (M) " PR#43; PR#54, RFC 0003 D8 - [^] Six audit findings fixed (L) " PR#55: CSP sandbox, symlink containment, read-only checkout, log names, socket opt-in, shape check. - [x] Links between artifacts of a private repository (XS) " PR#164: control-token cookie SameSite=Lax, artifacts stay sandboxed. - [x] Build variables off the command line of werkdock and docker (S) " PR#166: bare -e KEY, the value in the CLI's environment; werkdock PR#17 keeps it off bwrap's. - [?] Real UI authentication (L) " Needs an ADR that revises ADR 0004. - [-] #security.login: Pages behind a login - [-] #security.robotsinit: robots.txt generated by init - [~] #ops: Deployment and operations - [^] init --systemd user unit (M) " Plan step 12, ADR 0004 - [^] Managed nginx/TLS container, opt-in (L) " Plan step 13, ADR 0005, PR#124 - [^] jlink runtime bundle (M) " Plan step 15, ADR 0006 - [^] Rename GitTally to Werkator (L) " PR#1, v1.0.0 - [^] tools/remote: any host layout, authenticated clone, SSH multiplexing (M) " PR#18, PR#21, PR#24, PR#28 - [^] Unit declares SuccessExitStatus=143 (XS) " PR#73 - [ ] Bring vm4006 from v1.37.12 to main (S) " Needs init --systemd once; remove TESTCONTAINERS_HOST_OVERRIDE. - [-] #ops.spa: SPA or server push - [-] #ops.compose: External compose stack instead of managed nginx - [-] #ops.graal: GraalVM native image - [-] #ops.container: Containerized Werkator runtime - [~] #forgejo: Forgejo compatibility - [^] ADR 0010, RFC 0006, export:forgejo and tools/werkator-to-forgejo (M) " PR#92 - [^] Export notes by topic; job as header and steps (S) " PR#115 - [ ] RFC 0006 step 2 rest: GITHUB_* and FORGEJO_* variables in every build (S) " PR#92 - [ ] #forgejo.s3: RFC 0006 step 3: cheap deviations, one PR each (M) :#watch.list - [ ] #forgejo.s3b: RFC 0006 step 3b: build environments as registry images (M) - [ ] #forgejo.s4: RFC 0006 step 4: decide the deviations that stay (S) - [ ] #forgejo.s5: RFC 0006 step 5: Werkator reads the workflow subset (L) :#forgejo.s3,#forgejo.s3b,#forgejo.s4 - [ ] #forgejo.s6: RFC 0006 step 6: one workflow on both systems in production (M) :#forgejo.s5 - [?] Workflow as the primary format, by a new ADR (XL) - [-] #forgejo.free: Keep the own format free - [-] #forgejo.replace: Replace the own format by the workflow format now - [~] #tests: Tests, mutation testing and Mutation-CRAP - [^] Kotest, MockK, WireMock, Testcontainers (S) " ADR 0001 - [^] Flaky tests fixed (S) " PR#20, PR#46, PR#60, PR#97, PR#157 - [^] unitTest and integrationTest tasks by spec name (S) " PR#91 - [^] Nightly mutation build with Mutation-CRAP (M) " PR#93, PR#94 - [^] Target 15, red from 12, gate as a ratchet (S) " PR#104 - [^] Mutation-CRAP campaign, gate 650 to 15 (XL) " PR#105 to PR#131 - [^] PIT memory and faster mutation tests (M) " PR#134 to PR#145 - [^] PIT minions on the toolchain's JVM (S) " PR#154; since PR#152 they ran on Gradle's Java 21 and found no test. - [^] No endless loop for a mutant in the history's gap filler (XS) " PR#162; HistoryTier.nulls gave MEMORY_ERROR, an inconclusive gate. - [ ] Mutation tests in every build (L) " Incremental on branches, full on main; the speed steps are done. " The split, seeded from the history.bin of main, is still to be designed. - [ ] Measured heap limit for PIT minions (S) " PR#135, PR#136 - [-] #tests.frameworks: JUnit 5 or Spek 2 - [-] #tests.executorit: BuildExecutorIntegrationTest inside PIT - [-] #tests.xmx512: PIT minions at -Xmx512m - [-] #tests.origin: Version check against origin/main - [~] #process: Development process and docs - [^] A version per PR, checked by ReleaseVersionConsistencyUnitTest (S) " PR#52 - [^] docs/llms.md (S) " PR#36 - [^] Agents open PRs as WIP; AI review by werkrevisor; shared agentic workflow (S) " PR#127, PR#128, PR#148 - [^] Werkbaum plan (S) " PR#149 - [^] Codex review by the runner of werkrevisor, advise only (XS) " PR#153 - [x] Codex review holds the merge (XS) " PR#158; ai-review/codex is a required status. - [x] A misreported build status waits for the human (XS) " PR#159: Jev category status_misreported; BuildSettingsSource is a hard path. - [x] docs/agentic-workflow.md from the master copy of werkregie (XS) " PR#161 - [^] The AI review skips generated sections of the docs (XS) " PR#165, after werkrevisor PR#122. - [?] CI check that llms.md stays in sync (XS) " PR#36 --- #sandbox.proot ADR 0008: proot and fakechroot are slow and fragile, and they isolate nothing. #sandbox.native ADR 0008: native builds with hand-installed toolchains give no isolation. #sandbox.levels Level 2 pulls OCI images, level 3 offers a daemon API. Deferred indefinitely on 2026-09-01; see plan step 21. #sandbox.alias The alias bwrap goes with plan step 18, which sets ConfigVersions.FORMAT_BROKE_IN. #config.step18 The legacy branches section is read only while no build is defined. When it is removed, FORMAT_BROKE_IN is set, and a leftover branches key is rejected by name. #config.gittally The fallback to the old name rides on plan step 18, like the bwrap alias. #config.autobuild ADR 0007: an autoBuild slot is a job in disguise. #config.parallel ADR 0007: autoBuild and builds in parallel forever are two ways to say one thing. #config.pinbuilds Reverted on 2026-08-29: a branch must describe its own CI (ADR 0007). #config.maxconc ADR 0007: the key moved to executor.maxConcurrent, without an alias. #config.secrets PR#51: too much machinery for two keys. #watch.list The list form is the counterpart of needs in a workflow; it is part of RFC 0006 step 3. #multi.federation ADR 0009: a dashboard over single-repository instances keeps N services and N ports. #multi.prefix Plan step 22: not needed, and it renames existing directories. #ui.rfc0001 Option G, "Kin", replaced the options A to F. #ui.trendbranch Plan step 20 was revised to one trend per build definition. #restart2 One restart repeats the build at the same commit, the other builds the newest commit of the branch. A follow-up build and a pull-request target build run at a given commit, so they refuse the newest commit. #artifacts.sqlite ADR 0004: not needed; the repository interface keeps the switch possible. #metrics.a2 RFC 0002: the cards may not grow. #metrics.b2 RFC 0002: a second card doubles the cards. #metrics.switch PR#16: a choice that nobody makes. #selfdeploy.pathunit RFC 0005: not needed once restartsInstance exists. #selfdeploy.mainonly PR#61: changes to the deployment would be untestable before the merge. #selfdeploy.temurin PR#62: each Java update would mean about 1 GB uploaded by hand. #security.login Security audit: public read access is a requirement. #security.robotsinit PR#25: when Werkator serves robots.txt itself, it covers Apache and nginx. #ops.spa ADR 0004: polling is enough. #ops.compose ADR 0005: an external compose stack is manual work for every operator. #ops.graal ADR 0006: Spring AOT cannot hold CLI mode and server mode in one image. #ops.container ADR 0006: socket mounts, a HOME at the same path and uid mapping. #forgejo.s3 Includes afterSuccessOf as a list. #forgejo.free ADR 0010: the own format stays expressible as a workflow. #forgejo.replace ADR 0010: the workflow format needs uses:, expressions and matrix; Werkator would be a second runner. #tests.frameworks ADR 0001: Kotest is more idiomatic; Spek has stalled. #tests.executorit PR#97: about one more hour per run. #tests.xmx512 PR#134 gave MEMORY_ERROR; PR#135 reverted it. #tests.origin PR#52: it fails every branch that is merely out of date.