diff --git a/packages/pdf/src/templates/shared/sections.test.ts b/packages/pdf/src/templates/shared/sections.test.ts
new file mode 100644
index 000000000..2eb3b769c
--- /dev/null
+++ b/packages/pdf/src/templates/shared/sections.test.ts
@@ -0,0 +1,15 @@
+import { readFileSync } from "node:fs";
+import { fileURLToPath } from "node:url";
+import { describe, expect, it } from "vitest";
+
+const source = readFileSync(fileURLToPath(new URL("./sections.tsx", import.meta.url)), "utf8");
+
+describe("ExperienceSection", () => {
+ it("does not hide the item position header when role progression is present", () => {
+ expect(source).not.toContain("item.roles.length === 0 && (hasPosition || hasSplitRowText(headerPeriod))");
+ });
+
+ it("does not repeat the summary period after rendering it in a role-progression header", () => {
+ expect(source).not.toContain("item.roles.length > 0 && {item.period}");
+ });
+});
diff --git a/packages/pdf/src/templates/shared/sections.tsx b/packages/pdf/src/templates/shared/sections.tsx
index bb03f832e..0b23f906e 100644
--- a/packages/pdf/src/templates/shared/sections.tsx
+++ b/packages/pdf/src/templates/shared/sections.tsx
@@ -415,7 +415,7 @@ const ExperienceSection = ({ sectionId = "experience", sectionData }: ItemSectio
{hasSplitRowText(headerLocation) && {headerLocation}}
- {item.roles.length === 0 && (hasPosition || hasSplitRowText(headerPeriod)) && (
+ {(hasPosition || hasSplitRowText(headerPeriod)) && (
{hasPosition && {item.position}}
{hasSplitRowText(headerPeriod) && {headerPeriod}}
@@ -428,8 +428,6 @@ const ExperienceSection = ({ sectionId = "experience", sectionData }: ItemSectio
{inlineItemHeader ? renderInlineHeader() : renderSplitHeader()}
- {item.roles.length > 0 && {item.period}}
-
{item.roles.map((role) => (