Draft
Conversation
Remove the static file path payload from SiteRoute and let the app look up the serving path from the model.
Delegate note and static-file SiteRoute construction to the model resolver helper so conversion logic has a single owner.
Give route, pandoc, and model packages their own test suites and leave app tests for app-owned behavior.
Owner
Author
Structural Review Follow-upHickey findings fixed in this PR
Lowy findings fixed in this PR
Code-police follow-up
|
Owner
Author
EvidenceNo screenshot evidence was captured for this PR because the change is an internal package-boundary refactor with no visible UI surface. Rendering paths were still exercised by the test suite:
|
Owner
Author
|
| Step | Status | Duration | Verification |
|---|---|---|---|
| sync | ✓ | 0s | git fetch ok; forge=github; noGit=false |
| research | ✓ | 3m 46s | Fetched issue #600 and mapped package/build blockers: cabal.project, nix projectRoot, SiteRoute.Type hashtag dependency, model SiteRoute.Class imports, and Stork URL rendering injection. |
| branch | ✓ | 0s | Created feature branch split-multi-package-layout from origin/master. |
| implement | ✓ | 4m 20s | Moved app package under packages/emanote, extracted route/source/pandoc/model packages, patched boundary imports, injected Stork URL rendering, and updated Cabal/Nix package discovery. |
| check | ✓ | 2m 27s | Configured check ran as nix develop -c cabal build all because cabal is not on the ambient PATH; all packages and executable built successfully. |
| docs | ✓ | 53s | Updated docs and changelog for packages/emanote default-layer paths and the new multi-package layout. |
| fmt | ✓ | 27s | just fmt completed cleanly after cabal-fmt normalized the new package files. |
| commit | ✓ | 26s | Created and pushed commit a780e5e (refactor: split emanote into packages) to origin/split-multi-package-layout. |
| hickey+lowy | ✓ | 27m 11s | Applied all Hickey/Lowy findings in follow-up commits: simplified static routes, consolidated route construction, moved tests to owning packages, moved app runtime state out of emanote-model, and moved Stork engine ownership to the app package; nix develop -c cabal build all passed after the final fix. |
| police | ✓ | 2m 6s | Code-police pass found one small elegance issue in Emanote.Site.Model readers being unnecessarily restricted to Model; fixed in b4810d1 and verified with nix develop -c cabal build all plus pre-commit. |
| test | ✓ | 2m 36s | nix develop -c cabal test all passed all package unit tests; just e2e-live passed 22/22 scenarios; just e2e-static passed 20 scenarios with 2 morph scenarios skipped by mode; just e2e-morph passed 22/22 scenarios. |
| create-pr | ✓ | 42s | Created draft PR #679 (#679) and posted structural review follow-up comment #679 (comment). |
| ci | ✓ | 4m 1s | vira ci completed successfully, built the flake outputs for x86_64-linux and aarch64-darwin, and created GitHub signoffs vira/aarch64-darwin and vira/x86_64-linux for b4810d1. |
| evidence | ✓ | 11s | Posted PR evidence comment #679 (comment) noting that no screenshot was needed for this internal package-boundary refactor and listing unit, e2e, and vira CI coverage. |
| done | ✓ | 16s | All workflow steps succeeded; final results table is being generated from .do-results.json and posted to PR #679. |
| Total | 51m 43s |
Slowest step: hickey+lowy (27m 11s)
Optimization suggestions
- The structural review pass dominated the run. For future package-boundary refactors, split the first pass into a smaller package move PR and then a runtime-boundary cleanup PR so Hickey/Lowy has less diff to evaluate at once.
- CI was only 4m 1s, so reruns after comment-only or metadata-only follow-ups should use
/do --from ci-onlyrather than replaying the full workflow. - The local test step was short relative to the review work. Keep the package unit tests colocated with their owning packages so future reviewers can validate boundary moves without re-reading the whole app test suite.
Workflow completed at 2026-04-27T01:17:39Z.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Emanote is now split into focused internal Cabal packages for routes, sources, Pandoc support, model logic, and the app layer. This closes #600 by making the module boundaries enforceable at build time instead of relying on naming convention inside one large package.
The app package keeps the runtime concerns: Ema route encoders, concrete Pandoc renderers, Heist template state, Tailwind flags, process IDs, and the Stork engine/cache now live above the model package. The lower packages remain reusable building blocks, with tests moved to the packages that own the behavior they exercise.
The split is wired through Cabal and Nix with explicit
cabal.projectpackage entries and the flake Haskell root widened to includepackages/. I verified the branch withnix develop -c cabal build all,nix develop -c cabal test all, and all three configured e2e modes:just e2e-live,just e2e-static, andjust e2e-morph.Closes #600.
Try it locally
Generated by
/doon Codex (modelgpt-5).