immich server/: ac run immich-fault
immich server/ @ 02063972e8 → ac51228171 on ac/s7-fault: run status stopped.
no whole-PR certificate run status stopped: the run ended before its whole-PR certificate
| Field | Value |
|---|---|
| Target | immich (profile), package root server/, github.com/immich-app/immich |
| Commits | base 02063972e8 → head ac512281719130a99e5b3ede6cb06b648d294c6c; branch ac/s7-fault (a local branch; the certificates name its trees) |
| Trees | base 424df72c3407dd1e7df5ee4e81a1d5fcd85cc01c |
| Plan | from the plan file plan.yaml: 59 steps, 367 moves, sha256 b4c7c548883c0635951f893c7717727f3d086a0c4e23b2db442e796dd416cc7f |
| Rungs requested | R0, R1 |
| Whole-PR digest | – |
| Cost | planner spend in this run $0.0000; the plan cost $0.1998 when it was recorded |
| Injected fault | --inject-fault 2:M2: applied to step 2, M2 (Drop one importer rewrite): server/src/services/workflow-execution.service.ts: import specifier 'src/modules/album/album.dto.js' left as in base, 'src/dtos/album.dto.js' |
The plan: Nemotron draws the map
Deterministic seeds decided where files go; plan.yaml marks 8 placements by the planner and 2 by the critic. This run dir has no plan.json, so the report can't name the models that made the plan. The plan has 38 modules, 20 platform folders and 1 shared folder over 269 planned files: 259 from the deterministic seeds draft, 8 by the planner, 2 by the critic. 30 placements are marked contested.
Placements the planner and the critic decided (10)
| File | Group | Decided by | Rationale |
|---|---|---|---|
src/app.common.ts | platform/bootstrap | planner | Bootstrap wiring for Express and telemetry; belongs to platform plumbing. |
src/controllers/app.controller.ts | platform/bootstrap | planner | Root app controller only serves health/info endpoints; platform plumbing. |
src/dtos/editing.dto.ts | module/asset | planner | Editing DTOs are used by asset edit flows. |
src/dtos/env.dto.ts | shared/shared | planner | Environment schema DTO is a pure type shared across config. |
src/dtos/onboarding.dto.ts | module/system-metadata | planner | Onboarding DTOs used by system‑metadata controller. |
src/repositories/app.repository.ts | module/maintenance | critic | Only the maintenance module consumes this repository; fixes the impure‑shared warning. |
src/utils/editor.ts | platform/media | critic | Utility is only imported by platform/media; moving it out of shared resolves the single‑consumer warning. |
src/utils/object.ts | shared/shared | planner | Plain object utilities. |
src/utils/pagination.ts | shared/shared | planner | Pagination helpers used everywhere. |
src/utils/profile-image.ts | module/user | planner | Profile image generation used by user feature. |
plan.yaml · the plan cost $0.1998 when it was recorded; a replay from the cassette costs $0
Before and after: the module graph
At the base commit the 563 source files under src/ sit in 14 folders outside the layout; at the head commit 18 sit in 3 feature modules and 545 are still in 14 folders outside the layout. The file-level import pairs are the same 2,051 on both sides (a certified move keeps every import resolving to the same file); only their grouping changes. The share of pairs inside one folder falls: 479 of 2,051 (23.4%) at base, 472 of 2,051 (23.0%) at head. The largest blocks of internal pairs are src/schema/ 152, src/services/ 111, src/repositories/ 89 at base and src/schema/ 152, src/services/ 104, src/repositories/ 85 at head. Grouping by feature doesn't remove the imports between features; it makes them visible. The findings below name what ties the modules together (1 god-injection base class and 1 module cycle). R4 was not part of this run, so no boundary rules hold them yet.
Import cycles at base: 12 folders
src/ src/commands/ src/controllers/ src/cores/ src/dtos/ src/emails/ src/maintenance/ src/middleware/ src/repositories/ src/schema/ src/services/ src/utils/
Import cycles at head: 15 folders
module/activity module/album module/api-key src/ src/commands/ src/controllers/ src/cores/ src/dtos/ src/emails/ src/maintenance/ src/middleware/ src/repositories/ src/schema/ src/services/ src/utils/
Left: the folders at the base commit, by size. Right: where their files are at the head commit, grouped by layout kind. A band is a number of files; every node is at least one label tall, so small groups are drawn larger than their share.
Table view
| Base folder | Head folder | Files |
|---|---|---|
src/ | src/ | 10 |
src/bin/ | src/bin/ | 2 |
src/commands/ | src/commands/ | 10 |
src/controllers/ | module/activity | 2 |
src/controllers/ | module/album | 2 |
src/controllers/ | module/api-key | 2 |
src/controllers/ | src/controllers/ | 76 |
src/cores/ | src/cores/ | 2 |
src/dtos/ | module/activity | 1 |
src/dtos/ | module/api-key | 1 |
src/dtos/ | src/dtos/ | 53 |
src/emails/ | src/emails/ | 9 |
src/maintenance/ | src/maintenance/ | 6 |
src/middleware/ | src/middleware/ | 8 |
src/repositories/ | module/activity | 1 |
src/repositories/ | module/album | 2 |
src/repositories/ | module/api-key | 1 |
src/repositories/ | src/repositories/ | 59 |
src/schema/ | src/schema/ | 168 |
src/services/ | module/activity | 2 |
src/services/ | module/album | 2 |
src/services/ | module/api-key | 2 |
src/services/ | src/services/ | 96 |
src/utils/ | src/utils/ | 43 |
src/workers/ | src/workers/ | 3 |
1,572 file pairs cross folders in 73 folder edges. Rows import columns. Folders are ordered importers first (strongly connected sets, then a greedy order inside each), so a cell below the diagonal is an import against the order. Darker means more file pairs (1, 2–3, 4–9, 10–29, 30+).
Table view
| Importer folder | Imported folder | File pairs | Type-only |
|---|---|---|---|
src/ | src/commands/ | 1 | 0 |
src/ | src/controllers/ | 1 | 0 |
src/ | src/dtos/ | 7 | 0 |
src/ | src/maintenance/ | 6 | 0 |
src/ | src/middleware/ | 6 | 0 |
src/ | src/repositories/ | 18 | 0 |
src/ | src/schema/ | 6 | 1 |
src/ | src/services/ | 6 | 0 |
src/ | src/utils/ | 5 | 0 |
src/bin/ | src/ | 2 | 0 |
src/bin/ | src/repositories/ | 6 | 0 |
src/bin/ | src/services/ | 1 | 0 |
src/bin/ | src/utils/ | 2 | 0 |
src/commands/ | src/ | 1 | 0 |
src/commands/ | src/dtos/ | 1 | 0 |
src/commands/ | src/services/ | 9 | 0 |
src/controllers/ | src/ | 117 | 1 |
src/controllers/ | src/dtos/ | 112 | 34 |
src/controllers/ | src/middleware/ | 50 | 0 |
src/controllers/ | src/repositories/ | 9 | 0 |
src/controllers/ | src/services/ | 54 | 3 |
src/controllers/ | src/utils/ | 13 | 0 |
src/cores/ | src/ | 3 | 1 |
src/cores/ | src/repositories/ | 8 | 0 |
src/cores/ | src/utils/ | 2 | 0 |
src/dtos/ | src/ | 90 | 9 |
src/dtos/ | src/repositories/ | 1 | 0 |
src/dtos/ | src/schema/ | 3 | 0 |
src/dtos/ | src/utils/ | 11 | 0 |
src/emails/ | src/repositories/ | 4 | 0 |
src/emails/ | src/utils/ | 3 | 0 |
src/maintenance/ | src/ | 7 | 1 |
src/maintenance/ | src/controllers/ | 2 | 2 |
src/maintenance/ | src/cores/ | 1 | 0 |
src/maintenance/ | src/dtos/ | 7 | 0 |
src/maintenance/ | src/middleware/ | 1 | 0 |
src/maintenance/ | src/repositories/ | 12 | 1 |
src/maintenance/ | src/services/ | 7 | 5 |
src/maintenance/ | src/utils/ | 5 | 0 |
src/middleware/ | src/ | 5 | 1 |
src/middleware/ | src/dtos/ | 3 | 0 |
src/middleware/ | src/repositories/ | 7 | 0 |
src/middleware/ | src/services/ | 3 | 0 |
src/middleware/ | src/utils/ | 6 | 0 |
src/repositories/ | src/ | 111 | 10 |
src/repositories/ | src/dtos/ | 28 | 1 |
src/repositories/ | src/emails/ | 4 | 0 |
src/repositories/ | src/schema/ | 85 | 0 |
src/repositories/ | src/utils/ | 30 | 0 |
src/schema/ | src/ | 72 | 4 |
src/schema/ | src/dtos/ | 5 | 0 |
src/schema/ | src/repositories/ | 3 | 0 |
src/schema/ | src/utils/ | 3 | 0 |
src/services/ | src/ | 129 | 25 |
src/services/ | src/cores/ | 14 | 0 |
src/services/ | src/dtos/ | 124 | 1 |
src/services/ | src/maintenance/ | 1 | 0 |
src/services/ | src/middleware/ | 1 | 0 |
src/services/ | src/repositories/ | 109 | 18 |
src/services/ | src/schema/ | 11 | 0 |
src/services/ | src/utils/ | 119 | 0 |
src/utils/ | src/ | 34 | 8 |
src/utils/ | src/cores/ | 3 | 0 |
src/utils/ | src/dtos/ | 21 | 0 |
src/utils/ | src/middleware/ | 1 | 0 |
src/utils/ | src/repositories/ | 20 | 1 |
src/utils/ | src/schema/ | 2 | 0 |
src/workers/ | src/ | 6 | 0 |
src/workers/ | src/maintenance/ | 1 | 0 |
src/workers/ | src/middleware/ | 1 | 0 |
src/workers/ | src/repositories/ | 6 | 0 |
src/workers/ | src/services/ | 1 | 0 |
src/workers/ | src/utils/ | 3 | 0 |
1,579 file pairs cross folders in 100 folder edges. Rows import columns. Folders are ordered importers first (strongly connected sets, then a greedy order inside each), so a cell below the diagonal is an import against the order. Darker means more file pairs (1, 2–3, 4–9, 10–29, 30+).
Table view
| Importer folder | Imported folder | File pairs | Type-only |
|---|---|---|---|
module/activity | src/ | 10 | 0 |
module/activity | src/dtos/ | 3 | 1 |
module/activity | src/middleware/ | 1 | 0 |
module/activity | src/schema/ | 2 | 0 |
module/activity | src/services/ | 1 | 0 |
module/activity | src/utils/ | 1 | 0 |
module/album | src/ | 9 | 0 |
module/album | src/dtos/ | 9 | 1 |
module/album | src/middleware/ | 1 | 0 |
module/album | src/schema/ | 5 | 0 |
module/album | src/services/ | 1 | 0 |
module/album | src/utils/ | 5 | 0 |
module/api-key | src/ | 10 | 0 |
module/api-key | src/dtos/ | 2 | 1 |
module/api-key | src/middleware/ | 1 | 0 |
module/api-key | src/schema/ | 2 | 0 |
module/api-key | src/services/ | 1 | 0 |
module/api-key | src/utils/ | 3 | 0 |
src/ | src/commands/ | 1 | 0 |
src/ | src/controllers/ | 1 | 0 |
src/ | src/dtos/ | 7 | 0 |
src/ | src/maintenance/ | 6 | 0 |
src/ | src/middleware/ | 6 | 0 |
src/ | src/repositories/ | 18 | 0 |
src/ | src/schema/ | 6 | 1 |
src/ | src/services/ | 6 | 0 |
src/ | src/utils/ | 5 | 0 |
src/bin/ | src/ | 2 | 0 |
src/bin/ | src/repositories/ | 6 | 0 |
src/bin/ | src/services/ | 1 | 0 |
src/bin/ | src/utils/ | 2 | 0 |
src/commands/ | src/ | 1 | 0 |
src/commands/ | src/dtos/ | 1 | 0 |
src/commands/ | src/services/ | 9 | 0 |
src/controllers/ | module/activity | 1 | 0 |
src/controllers/ | module/album | 1 | 0 |
src/controllers/ | module/api-key | 1 | 0 |
src/controllers/ | src/ | 108 | 1 |
src/controllers/ | src/dtos/ | 104 | 31 |
src/controllers/ | src/middleware/ | 47 | 0 |
src/controllers/ | src/repositories/ | 9 | 0 |
src/controllers/ | src/services/ | 51 | 3 |
src/controllers/ | src/utils/ | 13 | 0 |
src/cores/ | src/ | 3 | 1 |
src/cores/ | src/repositories/ | 8 | 0 |
src/cores/ | src/utils/ | 2 | 0 |
src/dtos/ | src/ | 85 | 9 |
src/dtos/ | src/repositories/ | 1 | 0 |
src/dtos/ | src/schema/ | 3 | 0 |
src/dtos/ | src/utils/ | 11 | 0 |
src/emails/ | src/repositories/ | 4 | 0 |
src/emails/ | src/utils/ | 3 | 0 |
src/maintenance/ | src/ | 7 | 1 |
src/maintenance/ | src/controllers/ | 2 | 2 |
src/maintenance/ | src/cores/ | 1 | 0 |
src/maintenance/ | src/dtos/ | 7 | 0 |
src/maintenance/ | src/middleware/ | 1 | 0 |
src/maintenance/ | src/repositories/ | 12 | 1 |
src/maintenance/ | src/services/ | 7 | 5 |
src/maintenance/ | src/utils/ | 5 | 0 |
src/middleware/ | src/ | 5 | 1 |
src/middleware/ | src/dtos/ | 3 | 0 |
src/middleware/ | src/repositories/ | 7 | 0 |
src/middleware/ | src/services/ | 3 | 0 |
src/middleware/ | src/utils/ | 6 | 0 |
src/repositories/ | module/activity | 1 | 0 |
src/repositories/ | module/album | 2 | 0 |
src/repositories/ | module/api-key | 1 | 0 |
src/repositories/ | src/ | 101 | 10 |
src/repositories/ | src/dtos/ | 27 | 1 |
src/repositories/ | src/emails/ | 4 | 0 |
src/repositories/ | src/schema/ | 76 | 0 |
src/repositories/ | src/utils/ | 27 | 0 |
src/schema/ | src/ | 72 | 4 |
src/schema/ | src/dtos/ | 5 | 0 |
src/schema/ | src/repositories/ | 3 | 0 |
src/schema/ | src/utils/ | 3 | 0 |
src/services/ | module/activity | 3 | 0 |
src/services/ | module/album | 4 | 0 |
src/services/ | module/api-key | 2 | 0 |
src/services/ | src/ | 124 | 25 |
src/services/ | src/cores/ | 14 | 0 |
src/services/ | src/dtos/ | 115 | 1 |
src/services/ | src/maintenance/ | 1 | 0 |
src/services/ | src/middleware/ | 1 | 0 |
src/services/ | src/repositories/ | 104 | 18 |
src/services/ | src/schema/ | 11 | 0 |
src/services/ | src/utils/ | 113 | 0 |
src/utils/ | src/ | 34 | 8 |
src/utils/ | src/cores/ | 3 | 0 |
src/utils/ | src/dtos/ | 21 | 0 |
src/utils/ | src/middleware/ | 1 | 0 |
src/utils/ | src/repositories/ | 20 | 1 |
src/utils/ | src/schema/ | 2 | 0 |
src/workers/ | src/ | 6 | 0 |
src/workers/ | src/maintenance/ | 1 | 0 |
src/workers/ | src/middleware/ | 1 | 0 |
src/workers/ | src/repositories/ | 6 | 0 |
src/workers/ | src/services/ | 1 | 0 |
src/workers/ | src/utils/ | 3 | 0 |
Computed by architecture-cleaner analyzer (TypeScript module resolution), production importers under the module root with TypeScript 6.0.3, from git objects of both commits; stored in graph.json. Folders outside the layout are collapsed to their first directory under the module root, so this graph can count fewer folders than the findings log.
The ladder
One transformation per commit: each of the 3 committed steps was certified against its parent before the next one started, with the static checks (K0, K1, K2, K3a, K3b, K3c, K4, K6, K7). The rung certificate of R1 (partial: the run stopped inside the rung) adds the oracles (K8: tsc, unit, openapi). There is no whole-PR certificate (run status: stopped). A FAIL rolls the commit back, and the step replans with the plan entries the failure names pinned in place.
| Rung | Status | Steps | Rung certificate | Duration |
|---|---|---|---|---|
| R0 | passed | – | – | 4 m 04 s |
| R1 | running | 3 certified, 35 pending | PASS (static checks and oracles) partial | 9 m 33 s |
| R2 | not-requested | 0 certified, 21 pending | – | 0.0 s |
| R3 | not-requested | 0 certified | – | 0.0 s |
| R4 | not-requested | 0 certified | – | 0.0 s |
Table view
| Phase | Time |
|---|---|
| preflight | 14.2 s |
| baseline test runs | 3 m 50 s |
| steps (move, commit, certify) | 7 m 11 s |
| rung certificates with oracles | 2 m 22 s |
| other (findings, report, bookkeeping) | 0.1 s |
| wall time | 13 m 37 s |
Failed attempts and rollbacks (1)
1 attempt failed (certified FAIL and rolled back). A commit that fails its certificate is rolled back. They are recorded here and in run.json, never hidden.
Step 2 module/album, attempt 1 of 2; the step ended certified
attempt 1: failed, rolled back round 1, from fd2b27e474, 7 moves, 1 m 44 s
injected fault M2 M2 (Drop one importer rewrite): server/src/services/workflow-execution.service.ts: import specifier 'src/modules/album/album.dto.js' left as in base, 'src/dtos/album.dto.js'
certificate FAIL (K3a, K3b, K3c): K3a server/src/services/workflow-execution.service.ts: line 14: import 'src/dtos/album.dto.js': expected file server/src/modules/album/album.dto.ts (typescript), got unresolved under server/tsconfig.build.json, server/tsconfig.json; K3b server/src/services/workflow-execution.service.ts: site 7 'src/dtos/album.dto.js' (import): base server/src/modules/album/album.dto.ts, head unresolved; K3c server/src/services/workflow-execution.service.ts: nest-cli/emit: import 'src/dtos/album.dto.js' resolves to unresolved (ERR_MODULE_NOT_FOUND), expected server/src/modules/album/album.dto.ts; base server/src/services/workflow-execution.service.ts 'src/dtos/album.dto.js'
Offending: server/src/services/workflow-execution.service.ts
Pinned by this failure: server/src/dtos/album.dto.ts
Certificate of the rolled-back commit: FAIL (static checks) certificates/failed/002-R1-module-album-attempt1.json
certificate JSON · digest sha256:72254a76e23cdf2167d261fbf37d829a80b34856d77581e94722cc575009b8e4
ac certify fd2b27e474..1389c1c3ae (package root server/), profile immich
trees: e6c86400e6..b7b27b645c
pathMap: 7 moves, 20 edited in place, 3437 unchanged, 0 added, 0 deleted
PASS K0 Envelope: inside the envelope: 678 TypeScript vs 3 JavaScript sources under server; no automock, nested package scope, symlink, same-stem pair or unreadable runner config around 7 moved files (5.0 s)
PASS K1 Move-set integrity: 7 moves, 20 files edited in place, nothing added or deleted (2.0 s)
PASS K2 Byte-span confinement: 35 specifier spans changed in 25 files; every other byte identical (0.8 s)
FAIL K3a Resolution identity under TypeScript: 1 violations (1 resolution mismatches) (1.5 s)
server/src/services/workflow-execution.service.ts: line 14: import 'src/dtos/album.dto.js': expected file server/src/modules/album/album.dto.ts (typescript), got unresolved under server/tsconfig.build.json, server/tsconfig.json
FAIL K3b Resolution identity under the test runner: vitest 4.1.11: 1 violations (1 dangling) (8.0 s)
server/src/services/workflow-execution.service.ts: site 7 'src/dtos/album.dto.js' (import): base server/src/modules/album/album.dto.ts, head unresolved
FAIL K3c Resolution identity under the runtime: 1 violations under nest-cli/emit (6.8 s)
server/src/services/workflow-execution.service.ts: nest-cli/emit: import 'src/dtos/album.dto.js' resolves to unresolved (ERR_MODULE_NOT_FOUND), expected server/src/modules/album/album.dto.ts; base server/src/services/workflow-execution.service.ts 'src/dtos/album.dto.js'
PASS K4 Location scan: 7 moved files expose no location; no computed path reaches a change; no old path in code, config or CI (8 findings in docs, comments or ungated coverage settings) (6.7 s)
finding (opaque-dynamic-load) server/src/repositories/database.repository.ts: line 510: import(filePath) loads a module by a path K4 can't evaluate
finding (old-path-in-docs) .github/pull_request_template.md: line 36: 'src/services/' is the directory server/src/services, whose contents change with the move of server/src/services/album.service.spec.ts (moved to server/src/modules/album/album.service.spec.ts)
finding (old-path-in-docs) .github/pull_request_template.md: line 37: 'src/repositories/' is the directory server/src/repositories, whose contents change with the move of server/src/repositories/album-user.repository.ts (moved to server/src/modules/album/album-user.repository.ts)
… 6 more findings
PASS K6 Test inventory: vitest 4.1.11: 105 test files, 2337 tests, per-file load status and case names equal (50.3 s)
PASS K7 Emit layout: 7 emitting programs keep their outDir and rootDir (1 by TypeScript's default) (0.5 s)
finding (default-root-dir) e2e/tsconfig.json: emits into e2e/dist without a rootDir; TypeScript 6.0+ and before 6.0's default stays e2e and e2e
verdict: FAIL (static checks only)
digest: sha256:72254a76e23cdf2167d261fbf37d829a80b34856d77581e94722cc575009b8e4The step then replanned without 1 pinned file: attempt 2 passed.
Every step
Open a step for its moves, its attempts and its certificate.
001 R1 module/activity certified 6 files moved, 17 specifier edits in 12 files, 2 m 25 s
Commit fd2b27e4749f4fe14a54c2474a00c0bffb4513ec, tree e6c86400e6aba4584b58dce69f982ffda608e85f
6 paths moved
server/src/controllers/activity.controller.spec.ts → server/src/modules/activity/activity.controller.spec.ts server/src/controllers/activity.controller.ts → server/src/modules/activity/activity.controller.ts server/src/dtos/activity.dto.ts → server/src/modules/activity/activity.dto.ts server/src/repositories/activity.repository.ts → server/src/modules/activity/activity.repository.ts server/src/services/activity.service.spec.ts → server/src/modules/activity/activity.service.spec.ts server/src/services/activity.service.ts → server/src/modules/activity/activity.service.ts
attempt 1: passed round 1, from 02063972e8, 6 moves, 2 m 25 s
Certificate: PASS (static checks) certificates/001-R1-module-activity.json
certificate JSON · digest sha256:909262855d4acc3f478bb34600f1209cda980a479c70a3cf7232da297ffac519
ac certify 02063972e8..37bbc12433 (package root server/), profile immich
trees: 424df72c34..e6c86400e6
pathMap: 6 moves, 8 edited in place, 3450 unchanged, 0 added, 0 deleted
PASS K0 Envelope: inside the envelope: 678 TypeScript vs 3 JavaScript sources under server; no automock, nested package scope, symlink, same-stem pair or unreadable runner config around 6 moved files (9.6 s)
PASS K1 Move-set integrity: 6 moves, 8 files edited in place, nothing added or deleted (1.6 s)
PASS K2 Byte-span confinement: 17 specifier spans changed in 12 files; every other byte identical (0.8 s)
PASS K3a Resolution identity under TypeScript: 6647 sites in 1100 files resolve to map(base) under every program (458 files in several); 17 rewritten specifiers keep their form (1.5 s)
PASS K3b Resolution identity under the test runner: vitest 4.1.11: 4837 sites in 672 files resolve to map(base) (8.2 s)
PASS K3c Resolution identity under the runtime: 6192 runtime sites resolve to map(base) under nest-cli/emit (3442 rewritten by the build) (6.7 s)
PASS K4 Location scan: 6 moved files expose no location; no computed path reaches a change; no old path in code, config or CI (8 findings in docs, comments or ungated coverage settings) (7.0 s)
finding (opaque-dynamic-load) server/src/repositories/database.repository.ts: line 510: import(filePath) loads a module by a path K4 can't evaluate
finding (old-path-in-docs) .github/pull_request_template.md: line 36: 'src/services/' is the directory server/src/services, whose contents change with the move of server/src/services/activity.service.spec.ts (moved to server/src/modules/activity/activity.service.spec.ts)
finding (old-path-in-docs) .github/pull_request_template.md: line 37: 'src/repositories/' is the directory server/src/repositories, whose contents change with the move of server/src/repositories/activity.repository.ts (moved to server/src/modules/activity/activity.repository.ts)
… 6 more findings
PASS K6 Test inventory: vitest 4.1.11: 105 test files, 2337 tests, per-file load status and case names equal (98.1 s)
PASS K7 Emit layout: 7 emitting programs keep their outDir and rootDir (1 by TypeScript's default) (0.7 s)
finding (default-root-dir) e2e/tsconfig.json: emits into e2e/dist without a rootDir; TypeScript 6.0+ and before 6.0's default stays e2e and e2e
verdict: PASS (static checks only)
digest: sha256:909262855d4acc3f478bb34600f1209cda980a479c70a3cf7232da297ffac519002 R1 module/album certified 1 failed attempt 6 files moved, 28 specifier edits in 20 files, 3 m 15 s
Commit 3876d5c90ee7a1290810181b572a1d92e7f36dc5, tree 7c25e3c579de431aa67a951a497dbfb36026a76e
6 paths moved
server/src/controllers/album.controller.spec.ts → server/src/modules/album/album.controller.spec.ts server/src/controllers/album.controller.ts → server/src/modules/album/album.controller.ts server/src/repositories/album-user.repository.ts → server/src/modules/album/album-user.repository.ts server/src/repositories/album.repository.ts → server/src/modules/album/album.repository.ts server/src/services/album.service.spec.ts → server/src/modules/album/album.service.spec.ts server/src/services/album.service.ts → server/src/modules/album/album.service.ts
attempt 1: failed, rolled back round 1, from fd2b27e474, 7 moves, 1 m 44 s
injected fault M2 M2 (Drop one importer rewrite): server/src/services/workflow-execution.service.ts: import specifier 'src/modules/album/album.dto.js' left as in base, 'src/dtos/album.dto.js'
certificate FAIL (K3a, K3b, K3c): K3a server/src/services/workflow-execution.service.ts: line 14: import 'src/dtos/album.dto.js': expected file server/src/modules/album/album.dto.ts (typescript), got unresolved under server/tsconfig.build.json, server/tsconfig.json; K3b server/src/services/workflow-execution.service.ts: site 7 'src/dtos/album.dto.js' (import): base server/src/modules/album/album.dto.ts, head unresolved; K3c server/src/services/workflow-execution.service.ts: nest-cli/emit: import 'src/dtos/album.dto.js' resolves to unresolved (ERR_MODULE_NOT_FOUND), expected server/src/modules/album/album.dto.ts; base server/src/services/workflow-execution.service.ts 'src/dtos/album.dto.js'
Offending: server/src/services/workflow-execution.service.ts
Pinned by this failure: server/src/dtos/album.dto.ts
Certificate of the rolled-back commit: FAIL (static checks) certificates/failed/002-R1-module-album-attempt1.json
certificate JSON · digest sha256:72254a76e23cdf2167d261fbf37d829a80b34856d77581e94722cc575009b8e4
ac certify fd2b27e474..1389c1c3ae (package root server/), profile immich
trees: e6c86400e6..b7b27b645c
pathMap: 7 moves, 20 edited in place, 3437 unchanged, 0 added, 0 deleted
PASS K0 Envelope: inside the envelope: 678 TypeScript vs 3 JavaScript sources under server; no automock, nested package scope, symlink, same-stem pair or unreadable runner config around 7 moved files (5.0 s)
PASS K1 Move-set integrity: 7 moves, 20 files edited in place, nothing added or deleted (2.0 s)
PASS K2 Byte-span confinement: 35 specifier spans changed in 25 files; every other byte identical (0.8 s)
FAIL K3a Resolution identity under TypeScript: 1 violations (1 resolution mismatches) (1.5 s)
server/src/services/workflow-execution.service.ts: line 14: import 'src/dtos/album.dto.js': expected file server/src/modules/album/album.dto.ts (typescript), got unresolved under server/tsconfig.build.json, server/tsconfig.json
FAIL K3b Resolution identity under the test runner: vitest 4.1.11: 1 violations (1 dangling) (8.0 s)
server/src/services/workflow-execution.service.ts: site 7 'src/dtos/album.dto.js' (import): base server/src/modules/album/album.dto.ts, head unresolved
FAIL K3c Resolution identity under the runtime: 1 violations under nest-cli/emit (6.8 s)
server/src/services/workflow-execution.service.ts: nest-cli/emit: import 'src/dtos/album.dto.js' resolves to unresolved (ERR_MODULE_NOT_FOUND), expected server/src/modules/album/album.dto.ts; base server/src/services/workflow-execution.service.ts 'src/dtos/album.dto.js'
PASS K4 Location scan: 7 moved files expose no location; no computed path reaches a change; no old path in code, config or CI (8 findings in docs, comments or ungated coverage settings) (6.7 s)
finding (opaque-dynamic-load) server/src/repositories/database.repository.ts: line 510: import(filePath) loads a module by a path K4 can't evaluate
finding (old-path-in-docs) .github/pull_request_template.md: line 36: 'src/services/' is the directory server/src/services, whose contents change with the move of server/src/services/album.service.spec.ts (moved to server/src/modules/album/album.service.spec.ts)
finding (old-path-in-docs) .github/pull_request_template.md: line 37: 'src/repositories/' is the directory server/src/repositories, whose contents change with the move of server/src/repositories/album-user.repository.ts (moved to server/src/modules/album/album-user.repository.ts)
… 6 more findings
PASS K6 Test inventory: vitest 4.1.11: 105 test files, 2337 tests, per-file load status and case names equal (50.3 s)
PASS K7 Emit layout: 7 emitting programs keep their outDir and rootDir (1 by TypeScript's default) (0.5 s)
finding (default-root-dir) e2e/tsconfig.json: emits into e2e/dist without a rootDir; TypeScript 6.0+ and before 6.0's default stays e2e and e2e
verdict: FAIL (static checks only)
digest: sha256:72254a76e23cdf2167d261fbf37d829a80b34856d77581e94722cc575009b8e4attempt 2: passed round 1, from fd2b27e474, 6 moves, 1 m 31 s
Certificate: PASS (static checks) certificates/002-R1-module-album.json
certificate JSON · digest sha256:78e6b72fe0cab9da2574f6a455ed76aba71f3ef704d946bbdb494822634d0562
ac certify fd2b27e474..21972e12b6 (package root server/), profile immich
trees: e6c86400e6..7c25e3c579
pathMap: 6 moves, 16 edited in place, 3442 unchanged, 0 added, 0 deleted
PASS K0 Envelope: inside the envelope: 678 TypeScript vs 3 JavaScript sources under server; no automock, nested package scope, symlink, same-stem pair or unreadable runner config around 6 moved files (5.0 s)
PASS K1 Move-set integrity: 6 moves, 16 files edited in place, nothing added or deleted (2.0 s)
PASS K2 Byte-span confinement: 28 specifier spans changed in 20 files; every other byte identical (0.8 s)
PASS K3a Resolution identity under TypeScript: 6647 sites in 1100 files resolve to map(base) under every program (458 files in several); 28 rewritten specifiers keep their form (1.5 s)
PASS K3b Resolution identity under the test runner: vitest 4.1.11: 4837 sites in 672 files resolve to map(base) (8.1 s)
PASS K3c Resolution identity under the runtime: 6192 runtime sites resolve to map(base) under nest-cli/emit (3442 rewritten by the build) (6.4 s)
PASS K4 Location scan: 6 moved files expose no location; no computed path reaches a change; no old path in code, config or CI (8 findings in docs, comments or ungated coverage settings) (6.5 s)
finding (opaque-dynamic-load) server/src/repositories/database.repository.ts: line 510: import(filePath) loads a module by a path K4 can't evaluate
finding (old-path-in-docs) .github/pull_request_template.md: line 36: 'src/services/' is the directory server/src/services, whose contents change with the move of server/src/services/album.service.spec.ts (moved to server/src/modules/album/album.service.spec.ts)
finding (old-path-in-docs) .github/pull_request_template.md: line 37: 'src/repositories/' is the directory server/src/repositories, whose contents change with the move of server/src/repositories/album-user.repository.ts (moved to server/src/modules/album/album-user.repository.ts)
… 6 more findings
PASS K6 Test inventory: vitest 4.1.11: 105 test files, 2337 tests, per-file load status and case names equal (49.3 s)
PASS K7 Emit layout: 7 emitting programs keep their outDir and rootDir (1 by TypeScript's default) (0.5 s)
finding (default-root-dir) e2e/tsconfig.json: emits into e2e/dist without a rootDir; TypeScript 6.0+ and before 6.0's default stays e2e and e2e
verdict: PASS (static checks only)
digest: sha256:78e6b72fe0cab9da2574f6a455ed76aba71f3ef704d946bbdb494822634d0562003 R1 module/api-key certified 6 files moved, 14 specifier edits in 11 files, 1 m 31 s
Commit ac512281719130a99e5b3ede6cb06b648d294c6c, tree 5912e52b568ec2cca43143258ebd3aee23713da2
6 paths moved
server/src/controllers/api-key.controller.spec.ts → server/src/modules/api-key/api-key.controller.spec.ts server/src/controllers/api-key.controller.ts → server/src/modules/api-key/api-key.controller.ts server/src/dtos/api-key.dto.ts → server/src/modules/api-key/api-key.dto.ts server/src/repositories/api-key.repository.ts → server/src/modules/api-key/api-key.repository.ts server/src/services/api-key.service.spec.ts → server/src/modules/api-key/api-key.service.spec.ts server/src/services/api-key.service.ts → server/src/modules/api-key/api-key.service.ts
attempt 1: passed round 1, from 3876d5c90e, 6 moves, 1 m 31 s
Certificate: PASS (static checks) certificates/003-R1-module-api-key.json
certificate JSON · digest sha256:5791cb1a9e19bfecb7516d1acad9515378a4d03b6a2dcc0c29aeb4d5de0d7fed
ac certify 3876d5c90e..1230e2184d (package root server/), profile immich
trees: 7c25e3c579..5912e52b56
pathMap: 6 moves, 7 edited in place, 3451 unchanged, 0 added, 0 deleted
PASS K0 Envelope: inside the envelope: 678 TypeScript vs 3 JavaScript sources under server; no automock, nested package scope, symlink, same-stem pair or unreadable runner config around 6 moved files (5.1 s)
PASS K1 Move-set integrity: 6 moves, 7 files edited in place, nothing added or deleted (2.2 s)
PASS K2 Byte-span confinement: 14 specifier spans changed in 11 files; every other byte identical (0.7 s)
PASS K3a Resolution identity under TypeScript: 6647 sites in 1100 files resolve to map(base) under every program (458 files in several); 14 rewritten specifiers keep their form (1.5 s)
PASS K3b Resolution identity under the test runner: vitest 4.1.11: 4837 sites in 672 files resolve to map(base) (8.3 s)
PASS K3c Resolution identity under the runtime: 6192 runtime sites resolve to map(base) under nest-cli/emit (3442 rewritten by the build) (6.7 s)
PASS K4 Location scan: 6 moved files expose no location; no computed path reaches a change; no old path in code, config or CI (8 findings in docs, comments or ungated coverage settings) (6.3 s)
finding (opaque-dynamic-load) server/src/repositories/database.repository.ts: line 510: import(filePath) loads a module by a path K4 can't evaluate
finding (old-path-in-docs) .github/pull_request_template.md: line 36: 'src/services/' is the directory server/src/services, whose contents change with the move of server/src/services/api-key.service.spec.ts (moved to server/src/modules/api-key/api-key.service.spec.ts)
finding (old-path-in-docs) .github/pull_request_template.md: line 37: 'src/repositories/' is the directory server/src/repositories, whose contents change with the move of server/src/repositories/api-key.repository.ts (moved to server/src/modules/api-key/api-key.repository.ts)
… 6 more findings
PASS K6 Test inventory: vitest 4.1.11: 105 test files, 2337 tests, per-file load status and case names equal (49.2 s)
PASS K7 Emit layout: 7 emitting programs keep their outDir and rootDir (1 by TypeScript's default) (0.5 s)
finding (default-root-dir) e2e/tsconfig.json: emits into e2e/dist without a rootDir; TypeScript 6.0+ and before 6.0's default stays e2e and e2e
verdict: PASS (static checks only)
digest: sha256:5791cb1a9e19bfecb7516d1acad9515378a4d03b6a2dcc0c29aeb4d5de0d7fed56 steps never ran (run status: stopped).
Seconds per step, from run.json attempt timings.
Table view
| # | Rung | Group | Move + commit (s) | Certify (s) | Other (s) | Failed attempts (s) |
|---|---|---|---|---|---|---|
| 1 | R1 | module/activity | 8.8 | 135.6 | 0.1 | 0.0 |
| 2 | R1 | module/album | 9.0 | 81.7 | 0.1 | 104.0 |
| 3 | R1 | module/api-key | 9.0 | 82.0 | 0.1 | 0.0 |
Rung certificates
R1 rung certificate: PASS (static checks and oracles) rungs/R1.json
certificate JSON · digest sha256:8ea0a7596256d5ec473d99d32b042f0e410bb145c4b461fc4b0fed6527024777
ac certify 02063972e8..ac51228171 (package root server/), profile immich
trees: 424df72c34..5912e52b56
pathMap: 18 moves, 18 edited in place, 3428 unchanged, 0 added, 0 deleted
PASS K0 Envelope: inside the envelope: 678 TypeScript vs 3 JavaScript sources under server; no automock, nested package scope, symlink, same-stem pair or unreadable runner config around 18 moved files (0.3 s)
PASS K1 Move-set integrity: 18 moves, 18 files edited in place, nothing added or deleted (2.4 s)
PASS K2 Byte-span confinement: 59 specifier spans changed in 30 files; every other byte identical (0.9 s)
PASS K3a Resolution identity under TypeScript: 6647 sites in 1100 files resolve to map(base) under every program (458 files in several); 59 rewritten specifiers keep their form (1.5 s)
PASS K3b Resolution identity under the test runner: vitest 4.1.11: 4837 sites in 672 files resolve to map(base) (8.1 s)
PASS K3c Resolution identity under the runtime: 6192 runtime sites resolve to map(base) under nest-cli/emit (3442 rewritten by the build) (6.5 s)
PASS K4 Location scan: 18 moved files expose no location; no computed path reaches a change; no old path in code, config or CI (8 findings in docs, comments or ungated coverage settings) (6.2 s)
finding (opaque-dynamic-load) server/src/repositories/database.repository.ts: line 510: import(filePath) loads a module by a path K4 can't evaluate
finding (old-path-in-docs) .github/pull_request_template.md: line 36: 'src/services/' is the directory server/src/services, whose contents change with the move of server/src/services/activity.service.spec.ts (moved to server/src/modules/activity/activity.service.spec.ts)
finding (old-path-in-docs) .github/pull_request_template.md: line 37: 'src/repositories/' is the directory server/src/repositories, whose contents change with the move of server/src/repositories/activity.repository.ts (moved to server/src/modules/activity/activity.repository.ts)
… 6 more findings
PASS K6 Test inventory: vitest 4.1.11: 105 test files, 2337 tests, per-file load status and case names equal (0.0 s)
PASS K7 Emit layout: 7 emitting programs keep their outDir and rootDir (1 by TypeScript's default) (0.5 s)
finding (default-root-dir) e2e/tsconfig.json: emits into e2e/dist without a rootDir; TypeScript 6.0+ and before 6.0's default stays e2e and e2e
PASS K8 Oracles on the commit: tsc exit 0; unit 105/105 files and 2,337/2,337 cases equal to base (head: 105/105 files load, 2,337 passed, 0 failed, 0 skipped); openapi byte-identical to the base's open-api/immich-openapi-specs.json (947,932 bytes) (114.0 s)
verdict: PASS (static checks and oracles)
digest: sha256:8ea0a7596256d5ec473d99d32b042f0e410bb145c4b461fc4b0fed6527024777The whole PR
No whole-PR certificate.
Findings: recorded, never fixed
A good restructure makes existing bugs obvious; fixing them is never part of it. These 23 findings were found by deterministic collectors and are left exactly as they are in the code.
| Kind | Findings |
|---|---|
| module-cycle | 1 |
| god-injection | 1 |
| multi-writer-table | 3 |
| injected-fault | 1 |
| pinned | 1 |
| plan-warning | 10 |
| old-path-in-docs | 2 |
| coverage-scope | 1 |
| default-root-dir | 1 |
| opaque-dynamic-load | 1 |
| ungated-coverage-glob | 1 |
No narration: every finding shows its deterministic evidence only.
Sources
| Source | What it contributed |
|---|---|
target | facts at 02063972e8: 269 movable files, 1759 edges, 269 placed by the plan |
plan-graph | no committed boundary rules (R4 didn't run): cycles from the plan's groups over the facts, 1 strongly connected sets; no back-edges without R4's order |
facts | 3 tables with writers in several groups, 1 god-injection base classes |
analyzer | 458 production files analyzed, 0 import test code |
validator | 10 warnings on the run's plan |
certificate | 4 certificates read (steps, rungs, whole PR) |
run | 8 run.json findings |
module-cycle (1)
55 groups form one import cycle F-f0f96c77a088
Evidence
55 of 59 groups are strongly connected (from the planner's facts at 02063972e8, grouped by the run's plan.yaml): each reaches every other through imports. Members: module/activity, module/album, module/api-key, module/asset, module/auth, module/cluster-group, module/config, module/database-backup, module/download, module/duplicate, module/integrity, module/job, module/library, module/machine-learning, module/maintenance, module/map, module/memory, module/notification, module/ocr, module/partner, module/person, module/plugin, module/queue, module/search, module/server, module/session, module/shared-link, module/stack, module/sync, module/system-metadata, module/tag, module/timeline, module/trash, module/user, module/version, module/video-stream, module/view, module/workflow, platform/access, platform/bootstrap, platform/cron, platform/database, platform/event, platform/file, platform/http-response, platform/logging, platform/media, platform/metadata, platform/move, platform/registry, platform/storage, platform/telemetry, platform/transcoding, platform/websocket, shared/shared. Inside the set: 506 edges between them over 1437 file pairs. These 118 edges (193 file pairs) close every cycle; without them the set is acyclic: - module/search → module/asset (7 file pairs, e.g. server/src/controllers/search.controller.ts → server/src/dtos/asset-response.dto.ts) - module/auth → module/user (6 file pairs, e.g. server/src/controllers/auth.controller.ts → server/src/dtos/user.dto.ts) - module/album → module/asset (5 file pairs, e.g. server/src/controllers/album.controller.ts → server/src/dtos/asset-ids.response.dto.ts) - module/shared-link → module/asset (5 file pairs, e.g. server/src/controllers/shared-link.controller.ts → server/src/dtos/asset-ids.response.dto.ts) - platform/media → module/asset (5 file pairs, e.g. server/src/repositories/media.repository.ts → server/src/dtos/editing.dto.ts) - platform/storage → module/asset (5 file pairs, e.g. server/src/cores/storage.core.ts → server/src/repositories/asset.repository.ts) - module/stack → module/asset (4 file pairs, e.g. server/src/controllers/stack.controller.ts → server/src/dtos/asset-ids.response.dto.ts) - module/tag → module/asset (4 file pairs, e.g. server/src/controllers/tag.controller.ts → server/src/dtos/asset-ids.response.dto.ts) - platform/access → module/person (4 file pairs, e.g. server/src/repositories/access.repository.ts → server/src/dtos/person.dto.ts) - module/asset → platform/registry (3 file pairs, e.g. server/src/services/asset-file.service.ts → server/src/services/base.service.ts) - module/job → module/asset (3 file pairs, e.g. server/src/services/job.service.ts → server/src/dtos/asset-response.dto.ts) - module/notification → module/asset (3 file pairs, e.g. server/src/services/notification.service.ts → server/src/dtos/asset-response.dto.ts) - module/partner → module/user (3 file pairs, e.g. server/src/dtos/partner.dto.ts → server/src/dtos/user.dto.ts) - module/search → module/person (3 file pairs, e.g. server/src/controllers/search.controller.ts → server/src/dtos/person.dto.ts) - module/server → module/user (3 file pairs, e.g. server/src/controllers/server.controller.ts → server/src/dtos/license.dto.ts) - … 103 more edges (130 file pairs)
Files: server/src/controllers/album.controller.ts server/src/controllers/auth.controller.ts server/src/controllers/search.controller.ts server/src/controllers/server.controller.ts server/src/controllers/shared-link.controller.ts server/src/controllers/stack.controller.ts server/src/controllers/tag.controller.ts server/src/cores/storage.core.ts and 14 more
Source: plan-graph
god-injection (1)
BaseService injects 56 members into 51 classes F-190847636c3d
Evidence
BaseService (server/src/services/base.service.ts) takes 56 constructor-injected members (56 of them repositories), and 51 classes extend it, so each receives all 56. Each subclass reads 5.7 of them on average through this.<member> (median 5, min 1, max 15 in MetadataService); every member has a reader. Most read: logger (33 classes), jobRepository (23 classes), assetRepository (21 classes), eventRepository (18 classes), userRepository (18 classes). Per class (members read of 56): - MetadataService (server/src/services/metadata.service.ts): 15 (albumRepository, assetJobRepository, assetRepository, cryptoRepository, databaseRepository, eventRepository, jobRepository, logger, … 7 more) - PersonService (server/src/services/person.service.ts): 15 (assetJobRepository, assetRepository, clusterGroupRepository, cryptoRepository, databaseRepository, jobRepository, logger, machineLearningRepository, … 7 more) - AssetService (server/src/services/asset.service.ts): 13 (albumRepository, assetEditRepository, assetJobRepository, assetRepository, eventRepository, jobRepository, logger, ocrRepository, … 5 more) - AuthService (server/src/services/auth.service.ts): 10 (apiKeyRepository, cryptoRepository, eventRepository, jobRepository, logger, mediaRepository, oauthRepository, sessionRepository, … 2 more) - LibraryService (server/src/services/library.service.ts): 10 (assetJobRepository, assetRepository, cronRepository, cryptoRepository, databaseRepository, eventRepository, jobRepository, libraryRepository, … 2 more) - UserService (server/src/services/user.service.ts): 10 (albumRepository, assetRepository, configRepository, cryptoRepository, eventRepository, jobRepository, logger, mediaRepository, … 2 more) - CliService (server/src/services/cli.service.ts): 9 (appRepository, assetRepository, cryptoRepository, databaseRepository, personRepository, sessionRepository, storageRepository, systemMetadataRepository, … 1 more) - DuplicateService (server/src/services/duplicate.service.ts): 9 (albumRepository, assetJobRepository, assetRepository, cryptoRepository, duplicateRepository, eventRepository, jobRepository, logger, … 1 more) - IntegrityService (server/src/services/integrity.service.ts): 9 (assetRepository, cronRepository, databaseRepository, eventRepository, integrityRepository, jobRepository, logger, storageRepository, … 1 more) - NotificationService (server/src/services/notification.service.ts): 9 (albumRepository, assetJobRepository, assetRepository, emailRepository, jobRepository, logger, notificationRepository, userRepository, … 1 more) - VersionService (server/src/services/version.service.ts): 9 (configRepository, cronRepository, databaseRepository, jobRepository, logger, serverInfoRepository, systemMetadataRepository, versionRepository, … 1 more) - MediaService (server/src/services/media.service.ts): 8 (assetJobRepository, assetRepository, jobRepository, logger, mediaRepository, ocrRepository, personRepository, storageRepository) - MemoryService (server/src/services/memory.service.ts): 8 (accessRepository, assetRepository, databaseRepository, logger, memoryRepository, personRepository, systemMetadataRepository, userRepository) - StorageTemplateService (server/src/services/storage-template.service.ts): 8 (albumRepository, assetJobRepository, databaseRepository, jobRepository, logger, moveRepository, storageRepository, userRepository) - UserAdminService (server/src/services/user-admin.service.ts): 8 (albumRepository, assetRepository, cryptoRepository, eventRepository, jobRepository, logger, sessionRepository, userRepository) - WorkflowExecutionService (server/src/services/workflow-execution.service.ts): 8 (configRepository, cryptoRepository, databaseRepository, jobRepository, logger, pluginRepository, storageRepository, workflowRepository) - AlbumService (server/src/services/album.service.ts): 7 (accessRepository, albumRepository, albumUserRepository, eventRepository, logger, mapRepository, userRepository) - AssetMediaService (server/src/services/asset-media.service.ts): 7 (albumRepository, assetRepository, eventRepository, jobRepository, logger, sharedLinkRepository, storageRepository) - ServerService (server/src/services/server.service.ts): 7 (configRepository, cryptoRepository, logger, serverInfoRepository, storageRepository, systemMetadataRepository, userRepository) - JobService (server/src/services/job.service.ts): 6 (assetEditRepository, assetRepository, eventRepository, jobRepository, logger, websocketRepository) - OcrService (server/src/services/ocr.service.ts): 6 (assetJobRepository, assetRepository, jobRepository, logger, machineLearningRepository, ocrRepository) - SmartInfoService (server/src/services/smart-info.service.ts): 6 (assetJobRepository, databaseRepository, jobRepository, logger, machineLearningRepository, searchRepository) - StorageService (server/src/services/storage.service.ts): 6 (assetRepository, configRepository, databaseRepository, logger, storageRepository, systemMetadataRepository) - TranscodingService (server/src/services/transcoding.service.ts): 6 (databaseRepository, logger, processRepository, storageRepository, videoStreamRepository, websocketRepository) - ClusterGroupService (server/src/services/cluster-group.service.ts): 5 (clusterGroupRepository, eventRepository, jobRepository, personRepository, userRepository) - DownloadService (server/src/services/download.service.ts): 5 (assetRepository, downloadRepository, logger, storageRepository, userRepository) - MaintenanceService (server/src/services/maintenance.service.ts): 5 (appRepository, eventRepository, logger, storageRepository, systemMetadataRepository) - QueueService (server/src/services/queue.service.ts): 5 (cronRepository, databaseRepository, eventRepository, jobRepository, logger) - SearchService (server/src/services/search.service.ts): 5 (assetRepository, machineLearningRepository, partnerRepository, personRepository, searchRepository) - TagService (server/src/services/tag.service.ts): 5 (accessRepository, assetRepository, eventRepository, jobRepository, tagRepository) - HlsService (server/src/services/hls.service.ts): 4 (cryptoRepository, storageRepository, videoStreamRepository, websocketRepository) - SharedLinkService (server/src/services/shared-link.service.ts): 4 (cryptoRepository, logger, sharedLinkAssetRepository, sharedLinkRepository) - SyncService (server/src/services/sync.service.ts): 4 (logger, sessionRepository, syncCheckpointRepository, syncRepository) - SystemConfigService (server/src/services/system-config.service.ts): 4 (configRepository, eventRepository, logger, machineLearningRepository) - TrashService (server/src/services/trash.service.ts): 4 (eventRepository, jobRepository, logger, trashRepository) - DatabaseService (server/src/services/database.service.ts): 3 (configRepository, databaseRepository, logger) - MapService (server/src/services/map.service.ts): 3 (albumRepository, mapRepository, partnerRepository) - NotificationAdminService (server/src/services/notification-admin.service.ts): 3 (emailRepository, notificationRepository, userRepository) - PartnerService (server/src/services/partner.service.ts): 3 (logger, partnerRepository, userRepository) - SessionService (server/src/services/session.service.ts): 3 (cryptoRepository, logger, sessionRepository) - StackService (server/src/services/stack.service.ts): 3 (assetRepository, eventRepository, stackRepository) - ApiKeyService (server/src/services/api-key.service.ts): 2 (apiKeyRepository, cryptoRepository) - AssetFileService (server/src/services/asset-file.service.ts): 2 (assetFileRepository, jobRepository) - TelemetryService (server/src/services/telemetry.service.ts): 2 (telemetryRepository, userRepository) - TimelineService (server/src/services/timeline.service.ts): 2 (assetRepository, partnerRepository) - WorkflowService (server/src/services/workflow.service.ts): 2 (pluginRepository, workflowRepository) - ActivityService (server/src/services/activity.service.ts): 1 (activityRepository) - AuthAdminService (server/src/services/auth-admin.service.ts): 1 (userRepository) - PluginService (server/src/services/plugin.service.ts): 1 (pluginRepository) - SystemMetadataService (server/src/services/system-metadata.service.ts): 1 (systemMetadataRepository) - ViewService (server/src/services/view.service.ts): 1 (viewRepository)
Files: server/src/services/activity.service.ts server/src/services/album.service.ts server/src/services/api-key.service.ts server/src/services/asset-file.service.ts server/src/services/asset-media.service.ts server/src/services/asset.service.ts server/src/services/auth-admin.service.ts server/src/services/auth.service.ts and 44 more
Source: facts
multi-writer-table (3)
Table asset is written by 4 groups F-471f7dbe2fc2
Evidence
Table asset is written by 4 files in 4 plan groups (and read by 23 files in 22 groups): - module/asset: server/src/repositories/asset.repository.ts - module/duplicate: server/src/repositories/duplicate.repository.ts - module/stack: server/src/repositories/stack.repository.ts - module/trash: server/src/repositories/trash.repository.ts
Files: server/src/repositories/asset.repository.ts server/src/repositories/duplicate.repository.ts server/src/repositories/stack.repository.ts server/src/repositories/trash.repository.ts
Source: facts
Table cluster_group is written by 2 groups F-bdcfcf0f1886
Evidence
Table cluster_group is written by 2 files in 2 plan groups: - module/cluster-group: server/src/repositories/cluster-group.repository.ts - module/person: server/src/repositories/person.repository.ts
Files: server/src/repositories/cluster-group.repository.ts server/src/repositories/person.repository.ts
Source: facts
Table session_sync_checkpoint is written by 2 groups F-e7b889cd5d1e
Evidence
Table session_sync_checkpoint is written by 2 files in 2 plan groups (and read by 1 file in 1 group): - module/session: server/src/repositories/session.repository.ts - module/sync: server/src/repositories/sync-checkpoint.repository.ts
Files: server/src/repositories/session.repository.ts server/src/repositories/sync-checkpoint.repository.ts
Source: facts
injected-fault (1)
Injected fault (--inject-fault): step 2 F-0daf1592fc4d
Evidence
step 2 (R1): seeded wrong move (--inject-fault): M2 (Drop one importer rewrite): server/src/services/workflow-execution.service.ts: import specifier 'src/modules/album/album.dto.js' left as in base, 'src/dtos/album.dto.js'
Source: run; steps 2
pinned (1)
Files pinned by a replan: step 2 F-0056b169b7fc
Evidence
step 2 (R1): attempt 1 (failed): certificate FAIL (K3a, K3b, K3c): K3a server/src/services/workflow-execution.service.ts: line 14: import 'src/dtos/album.dto.js': expected file server/src/modules/album/album.dto.ts (typescript), got unresolved under server/tsconfig.build.json, server/tsconfig.json; K3b server/src/services/workflow-execution.service.ts: site 7 'src/dtos/album.dto.js' (import): base server/src/modules/album/album.dto.ts, head unresolved; K3c server/src/services/workflow-execution.service.ts: nest-cli/emit: import 'src/dtos/album.dto.js' resolves to unresolved (ERR_MODULE_NOT_FOUND), expected server/src/modules/album/album.dto.ts; base server/src/services/workflow-execution.service.ts 'src/dtos/album.dto.js' 1 file: server/src/dtos/album.dto.ts
Files: server/src/dtos/album.dto.ts
Source: run; steps 2
plan-warning (10)
Plan warning (one-file-platform): platform/http-client F-14d96dec2313
Evidence
The plan validator's rule one-file-platform, on the run's plan.yaml (group platform/http-client): platform/http-client holds one file, and no other planned group uses it: consider folding it into the concern or feature it serves
Files: server/src/utils/fetch.ts
Source: validator
Plan warning (one-file-platform): platform/check F-175fe3a4820a
Evidence
The plan validator's rule one-file-platform, on the run's plan.yaml (group platform/check): platform/check holds one file, and no other planned group uses it: consider folding it into the concern or feature it serves
Files: server/src/commands/schema-check.ts
Source: validator
Plan warning (singleton-group): module/machine-learning F-545a4b88a62f
Evidence
The plan validator's rule singleton-group, on the run's plan.yaml (group module/machine-learning): module/machine-learning holds one file
Files: server/src/repositories/machine-learning.repository.ts
Source: validator
Plan warning (unsupported-merge): module/auth F-692ad4017c11
Evidence
The plan validator's rule unsupported-merge, on the run's plan.yaml (group module/auth): module/auth takes draft group "grant" (src/commands/grant-admin.ts): no shared word, edge, table or route
Source: validator
Plan warning (platform-feature): platform/move F-6dc722024105
Evidence
The plan validator's rule platform-feature, on the run's plan.yaml (group platform/move): src/repositories/move.repository.ts writes tables (move_history): a feature, not plumbing
Files: server/src/repositories/move.repository.ts
Source: validator
Plan warning (one-file-platform): platform/move F-af06f12438b8
Evidence
The plan validator's rule one-file-platform, on the run's plan.yaml (group platform/move): platform/move holds one file, and only platform/storage uses it: consider folding it there
Files: server/src/repositories/move.repository.ts
Source: validator
Plan warning (platform-feature): platform/bootstrap F-e1c975dc8064
Evidence
The plan validator's rule platform-feature, on the run's plan.yaml (group platform/bootstrap): src/controllers/app.controller.ts serves routes: a feature, not plumbing
Files: server/src/controllers/app.controller.ts
Source: validator
Plan warning (impure-shared): shared/shared F-e3b63d08f742
Evidence
The plan validator's rule impure-shared, on the run's plan.yaml (group shared/shared): src/services/api.service.ts is a service; shared/ holds pure code only
Files: server/src/services/api.service.ts
Source: validator
Plan warning (one-file-platform): platform/transcoding F-fa4aa2cae116
Evidence
The plan validator's rule one-file-platform, on the run's plan.yaml (group platform/transcoding): platform/transcoding holds one file, and no other planned group uses it: consider folding it into the concern or feature it serves
Files: server/src/services/transcoding.service.ts
Source: validator
Plan warning (unsupported-merge): module/auth F-ff0edb54f50f
Evidence
The plan validator's rule unsupported-merge, on the run's plan.yaml (group module/auth): module/auth takes draft group "password-login" (src/commands/password-login.ts): no shared word, edge, table or route
Source: validator
old-path-in-docs (2)
Docs name old paths (K4): docs/docs/developer/architecture.mdx F-68921a0c7282
Evidence
K4 reported 3 distinct findings in docs/docs/developer/architecture.mdx, 12 times (steps 1–3, rungs/R1.json): - line 60: 'src/repositories' is the directory server/src/repositories, whose contents change with the move of server/src/repositories/activity.repository.ts (moved to server/src/modules/activity/activity.repository.ts) (steps 1–3, rungs/R1.json) - line 60: 'src/services' is the directory server/src/services, whose contents change with the move of server/src/services/activity.service.spec.ts (moved to server/src/modules/activity/activity.service.spec.ts) (steps 1–3, rungs/R1.json) - line 64: 'src/controllers' is the directory server/src/controllers, whose contents change with the move of server/src/controllers/activity.controller.spec.ts (moved to server/src/modules/activity/activity.controller.spec.ts) (steps 1–3, rungs/R1.json)
Files: docs/docs/developer/architecture.mdx
Source: certificate; steps 1, 2, 3; certificates rungs/R1.json
Docs name old paths (K4): .github/pull_request_template.md F-8759fa26d236
Evidence
K4 reported 3 distinct findings in .github/pull_request_template.md, 12 times (steps 1–3, rungs/R1.json): - line 36: 'src/services/' is the directory server/src/services, whose contents change with the move of server/src/services/activity.service.spec.ts (moved to server/src/modules/activity/activity.service.spec.ts) (steps 1–3, rungs/R1.json) - line 37: 'src/repositories/' is the directory server/src/repositories, whose contents change with the move of server/src/repositories/activity.repository.ts (moved to server/src/modules/activity/activity.repository.ts) (steps 1–3, rungs/R1.json) - line 37: 'src/services/' is the directory server/src/services, whose contents change with the move of server/src/services/activity.service.spec.ts (moved to server/src/modules/activity/activity.service.spec.ts) (steps 1–3, rungs/R1.json)
Files: .github/pull_request_template.md
Source: certificate; steps 1, 2, 3; certificates rungs/R1.json
coverage-scope (1)
Coverage globs match other files (K4): server/test/vitest.config.mjs F-800da5f4439a
Evidence
K4 reported 2 distinct findings in server/test/vitest.config.mjs, 8 times (steps 1–3, rungs/R1.json): - line 19: 'src/services/**' is the glob server/src/services/** whose matches change (2 moved files, e.g. server/src/services/activity.service.spec.ts -> server/src/modules/activity/activity.service.spec.ts) of server/src/services/activity.service.spec.ts (moved to server/src/modules/activity/activit… (steps 1–3, rungs/R1.json) - line 21: 'src/services/*.spec.ts' is the glob server/src/services/*.spec.ts whose matches change (1 moved files, e.g. server/src/services/activity.service.spec.ts -> server/src/modules/activity/activity.service.spec.ts) of server/src/services/activity.service.spec.ts (moved to server/src/modules/ac… (steps 1–3, rungs/R1.json)
Files: server/test/vitest.config.mjs
Source: certificate; steps 1, 2, 3; certificates rungs/R1.json
default-root-dir (1)
Emit without a rootDir (K7): e2e/tsconfig.json F-966da7d59056
Evidence
K7 reported one finding in e2e/tsconfig.json, 4 times (steps 1–3, rungs/R1.json): - emits into e2e/dist without a rootDir; TypeScript 6.0+ and before 6.0's default stays e2e and e2e (steps 1–3, rungs/R1.json)
Files: e2e/tsconfig.json
Source: certificate; steps 1, 2, 3; certificates rungs/R1.json
opaque-dynamic-load (1)
A module loaded by a computed path (K4): server/src/repositories/database.repository.ts F-70d9e19108a1
Evidence
K4 reported one finding in server/src/repositories/database.repository.ts, 4 times (steps 1–3, rungs/R1.json): - line 510: import(filePath) loads a module by a path K4 can't evaluate (steps 1–3, rungs/R1.json)
Files: server/src/repositories/database.repository.ts
Source: certificate; steps 1, 2, 3; certificates rungs/R1.json
ungated-coverage-glob (1)
Coverage globs match other files, with no gate: server/test/vitest.config.mjs F-89500b32bdee
Evidence
The run recorded 2 distinct findings in server/test/vitest.config.mjs, 6 times (steps 1–3): - server/test/vitest.config.mjs line 19 [test.coverage.include]: coverage glob 'src/services/**' (server/src/services/**) matches differently for server/src/services/activity.service.ts (moving to server/src/modules/activity/activity.service.ts), server/src/services/activity.service.spec.ts (moving t… (steps 1–3) - server/test/vitest.config.mjs line 21 [test.coverage.exclude]: coverage glob 'src/services/*.spec.ts' (server/src/services/*.spec.ts) matches differently for server/src/services/activity.service.spec.ts (moving to server/src/modules/activity/activity.service.spec.ts); nothing in server/test/vitest.… (steps 1–3)
Files: server/test/vitest.config.mjs
Source: run; steps 1, 2, 3
Table access
No plan/plan.json with the planner's facts in this run dir, so there are no table accesses to show.
Cost
This run: the plan cost $0.1998 when it was recorded; planner spend during the run $0.0000. Replaying the plan from the committed cassettes costs $0.
The whole project's spend on Nebius Token Factory, from the gateway's ledger (budget/ledger.jsonl): $24.3980 of the $50.00 hard cap. The lines marked reconciled bring the ledger to the Nebius console bill: what Token Factory billed differently from the gateway's count (a lost call, cached input at its cached price, calls it didn't bill). The G3 runs (opencode with Nemotron 3 Super and, in S9, with Ultra: the generic-agent baseline) account for $8.9572 of it. The runs tf-probes, g1, g3-smoke, g3-immich, g3-mcphub, g3u-smoke, g3u-immich, g3u-immich-persistent are carried over from the gate spike as one line each.
Table view
| Budget run | Paid calls | Cost | Cap | Models | Notes |
|---|---|---|---|---|---|
tf-probes | 82 | $0.0250 | – | – | carried over from spike/gates:spike/llm/ledger.jsonl: 82 paid calls, $0.0250 |
g1 | 53 | $1.7552 | – | – | carried over from spike/gates:spike/llm/ledger.jsonl: 53 paid calls, $1.7042 reconciled, $0.0510: Nebius console 2026-10-14 21:31 UTC ($9.31) vs ledger ($9.259): Super output +58k and input +8k tokens are one G1 call lost to 'fetch failed' at 2026-10-02T13:46:58Z (estimate $0.0601), which the spike gateway booked at $0 and Token Factory billed |
g3-smoke | 6 | $0.0143 | – | – | carried over from spike/gates:spike/llm/ledger.jsonl: 6 paid calls, $0.0143 |
g3-immich | 251 | $4.9333 | – | – | carried over from spike/gates:spike/llm/ledger.jsonl: 251 paid calls, $4.9333 |
g3-mcphub | 62 | $0.8603 | – | – | carried over from spike/gates:spike/llm/ledger.jsonl: 62 paid calls, $0.8603 |
s5 | 17 | $1.2877 | $3.00 | Nemotron 3 Ultra | |
s6 | 38 | $0.4343 | $3.00 | Nemotron 3 Ultra, Nemotron 3.5 Lightning | |
s7 | 12 | $1.1213 | $5.00 | Nemotron 3 Ultra | |
s8 | 3 | $0.1114 | $3.00 | Nemotron 3 Ultra | |
s8b | 70 | $3.7268 | $7.00 | Nemotron 3 Ultra, Nemotron 3.5 Super VL | reconciled, −$0.2723: Nebius console export, 2026-09-24 to 10-24 (corupta, 2026-10-24): $24.40 billed; Ultra's cached input billed at its cached price, $0.12/M (from 2026-10-20 20:01 UTC at the latest; S7's hits on 2026-10-17 were billed in full), which the ledger charged at $1.00/M: 252,416 tokens; Super VL's cached input at $0.06/M, which the ledger charged at $0.30/M: 208,896 tokens reconciled, $0.0000: Nebius console export, 2026-09-24 to 10-24 (corupta, 2026-10-24): $24.40 billed; the Super VL call stopped at 2026-10-20T20:54Z leaves no trace in the bill (Super VL's billed input, 0.57M, is the 200 responses' 565,968 uncached prompt tokens; billed without a cache hit, its ~11k-token prompt would have made it 0.58M; sub-cent either way): its $0.0387 reservation settles at $0 |
s8c | 3 | $0.5941 | $3.00 | Nemotron 3.5 Super VL | reconciled, −$0.7033: Nebius console export, 2026-09-24 to 10-24 (corupta, 2026-10-24): $24.40 billed; Super VL's cached input at $0.06/M, which the ledger charged at $0.30/M: 6,528 tokens; the non-streamed call cut at 600 s (HTTP 504, 2026-10-21T00:31Z), booked at its $0.7017 estimate, was not billed (Super VL's billed output, 9.09M, matches its 200 responses' 9,092,987 tokens to the console's 0.01M) |
s8d | 30 | $6.3850 | $10.00 | Nemotron 3.5 Super VL | reconciled, −$0.0345: Nebius console export, 2026-09-24 to 10-24 (corupta, 2026-10-24): $24.40 billed; Super VL's cached input at $0.06/M, which the ledger charged at $0.30/M: 143,616 tokens |
g3u-smoke | 7 | $0.0570 | – | – | carried over from spike/g3-ultra:spike/llm/ledger.jsonl: 7 paid calls, $0.0762 reconciled, −$0.0191: Nebius console export, 2026-09-24 to 10-24 (corupta, 2026-10-24): $24.40 billed; Ultra's cached input billed at its cached price, $0.12/M (from 2026-10-20 20:01 UTC at the latest; S7's hits on 2026-10-17 were billed in full), which the ledger charged at $1.00/M: 21,760 tokens |
g3u-immich | 49 | $0.5456 | – | – | carried over from spike/g3-ultra:spike/llm/ledger.jsonl: 49 paid calls, $1.8630 reconciled, −$1.3174: Nebius console export, 2026-09-24 to 10-24 (corupta, 2026-10-24): $24.40 billed; Ultra's cached input billed at its cached price, $0.12/M (from 2026-10-20 20:01 UTC at the latest; S7's hits on 2026-10-17 were billed in full), which the ledger charged at $1.00/M: 1,497,088 tokens |
g3u-immich-persistent | 170 | $2.5468 | – | – | carried over from spike/g3-ultra:spike/llm/ledger.jsonl: 170 paid calls, $11.7612 reconciled, −$9.2144: Nebius console export, 2026-09-24 to 10-24 (corupta, 2026-10-24): $24.40 billed; Ultra's cached input billed at its cached price, $0.12/M (from 2026-10-20 20:01 UTC at the latest; S7's hits on 2026-10-17 were billed in full), which the ledger charged at $1.00/M: 10,470,912 tokens |
| total | 853 | $24.3980 | $50.00 |
A/B: the same task, a generic agent
G3 gave opencode 1.18.34 with NVIDIA Nemotron 3 Super on Nebius Token Factory the same restructure, with a fixed prompt and no human input. Its branches were certified in session S4 by our checker, the version before this run's (certificate format 1; K7 came later). The same agent on Nemotron 3 Ultra, the model ac plans with (S9), is on the site's A/B page: its single-shot changed nothing, and its persistent run hit its $12 cap in turn 1 with every import of the moved files dangling.
immich server/ @ 02063972e8
Target: immich @ 02063972e8. Base: tsc 0 errors; vitest 105 test files, 2,337 cases (docs/gates.md, G2); the OpenAPI spec is 947,932 bytes (the certificates' K8).
A green test count is not proof. On immich, the branch g3/opencode-super (opencode + Nemotron 3 Super, single-shot) still passes all 2,337 of the base's test cases, while 66 of its 171 test files fail to load and tsc reports 1,680 errors (its certificate: K6, K8).
| ac, the full ladder (ours) | ac, one R1-style step (ours) | opencode + Nemotron 3 Super, single-shot | opencode + Nemotron 3 Super, persistent | Source | |
|---|---|---|---|---|---|
| Who | ac architecture-cleaner: Nemotron 3 Ultra plans, the executor moves, the certifier checks every commit | ac architecture-cleaner's executor, one move of 292 of the 302 controllers, services, repositories and DTOs (the 3 index.ts barrels and the barrel's spec, two process.cwd() specs, the three import.meta.dirname users and services/shared/user-methods.ts stay) | opencode 1.18.34, NVIDIA Nemotron 3 Super on Nebius Token Factory, one `opencode run` with the fixed prompt | the same agent; whenever it stopped, an automated reply reported typecheck and test results and asked it to continue | |
| Branch | ac/s6-ladder (S6)run report | ac/s3-r1 (S3) | g3/opencode-super (G3 (S2)) | g3/opencode-super-persistent (G3 (S2)) | |
| Outcome | Completed unattended: 63 commits, each certified on its first attempt; every rung and the whole PR PASS with the oracles | One certified commit | Stopped after 169 s and asked the user to run its sed commands | Stopped by the $5 budget cap during turn 5, after 33 min | docs/sessions/s6.md; docs/sessions/s3.md; docs/gates.md (G3 table) |
| What the diff is | 367 files moved into 38 modules, 20 platform folders and shared/; 2,474 specifier edits in 515 files; 2 boundary-rule files added and proven inert; every other byte identical certificate K1: 367 moved, 180 edited in place, 2 added (2 inert tool configs), 0 deleted | 292 files moved into 100 modules; 1,445 specifier edits in 386 files; every other byte identical certificate K1: 292 moved, 152 edited in place, 0 added, 0 deleted | 211 files copied into src/features/, originals kept; every rewritten import corrupted certificate K1: 0 moved, 0 edited in place, 211 added (31 of them copies of files that still exist), 0 deleted | 297 moved, 562 TypeScript files copied (a src.backup/ tree), 68 edited, 12 Python scripts left behind certificate K1: 365 moved, 0 edited in place, 614 added (291 of them copies of files that still exist), 0 deleted | docs/storyboard.md (lead table); docs/gates.md (G3 table); runs/immich-ladder/certificate.txt (K1, K2) certificate line: each arm's certificate, K1 |
| tsc errors (base: 0) | 0 certificate K8: tsc exit 0 | 0 certificate K8: tsc exit 0 | 1,680 certificate K8: tsc exited 1 on head (1,680 diagnostics), 0 on base | 768 (nest build: 4,675) certificate K8: tsc exited 1 on head (768 diagnostics), 0 on base | docs/storyboard.md (lead table); docs/gates.md (G3 table); runs/immich-ladder/certificate.txt (K8) certificate line: each arm's certificate, K8 tsc |
| Unit suite (base: 105 files, 2,337 cases) | 105/105 files, 2,337/2,337 cases certificate K8: unit 105/105 files and 2,337/2,337 cases equal to base (head: 105/105 files load, 2,337 passed, 0 failed, 0 skipped) | 105/105 files, 2,337/2,337 cases certificate K8: unit 105/105 files and 2,337/2,337 cases equal to base (head: 105/105 files load, 2,337 passed, 0 failed, 0 skipped) | 2,337/2,337 cases pass, but 66 of 171 spec files never load certificate K8: unit 105/171 files and 2,337/2,337 cases equal to base (head: 105/171 files load, 2,337 passed, 0 failed, 0 skipped) | 5/105 files, 52 cases certificate K8: unit 5/105 files and 52/2,337 cases equal to base (head: 5/105 files load, 52 passed, 0 failed, 0 skipped) | docs/storyboard.md (lead table); runs/immich-ladder/certificate.txt (K6, K8) certificate line: each arm's certificate, K8 unit |
| OpenAPI spec (base: 947,932 bytes) | byte-identical certificate K8: openapi byte-identical to the base's open-api/immich-openapi-specs.json (947,932 bytes) | byte-identical certificate K8: openapi byte-identical to the base's open-api/immich-openapi-specs.json (947,932 bytes) | byte-identical: the copies are dead code certificate K8: openapi byte-identical to the base's open-api/immich-openapi-specs.json (947,932 bytes), but 1 step failed on head | not produced: sync-open-api crashes certificate K8: openapi produced nothing | docs/storyboard.md (lead table); docs/gates.md (G3 table); runs/immich-ladder/certificate.txt (K8) certificate line: each arm's certificate, K8 openapi |
| Non-specifier lines changed in moved or copied files | 0 (K2) certificate K2: 2474 specifier spans changed in 515 files; every other byte identical | 0 (K2) certificate K2: 1445 specifier spans changed in 386 files; every other byte identical | 1,104 (2.4%) certificate K2: no file paired with a base file changed, so there was nothing to compare; K1 counts the 211 added files | 0, plus 926 in modified files certificate K2: no file paired with a base file changed, so there was nothing to compare; K1 counts the 614 added files | G3 arms: docs/gates.md (G3 table, the gate's line diff); ac arms: the certificates' K2 certificate line: each arm's certificate, K2 |
| New dangling specifiers | 0 (K3a, K3b, K3c: every site resolves to its base target) certificate K3b: vitest 4.1.11: 4837 sites in 672 files resolve to map(base) | 0 (K3a, K3b, K3c) certificate K3b: vitest 4.1.11: 4837 sites in 672 files resolve to map(base) | 0: its 552 rewritten imports are syntax errors, not specifiers, so the analyzer counts none; the rest still import the originals certificate K3b: vitest 4.1.11: 4837 sites in 672 files resolve to map(base) | 2,923 certificate K3b: vitest 4.1.11: 4548 violations (2802 dangling, 131 retargeted, 1615 dangling in added files) | G3 arms: docs/gates.md (G3 table, the gate's TypeScript analyzer); ac arms: the certificates' K3a–K3c certificate line: each arm's certificate, K3b |
| Behavior changes no unit test catches | None found: K4 finds no moved file whose location reaches behavior; 12 logged stack traces now name the new path (K4 findings) certificate K4: 367 moved files expose no location; no computed path reaches a change; no old path in code, config or CI (13 findings in docs, comments or ungated coverage settings) | None found (K4; 11 logged stack traces now name the new path) certificate K4: 292 moved files expose no location; no computed path reaches a change; no old path in code, config or CI (9 findings in docs, comments or ungated coverage settings) | 0 claims survived review: the copies are dead code certificate K4: 0 path-exposing uses in moved files (and 3 in added files), 0 computed paths into changed directories, 0 old paths in code/config (0 in coverage settings) | 2 survived review: database.repository.ts and config.repository.ts moved but kept their import.meta.dirname paths (migrations, helmet.json) certificate K4: 12 path-exposing uses in moved files (and 15 in added files), 2 computed paths into changed directories, 52 old paths in code/config (0 in coverage settings) | G3 arms: docs/gates.md (Addendum: G3 review); ac arms: the certificates' K4 certificate line: each arm's certificate, K4 |
| LLM cost | $0.1998 for the plan when recorded (Nemotron 3 Ultra) and $0.0010 for the findings narration (Nemotron 3.5 Lightning); a replay costs $0 | $0 | $0.30 (0.98M input tokens, 51 calls) | $4.63 (15.3M input tokens, 200 calls) | runs/immich-ladder/run.json (cost); docs/sessions/s6.md; docs/storyboard.md (lead table); docs/gates.md (G3 table) |
| Time | 1 h 55 m wall time on a quiet machine, certificates included | executor 14 s; certificate: static checks 124 s, oracles 111 s | 169 s | 33 min | docs/sessions/s6.md; docs/storyboard.md (lead table) |
ac certify verdict | PASS (with oracles) | PASS (with oracles) | FAIL (with oracles) failing: K1, K3a, K4, K6, K8 | FAIL (with oracles) failing: K1, K3a, K3b, K3c, K4, K6, K8 | the certificate files; one row per check below |
| K0 Envelope | PASS | PASS | PASS | PASS | |
| K1 Move-set integrity | PASS | PASS | FAIL | FAIL | |
| K2 Byte-span confinement | PASS | PASS | PASS nothing to compare: K1 counts the 211 added files | PASS nothing to compare: K1 counts the 614 added files | |
| K3a Resolution identity under TypeScript | PASS | PASS | FAIL | FAIL | |
| K3b Resolution identity under the test runner | PASS | PASS | PASS | FAIL | |
| K3c Resolution identity under the runtime | PASS | PASS | PASS | FAIL | |
| K4 Location scan | PASS | PASS | FAIL | FAIL | |
| K6 Test inventory | PASS | PASS | FAIL | FAIL | |
| K7 Emit layout | PASS | not checked: K7 came after this certificate (S6) | not checked: K7 came after this certificate (S6) | not checked: K7 came after this certificate (S6) | |
| K8 Oracles on the commit | PASS | PASS | FAIL | FAIL |
Where the gate's numbers and the certificates' differ
- What the diff is: The gate counted moved and copied files with git's rename and copy detection at 50% similarity (spike/g3/measure-diff.mjs). The certifier pairs a head file with a base file only when their bytes are equal outside specifier spans, so a moved, copied or edited file with any other change is an added file to it, and only exact copies count as copies. The persistent branch's certified moves are its base files paired with their untouched copies in src.backup/ (the certificate's pathMap); the files it moved into src/features/ or edited are among the added.
- Non-specifier lines changed in moved or copied files: The gate diffed each renamed or copied file against its original line by line. K2 compares only the files the certifier pairs with a base file, and those differ at most in specifier spans by construction, so the edits inside copies and rewrites are not K2's to see: those files are K1's added files, and K1 fails.
- New dangling specifiers: The gate counted import sites its TypeScript analyzer could not resolve at the head, leaving out specifiers already unresolved at base. K3b resolves every site the way the test runner does (vitest) and counts the sites of kept or moved files that no longer reach their base target (dangling, retargeted) apart from unresolved sites in added files; K3a and K3c do the same under TypeScript and the runtime.
- Behavior changes no unit test catches: K4 fails closed: it lists every use of a moved file's location, computed path into a changed directory and old path in code or config that it can't prove safe, so its counts are hazards, not confirmed breaks. On the persistent branch it flags both files whose breaks the G3 review confirmed by hand (database.repository.ts and config.repository.ts, as added files: their certified pairs are the src.backup/ copies).
The single-shot branch's restructure is a dead copy tree: nothing imports its 211 copies, so the tests still run against the original files. (docs/gates.md (G3 table; Addendum: G3 review))
The persistent run is the reference baseline, because single-shot runs quit within 3 minutes. (docs/gates.md (Plan corrections, item 3))
The certificates
ac, the full ladder: PASS sha256:9a5b2404631c…
ac certify 02063972e8..c4be040b57 (package root server/), profile immich
trees: 424df72c34..4e457bb4e8
pathMap: 367 moves, 180 edited in place, 2917 unchanged, 2 added, 0 deleted
PASS K0 Envelope: inside the envelope: 678 TypeScript vs 3 JavaScript sources under server; no automock, nested package scope, symlink, same-stem pair or unreadable runner config around 367 moved files (0.2 s)
PASS K1 Move-set integrity: 367 moves, 180 files edited in place, 2 inert tool configs added, nothing else added or deleted (8.3 s)
finding (tool-config-added) server/.dependency-cruiser-known-violations.json: added at the package root and proven inert: in no tsconfig program, loaded by no reference, packed by no published package, named or globbed by no other file, and the tool runs nowhere; CI path filters match it, so it triggers their jobs: 'server/**' in .github/workflows/docker.yml (line 45), 'server/**' in .github/workflows/test.yml (line 46)
finding (tool-config-added) server/.dependency-cruiser.json: added at the package root and proven inert: in no tsconfig program, loaded by no reference, packed by no published package, named or globbed by no other file, and the tool runs nowhere; CI path filters match it, so it triggers their jobs: 'server/**' in .github/workflows/docker.yml (line 45), 'server/**' in .github/workflows/test.yml (line 46)
PASS K2 Byte-span confinement: 2474 specifier spans changed in 515 files; every other byte identical (3.4 s)
PASS K3a Resolution identity under TypeScript: 6647 sites in 1100 files resolve to map(base) under every program (458 files in several); 2474 rewritten specifiers keep their form (1.8 s)
PASS K3b Resolution identity under the test runner: vitest 4.1.11: 4837 sites in 672 files resolve to map(base) (5.1 s)
PASS K3c Resolution identity under the runtime: 6192 runtime sites resolve to map(base) under nest-cli/emit (3442 rewritten by the build) (6.7 s)
PASS K4 Location scan: 367 moved files expose no location; no computed path reaches a change; no old path in code, config or CI (13 findings in docs, comments or ungated coverage settings) (5.7 s)
finding (stack-text) server/src/repositories/metadata.repository.ts: moved to server/src/platform/metadata/metadata.repository.ts; 1 stack-trace reads passed along as text (line 133); their frames now name the new path
finding (stack-text) server/src/repositories/websocket.repository.ts: moved to server/src/platform/websocket/websocket.repository.ts; 1 stack-trace reads passed along as text (line 95); their frames now name the new path
finding (stack-text) server/src/services/asset-media.service.ts: moved to server/src/modules/asset/asset-media.service.ts; 1 stack-trace reads passed along as text (line 224); their frames now name the new path
… 23 more findings
PASS K6 Test inventory: vitest 4.1.11: 105 test files, 2337 tests, per-file load status and case names equal (0.0 s)
PASS K7 Emit layout: 7 emitting programs keep their outDir and rootDir (1 by TypeScript's default) (0.5 s)
finding (default-root-dir) e2e/tsconfig.json: emits into e2e/dist without a rootDir; TypeScript 6.0+ and before 6.0's default stays e2e and e2e
PASS K8 Oracles on the commit: tsc exit 0; unit 105/105 files and 2,337/2,337 cases equal to base (head: 105/105 files load, 2,337 passed, 0 failed, 0 skipped); openapi byte-identical to the base's open-api/immich-openapi-specs.json (947,932 bytes) (114.9 s)
verdict: PASS (static checks and oracles)
digest: sha256:9a5b2404631c2ac668462ad93fcbcd116637244e2b4f76e987bcc4e23e8be2b5ac, one R1-style step: PASS sha256:2e9e00c96572…
ac certify 02063972e8..ff429b0d24 (package root server/)
pathMap: 292 moves, 152 edited in place, 3020 unchanged, 0 added, 0 deleted
PASS K0 Envelope: inside the envelope: 678 TypeScript vs 3 JavaScript sources under server; no automock, nested package scope, symlink, same-stem pair or unreadable runner config around 292 moved files (8.5 s)
PASS K1 Move-set integrity: 292 moves, 152 files edited in place, nothing added or deleted (1.5 s)
PASS K2 Byte-span confinement: 1445 specifier spans changed in 386 files; every other byte identical (2.9 s)
PASS K3a Resolution identity under TypeScript: 6647 sites in 1100 files resolve to map(base) under every program (458 files in several); 1445 rewritten specifiers keep their form (1.5 s)
PASS K3b Resolution identity under the test runner: vitest 4.1.11: 4837 sites in 672 files resolve to map(base) (5.8 s)
PASS K3c Resolution identity under the runtime: 6192 runtime sites resolve to map(base) under nest-cli/emit (3442 rewritten by the build) (7.2 s)
PASS K4 Location scan: 292 moved files expose no location; no computed path reaches a change; no old path in code, config or CI (9 findings in docs, comments or ungated coverage settings) (5.5 s)
finding (stack-text) server/src/repositories/metadata.repository.ts: moved to server/src/modules/metadata/metadata.repository.ts; 1 stack-trace reads passed along as text (line 133); their frames now name the new path
finding (stack-text) server/src/repositories/websocket.repository.ts: moved to server/src/modules/websocket/websocket.repository.ts; 1 stack-trace reads passed along as text (line 95); their frames now name the new path
finding (stack-text) server/src/services/asset-media.service.ts: moved to server/src/modules/asset-media/asset-media.service.ts; 1 stack-trace reads passed along as text (line 224); their frames now name the new path
… 18 more findings
PASS K6 Test inventory: vitest 4.1.11: 105 test files, 2337 tests, per-file load status and case names equal (91.2 s)
PASS K8 Oracles on the commit: tsc exit 0; unit 105/105 files and 2,337/2,337 cases equal to base (head: 105/105 files load, 2,337 passed, 0 failed, 0 skipped); openapi byte-identical to the base's open-api/immich-openapi-specs.json (947,932 bytes) (110.7 s)
verdict: PASS (static checks and oracles)
digest: sha256:2e9e00c96572e7347cf00084cacd7e371c3004c261092888575bb32d99138820
Ac-Certificate: pass (full) K0=pass K1=pass K2=pass K3=pass K4=pass K6=pass K8=pass
Ac-Certificate-Base: 02063972e82b1bfd17b6fc2e3b3ff39936229ea5
Ac-Certificate-Digest: sha256:2e9e00c96572e7347cf00084cacd7e371c3004c261092888575bb32d99138820opencode + Nemotron 3 Super, single-shot: FAIL sha256:8cbe6c92987f…
ac certify 02063972e8..03e76f3faa (package root server/)
pathMap: 0 moves, 0 edited in place, 3464 unchanged, 211 added, 0 deleted
PASS K0 Envelope: inside the envelope: 889 TypeScript vs 3 JavaScript sources under server; no automock, nested package scope, symlink, same-stem pair or unreadable runner config around 0 moved files (9.1 s)
FAIL K1 Move-set integrity: 211 violations (211 added, 0 deleted, 31 copies) (1.2 s)
server/src/features/activity/activity.controller.spec.ts: added: no file in base has its content (modulo specifiers)
server/src/features/activity/activity.controller.ts: added: no file in base has its content (modulo specifiers)
server/src/features/activity/activity.dto.ts: added: no file in base has its content (modulo specifiers)
server/src/features/activity/activity.repository.ts: added: a copy of server/src/repositories/activity.repository.ts, which still exists
server/src/features/activity/activity.service.spec.ts: added: no file in base has its content (modulo specifiers)
server/src/features/activity/activity.service.ts: added: no file in base has its content (modulo specifiers)
server/src/features/album/album.controller.spec.ts: added: no file in base has its content (modulo specifiers)
server/src/features/album/album.controller.ts: added: no file in base has its content (modulo specifiers)
… 203 more
PASS K2 Byte-span confinement: 0 specifier spans changed in 0 files; every other byte identical (0.0 s)
FAIL K3a Resolution identity under TypeScript: 211 violations (211 added source files) (1.3 s)
server/src/features/activity/activity.controller.spec.ts: added: its 3 reference sites have no counterpart in base
server/src/features/activity/activity.controller.ts: added: its 7 reference sites have no counterpart in base
server/src/features/activity/activity.dto.ts: added: its 4 reference sites have no counterpart in base
server/src/features/activity/activity.repository.ts: added: its 10 reference sites have no counterpart in base
server/src/features/activity/activity.service.spec.ts: added: its 6 reference sites have no counterpart in base
server/src/features/activity/activity.service.ts: added: its 3 reference sites have no counterpart in base
server/src/features/album/album.controller.spec.ts: added: its 3 reference sites have no counterpart in base
server/src/features/album/album.controller.ts: added: its 6 reference sites have no counterpart in base
… 203 more
PASS K3b Resolution identity under the test runner: vitest 4.1.11: 4837 sites in 672 files resolve to map(base) (6.6 s)
PASS K3c Resolution identity under the runtime: 6192 runtime sites resolve to map(base) under nest-cli/emit (3442 rewritten by the build) (7.6 s)
finding (added-file-unresolved) server/src/features/plugin/plugin.dto.ts: nest-cli/emit: import '@immich/plugin-sdk' doesn't resolve (ERR_MODULE_NOT_FOUND) in a file with no base counterpart
finding (added-file-unresolved) server/src/features/workflow/workflow.controller.spec.ts: nest-cli/emit: import '@immich/plugin-sdk' doesn't resolve (ERR_MODULE_NOT_FOUND) in a file with no base counterpart
finding (added-file-unresolved) server/src/features/workflow/workflow.service.ts: nest-cli/emit: import '@immich/plugin-sdk' doesn't resolve (ERR_MODULE_NOT_FOUND) in a file with no base counterpart
FAIL K4 Location scan: 0 path-exposing uses in moved files (and 3 in added files), 0 computed paths into changed directories, 0 old paths in code/config (0 in coverage settings) (0.9 s)
server/src/features/library/library.service.spec.ts: added with no base counterpart; line 888: process.cwd()
server/src/features/library/library.service.spec.ts: added with no base counterpart; line 1284: process.cwd()
server/src/features/library/library.service.spec.ts: added with no base counterpart; line 1298: process.cwd()
finding (stack-text) server/src/features/asset-media/asset-media.service.ts: added with no base counterpart; 1 stack-trace reads passed along as text (line 224); their frames now name the new path
finding (stack-text) server/src/features/auth/auth.service.ts: added with no base counterpart; 1 stack-trace reads passed along as text (line 403); their frames now name the new path
finding (stack-text) server/src/features/duplicate/duplicate.service.ts: added with no base counterpart; 1 stack-trace reads passed along as text (line 104); their frames now name the new path
… 2 more findings
FAIL K6 Test inventory: vitest 4.1.11: 66 violations (66 of 171 test files fail to load (base: 0), 66 new test files) (94.6 s)
server/src/features/activity/activity.controller.spec.ts: new in the vitest test list (added in head; fails to load: x Unexpected token `[`. Expected a string literal ,-[/tmp/ac-s4-certify/g3-immich-opencode-super.full/worktree-head/server/src/features/activity/activity.controller.spec.ts:2:1] 1 | import request fro)
server/src/features/activity/activity.service.spec.ts: new in the vitest test list (added in head; fails to load: x Unexpected token `[`. Expected a string literal ,-[/tmp/ac-s4-certify/g3-immich-opencode-super.full/worktree-head/server/src/features/activity/activity.service.spec.ts:2:1] 1 | import { BadRequestEx)
server/src/features/album/album.controller.spec.ts: new in the vitest test list (added in head; fails to load: x Unexpected token `[`. Expected a string literal ,-[/tmp/ac-s4-certify/g3-immich-opencode-super.full/worktree-head/server/src/features/album/album.controller.spec.ts:2:1] 1 | import request from 'sup)
server/src/features/album/album.service.spec.ts: new in the vitest test list (added in head; fails to load: x Unexpected token `[`. Expected a string literal ,-[/tmp/ac-s4-certify/g3-immich-opencode-super.full/worktree-head/server/src/features/album/album.service.spec.ts:2:1] 1 | import { BadRequestExceptio)
server/src/features/app/app.controller.spec.ts: new in the vitest test list (added in head; fails to load: x Unexpected token `[`. Expected a string literal ,-[/tmp/ac-s4-certify/g3-immich-opencode-super.full/worktree-head/server/src/features/app/app.controller.spec.ts:2:1] 1 | import request from 'superte)
server/src/features/asset/asset.controller.spec.ts: new in the vitest test list (added in head; fails to load: x Unexpected token `[`. Expected a string literal ,-[/tmp/ac-s4-certify/g3-immich-opencode-super.full/worktree-head/server/src/features/asset/asset.controller.spec.ts:2:1] 1 | import request from 'sup)
server/src/features/asset/asset.service.spec.ts: new in the vitest test list (added in head; fails to load: x Unexpected token `[`. Expected a string literal ,-[/tmp/ac-s4-certify/g3-immich-opencode-super.full/worktree-head/server/src/features/asset/asset.service.spec.ts:3:1] 1 | import { BadRequestExceptio)
server/src/features/asset-media/asset-media.controller.spec.ts: new in the vitest test list (added in head; fails to load: x Unexpected token `[`. Expected a string literal ,-[/tmp/ac-s4-certify/g3-immich-opencode-super.full/worktree-head/server/src/features/asset-media/asset-media.controller.spec.ts:2:1] 1 | import reque)
… 58 more
FAIL K8 Oracles on the commit: tsc exited 1 on head (1,680 diagnostics), 0 on base; unit 105/171 files and 2,337/2,337 cases equal to base (head: 105/171 files load, 2,337 passed, 0 failed, 0 skipped); openapi byte-identical to the base's open-api/immich-openapi-specs.json (947,932 bytes), but 1 step failed on head (118.9 s)
tsc: `node_modules/.bin/tsc --noEmit --incremental false --pretty false` exited 1 on head (1,680 diagnostics), exit 0 on base (log /tmp/ac-s4-certify/g3-immich-opencode-super.full/oracles/head/tsc/step-1.log)
server/src/features/activity/activity.controller.spec.ts: tsc: TS1005 ',' expected.
server/src/features/activity/activity.controller.spec.ts: tsc: TS1002 Unterminated string literal.
server/src/features/activity/activity.controller.spec.ts: tsc: TS1005 ',' expected.
server/src/features/activity/activity.controller.spec.ts: tsc: TS1005 ',' expected.
server/src/features/activity/activity.controller.spec.ts: tsc: TS1002 Unterminated string literal.
server/src/features/activity/activity.controller.spec.ts: tsc: TS1005 ',' expected.
server/src/features/activity/activity.controller.ts: tsc: TS1005 ',' expected.
… 72 more
verdict: FAIL (static checks and oracles)
digest: sha256:8cbe6c92987fbc9132d2af720c36a32a3e5f5598021c85169e7d39de6b6d2beb
Ac-Certificate: fail (full) K0=pass K1=fail K2=pass K3=fail K4=fail K6=fail K8=fail
Ac-Certificate-Base: 02063972e82b1bfd17b6fc2e3b3ff39936229ea5
Ac-Certificate-Digest: sha256:8cbe6c92987fbc9132d2af720c36a32a3e5f5598021c85169e7d39de6b6d2bebopencode + Nemotron 3 Super, persistent: FAIL sha256:90d2d44bbd64…
ac certify 02063972e8..1da2348b7c (package root server/)
pathMap: 365 moves, 0 edited in place, 3099 unchanged, 614 added, 0 deleted
PASS K0 Envelope: inside the envelope: 1242 TypeScript vs 3 JavaScript sources under server; no automock, nested package scope, symlink, same-stem pair or unreadable runner config around 365 moved files (23.1 s)
FAIL K1 Move-set integrity: 979 violations (614 added, 0 deleted, 291 copies) (1.2 s)
server/fix_app_files.py: added: no file in base has its content (modulo specifiers)
server/fix_features_only.py: added: no file in base has its content (modulo specifiers)
server/fix_indexes.py: added: no file in base has its content (modulo specifiers)
server/fix_quotes.py: added: no file in base has its content (modulo specifiers)
server/fix_quotes2.py: added: no file in base has its content (modulo specifiers)
server/fix_restructure.py: added: no file in base has its content (modulo specifiers)
server/rebuild_indexes.py: added: no file in base has its content (modulo specifiers)
server/regenerate_indexes.py: added: no file in base has its content (modulo specifiers)
… 971 more
finding (ambiguous-match) 30 groups of identical files were paired by where their directories' other files went, then by name and path similarity
PASS K2 Byte-span confinement: 0 specifier spans changed in 0 files; every other byte identical (4.2 s)
FAIL K3a Resolution identity under TypeScript: 3097 violations (2168 resolution mismatches, 365 program or format changes, 564 added source files) (2.6 s)
server/src/app.common.ts: line 9: import 'src/maintenance/maintenance-worker.service.js': expected file server/src.backup/maintenance/maintenance-worker.service.ts (typescript), got file server/src/maintenance/maintenance-worker.service.ts (typescript) under server/tsconfig.build.json, server/tsconfig.json
server/src/app.common.ts: line 10: import 'src/middleware/websocket.adapter.js': expected file server/src.backup/middleware/websocket.adapter.ts (typescript), got file server/src/middleware/websocket.adapter.ts (typescript) under server/tsconfig.build.json, server/tsconfig.json
server/src/app.common.ts: line 11: import 'src/repositories/config.repository.js': expected file server/src.backup/repositories/config.repository.ts (typescript), got unresolved under server/tsconfig.build.json, server/tsconfig.json
server/src/app.common.ts: line 12: import 'src/repositories/logging.repository.js': expected file server/src.backup/repositories/logging.repository.ts (typescript), got unresolved under server/tsconfig.build.json, server/tsconfig.json
server/src/app.common.ts: line 13: import 'src/repositories/telemetry.repository.js': expected file server/src.backup/repositories/telemetry.repository.ts (typescript), got unresolved under server/tsconfig.build.json, server/tsconfig.json
server/src/app.common.ts: line 14: import 'src/services/api.service.js': expected file server/src.backup/services/api.service.ts (typescript), got unresolved under server/tsconfig.build.json, server/tsconfig.json
server/src/app.common.ts: line 15: import 'src/utils/misc.js': expected file server/src.backup/utils/misc.ts (typescript), got file server/src/utils/misc.ts (typescript) under server/tsconfig.build.json, server/tsconfig.json
server/src/app.module.ts: line 11: import 'src/controllers/index.js': expected file server/src.backup/controllers/index.ts (typescript), got file server/src/controllers/index.ts (typescript) under server/tsconfig.build.json, server/tsconfig.json
… 3089 more
FAIL K3b Resolution identity under the test runner: vitest 4.1.11: 4548 violations (2802 dangling, 131 retargeted, 1615 dangling in added files) (7.5 s)
server/src/app.common.ts: site 8 'src/maintenance/maintenance-worker.service.js' (import): base server/src.backup/maintenance/maintenance-worker.service.ts, head server/src/maintenance/maintenance-worker.service.ts
server/src/app.common.ts: site 9 'src/middleware/websocket.adapter.js' (import): base server/src.backup/middleware/websocket.adapter.ts, head server/src/middleware/websocket.adapter.ts
server/src/app.common.ts: site 10 'src/repositories/config.repository.js' (import): base server/src.backup/repositories/config.repository.ts, head unresolved
server/src/app.common.ts: site 11 'src/repositories/logging.repository.js' (import): base server/src.backup/repositories/logging.repository.ts, head unresolved
server/src/app.common.ts: site 12 'src/repositories/telemetry.repository.js' (import): base server/src.backup/repositories/telemetry.repository.ts, head unresolved
server/src/app.common.ts: site 13 'src/services/api.service.js' (import): base server/src.backup/services/api.service.ts, head unresolved
server/src/app.common.ts: site 14 'src/utils/misc.js' (import): base server/src.backup/utils/misc.ts, head server/src/utils/misc.ts
server/src/app.module.ts: site 10 'src/controllers/index.js' (import): base server/src.backup/controllers/index.ts, head server/src/controllers/index.ts
… 4540 more
FAIL K3c Resolution identity under the runtime: 2287 violations under nest-cli/emit (10.0 s)
server/src/app.common.ts: nest-cli/emit: import 'src/maintenance/maintenance-worker.service.js' (emitted as './maintenance/maintenance-worker.service.js') resolves to server/src/maintenance/maintenance-worker.service.ts, expected server/src.backup/maintenance/maintenance-worker.service.ts; base server/src/app.common.ts 'src/maintenance/maintenance-worker.service.js'
server/src/app.common.ts: nest-cli/emit: import 'src/middleware/websocket.adapter.js' (emitted as './middleware/websocket.adapter.js') resolves to server/src/middleware/websocket.adapter.ts, expected server/src.backup/middleware/websocket.adapter.ts; base server/src/app.common.ts 'src/middleware/websocket.adapter.js'
server/src/app.common.ts: nest-cli/emit: import 'src/repositories/config.repository.js' resolves to unresolved (ERR_MODULE_NOT_FOUND), expected server/src.backup/repositories/config.repository.ts; base server/src/app.common.ts 'src/repositories/config.repository.js'
server/src/app.common.ts: nest-cli/emit: import 'src/repositories/logging.repository.js' resolves to unresolved (ERR_MODULE_NOT_FOUND), expected server/src.backup/repositories/logging.repository.ts; base server/src/app.common.ts 'src/repositories/logging.repository.js'
server/src/app.common.ts: nest-cli/emit: import 'src/repositories/telemetry.repository.js' resolves to unresolved (ERR_MODULE_NOT_FOUND), expected server/src.backup/repositories/telemetry.repository.ts; base server/src/app.common.ts 'src/repositories/telemetry.repository.js'
server/src/app.common.ts: nest-cli/emit: import 'src/services/api.service.js' resolves to unresolved (ERR_MODULE_NOT_FOUND), expected server/src.backup/services/api.service.ts; base server/src/app.common.ts 'src/services/api.service.js'
server/src/app.common.ts: nest-cli/emit: import 'src/utils/misc.js' (emitted as './utils/misc.js') resolves to server/src/utils/misc.ts, expected server/src.backup/utils/misc.ts; base server/src/app.common.ts 'src/utils/misc.js'
server/src/app.module.ts: nest-cli/emit: import 'src/controllers/index.js' (emitted as './controllers/index.js') resolves to server/src/controllers/index.ts, expected server/src.backup/controllers/index.ts; base server/src/app.module.ts 'src/controllers/index.js'
… 293 more
finding (added-file-unresolved) server/src.backup/app.common.ts: nest-cli/emit: import 'src/repositories/config.repository.js' doesn't resolve (ERR_MODULE_NOT_FOUND) in a file with no base counterpart
finding (added-file-unresolved) server/src.backup/app.common.ts: nest-cli/emit: import 'src/repositories/logging.repository.js' doesn't resolve (ERR_MODULE_NOT_FOUND) in a file with no base counterpart
finding (added-file-unresolved) server/src.backup/app.common.ts: nest-cli/emit: import 'src/repositories/telemetry.repository.js' doesn't resolve (ERR_MODULE_NOT_FOUND) in a file with no base counterpart
… 18 more findings
FAIL K4 Location scan: 12 path-exposing uses in moved files (and 15 in added files), 2 computed paths into changed directories, 52 old paths in code/config (0 in coverage settings) (7.5 s)
server/src/main.ts: moved to server/src.backup/main.ts; line 101: import.meta.filename: dirname(import.meta.filename) pointed at server/src (exists in base), now at server/src.backup (exists in head)
server/src/main.ts: moved to server/src.backup/main.ts; line 116: new Worker(workerFile) (worker_threads)
server/src/repositories/database.repository.ts: moved to server/src.backup/repositories/database.repository.ts; line 510: import(filePath) with a computed specifier (resolved relative to this file)
server/src/repositories/database.repository.ts: moved to server/src.backup/repositories/database.repository.ts; line 511: import.meta.dirname: join(import.meta.dirname, '..', 'schema/migrations') pointed at server/src/schema/migrations (exists in base), now at server/src.backup/schema/migrations (exists in head)
server/src/repositories/storage.repository.spec.ts: moved to server/src.backup/repositories/storage.repository.spec.ts; line 38: process.cwd()
server/src/services/cli.service.ts: moved to server/src.backup/services/cli.service.ts; line 25: import.meta.dirname: join(import.meta.dirname, '../schema/migrations') pointed at server/src/schema/migrations (exists in base), now at server/src.backup/schema/migrations (exists in head)
server/src/services/library.service.spec.ts: moved to server/src.backup/services/library.service.spec.ts; line 888: process.cwd()
server/src/services/library.service.spec.ts: moved to server/src.backup/services/library.service.spec.ts; line 1284: process.cwd()
… 73 more
finding (stack-text) server/src/main.ts: moved to server/src.backup/main.ts; 1 stack-trace reads passed along as text (line 129); their frames now name the new path
finding (stack-text) server/src/repositories/metadata.repository.ts: moved to server/src.backup/repositories/metadata.repository.ts; 1 stack-trace reads passed along as text (line 133); their frames now name the new path
finding (stack-text) server/src/repositories/websocket.repository.ts: moved to server/src.backup/repositories/websocket.repository.ts; 1 stack-trace reads passed along as text (line 95); their frames now name the new path
… 54 more findings
FAIL K6 Test inventory: vitest 4.1.11: 189 violations (100 of 105 test files fail to load (base: 0), 4 files that no longer load, 96 dropped test files, 89 new test files, 2285 lost tests) (53.7 s)
server/src/controllers/activity.controller.spec.ts: no longer in the vitest test list (now at server/src.backup/controllers/activity.controller.spec.ts)
server/src/controllers/album.controller.spec.ts: no longer in the vitest test list (now at server/src.backup/controllers/album.controller.spec.ts)
server/src/controllers/api-key.controller.spec.ts: no longer in the vitest test list (now at server/src.backup/controllers/api-key.controller.spec.ts)
server/src/controllers/app.controller.spec.ts: no longer in the vitest test list (now at server/src.backup/controllers/app.controller.spec.ts)
server/src/controllers/asset-media.controller.spec.ts: no longer in the vitest test list (now at server/src.backup/controllers/asset-media.controller.spec.ts)
server/src/controllers/asset.controller.spec.ts: no longer in the vitest test list (now at server/src.backup/controllers/asset.controller.spec.ts)
server/src/controllers/auth.controller.spec.ts: no longer in the vitest test list (now at server/src.backup/controllers/auth.controller.spec.ts)
server/src/controllers/config.controller.spec.ts: no longer in the vitest test list (now at server/src.backup/controllers/config.controller.spec.ts)
… 181 more
FAIL K8 Oracles on the commit: tsc exited 1 on head (768 diagnostics), 0 on base; unit 5/105 files and 52/2,337 cases equal to base (head: 5/105 files load, 52 passed, 0 failed, 0 skipped); openapi produced nothing (39.3 s)
tsc: `node_modules/.bin/tsc --noEmit --incremental false --pretty false` exited 1 on head (768 diagnostics), exit 0 on base (log /tmp/ac-s4-certify/g3-immich-opencode-super-persistent.full/oracles/head/tsc/step-1.log)
server/src/bin/sync-sql.ts: tsc: TS1002 Unterminated string literal.
server/src/bin/sync-sql.ts: tsc: TS1002 Unterminated string literal.
server/src/bin/sync-sql.ts: tsc: TS1002 Unterminated string literal.
server/src/bin/sync-sql.ts: tsc: TS1002 Unterminated string literal.
server/src/bin/sync-sql.ts: tsc: TS1002 Unterminated string literal.
server/src/bin/sync-sql.ts: tsc: TS1002 Unterminated string literal.
server/src/bin/sync-sql.ts: tsc: TS1002 Unterminated string literal.
… 206 more
verdict: FAIL (static checks and oracles)
digest: sha256:90d2d44bbd647b5f1b99d61590fbaa9f993572e244c7a8e91fd60c1b0161651e
Ac-Certificate: fail (full) K0=pass K1=fail K2=pass K3=fail K4=fail K6=fail K8=fail
Ac-Certificate-Base: 02063972e82b1bfd17b6fc2e3b3ff39936229ea5
Ac-Certificate-Digest: sha256:90d2d44bbd647b5f1b99d61590fbaa9f993572e244c7a8e91fd60c1b0161651eRendered by ac report from the run dir; the certificate files sit next to this page.