diff --git a/SPECGAPS.md b/SPECGAPS.md
index df497ee..4cfe8ba 100644
--- a/SPECGAPS.md
+++ b/SPECGAPS.md
@@ -117,7 +117,7 @@ All reconciled to follow code. Specs must be self-consistent and match code.
| D1-1 | ~~UniqueMediaTranslation invariant~~ | media.allium:108 | **Resolved:** test added (re-upsert updates not duplicates; direct duplicate insert rejected). Test exposed a real bug — `Media.Translation` declared the migration's index name but ecto_sqlite3 derives the violated-constraint name from columns, so violations crashed instead of returning a changeset error; fixed `unique_constraint` name to `:media_translations_translation_for_language_index` |
| D1-2 | ~~UniqueTranslationPerLanguage invariant~~ | translation.allium:94 | **Resolved:** test added (re-upsert updates not duplicates; direct duplicate insert rejected). Same bug as D1-1 — `Posts.Translation` declared the migration's index name but ecto_sqlite3 derives the violated-constraint name from columns, so duplicates crashed instead of returning a changeset error; fixed `unique_constraint` name to `:post_translations_translation_for_language_index` |
| D1-3 | ~~BundledDefaultTemplatesExistOutsideProjectData~~ | template.allium:65 | **Resolved:** added 4 tests in `template_lookup_priority_test.exs` — with no Template rows for the project, `load_template_source/3` resolves bundled single-post/post-list/not-found defaults (and still resolves when the project has no `templates/` directory at all) |
-| D1-4 | UserTemplateDirectoryOverridesBundledDefaults | template.allium:75 | Write test: project template overrides bundled same-slug |
+| D1-4 | ~~UserTemplateDirectoryOverridesBundledDefaults~~ | template.allium:75 | **Resolved:** added 2 tests in `template_lookup_priority_test.exs` — a published project Template row with the bundled default slug (`single-post`) wins over the bundled default both when resolving `:post` with no explicit slug and when the slug is requested explicitly |
| D1-5 | LiquidTagSubset (5 tags only) | template.allium:179 | Write test: unsupported tag raises error |
| D1-6 | LiquidFilterSubset (4 standard + 2 custom) | template.allium:191 | Write test: unsupported filter raises error |
| D1-7 | LiquidOperatorSubset | template.allium:210 | Write test: unsupported operator raises error |
diff --git a/test/bds/template_lookup_priority_test.exs b/test/bds/template_lookup_priority_test.exs
index c110b2a..90bf1b3 100644
--- a/test/bds/template_lookup_priority_test.exs
+++ b/test/bds/template_lookup_priority_test.exs
@@ -178,6 +178,40 @@ defmodule BDS.TemplateLookupPriorityTest do
end
end
+ describe "UserTemplateDirectoryOverridesBundledDefaults" do
+ test "published project template with default slug overrides bundled single-post", %{
+ project: project
+ } do
+ _template =
+ create_published_template(
+ project.id,
+ "single-post",
+ "{{ page.title }}"
+ )
+
+ {:ok, source} = TemplateSelection.load_template_source(project.id, :post, nil)
+
+ assert source =~ ~s(data-template="user-single-post")
+ refute source =~ ~s(data-template="single-post")
+ end
+
+ test "published project template overrides bundled default when slug requested explicitly", %{
+ project: project
+ } do
+ _template =
+ create_published_template(
+ project.id,
+ "single-post",
+ "{{ page.title }}"
+ )
+
+ {:ok, source} = TemplateSelection.load_template_source(project.id, :post, "single-post")
+
+ assert source =~ ~s(data-template="user-single-post")
+ refute source =~ ~s(data-template="single-post")
+ end
+ end
+
describe "end-to-end template lookup with rendering" do
test "post renders with tag-specific template when no post template set", %{
project: project