From e6089a2b63fbf5fb73be3a17e65dcf8be25232c8 Mon Sep 17 00:00:00 2001 From: Asif Sayyed Date: Mon, 11 May 2026 12:47:41 +0530 Subject: [PATCH 1/8] #25 fix accessibility issue --- index.html | 1 + style.css | 17 ++++++++++++----- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/index.html b/index.html index c3e8c99..32519c2 100644 --- a/index.html +++ b/index.html @@ -108,6 +108,7 @@

The Ship of Theseus

+

Insights

How much has changed? diff --git a/style.css b/style.css index a2999ea..87fb96b 100644 --- a/style.css +++ b/style.css @@ -10,6 +10,18 @@ --font-mono: 'JetBrains Mono', monospace; } +.visually-hidden { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + white-space: nowrap; + border: 0; +} + * { margin: 0; padding: 0; @@ -69,7 +81,6 @@ body { text-transform: uppercase; letter-spacing: 0.15em; color: var(--text-secondary); - opacity: 0.6; transition: all 0.3s ease; cursor: default; } @@ -160,7 +171,6 @@ body { font-size: 0.9rem; cursor: pointer; transition: all 0.3s ease; - opacity: 0.6; } .mode-btn, @@ -192,7 +202,6 @@ body { font-style: italic; font-size: 0.9rem; color: var(--text-secondary); - opacity: 0.7; margin-top: 0.5rem; } @@ -671,7 +680,6 @@ svg#main-chart { .footer-text { font-size: 0.8rem; color: var(--text-secondary); - opacity: 0.5; } /* Personal Narrative Section */ @@ -732,7 +740,6 @@ svg#main-chart { font-style: normal; font-size: 0.85rem; color: var(--text-secondary); - opacity: 0.7; display: block; margin-top: 0.5rem; letter-spacing: 0.05em; From feacbf016961922784bc61cb3a48efdafcd036cf Mon Sep 17 00:00:00 2001 From: Asif Sayyed Date: Mon, 11 May 2026 13:08:48 +0530 Subject: [PATCH 2/8] #25 removed some cards --- app.js | 122 +++++++++++++++-------------------------------------- index.html | 24 ----------- style.css | 3 +- 3 files changed, 35 insertions(+), 114 deletions(-) diff --git a/app.js b/app.js index 3c58519..5f1dd23 100644 --- a/app.js +++ b/app.js @@ -211,8 +211,8 @@ class TheseusVisualizer { .attr("x1", "0%").attr("y1", "0%") .attr("x2", "0%").attr("y2", "100%"); - grad.append("stop").attr("offset", "0%").attr("stop-color", color).attr("stop-opacity", 0.6); - grad.append("stop").attr("offset", "100%").attr("stop-color", color).attr("stop-opacity", 0.05); + grad.append("stop").attr("offset", "0%").attr("stop-color", color).attr("stop-opacity", 0.9); + grad.append("stop").attr("offset", "100%").attr("stop-color", color).attr("stop-opacity", 0.4); }); // Specialized gradients for Identity mode if needed @@ -223,8 +223,8 @@ class TheseusVisualizer { .attr("id", `grad-id-${id}`) .attr("x1", "0%").attr("y1", "0%") .attr("x2", "0%").attr("y2", "100%"); - grad.append("stop").attr("offset", "0%").attr("stop-color", color).attr("stop-opacity", 0.6); - grad.append("stop").attr("offset", "100%").attr("stop-color", color).attr("stop-opacity", 0.05); + grad.append("stop").attr("offset", "0%").attr("stop-color", color).attr("stop-opacity", 0.9); + grad.append("stop").attr("offset", "100%").attr("stop-color", color).attr("stop-opacity", 0.4); }); } @@ -434,54 +434,31 @@ class TheseusVisualizer { ? point.date.toISOString().split('T')[0] : point.date; - const oldestYear = this.years[0]; - const originalVal = point[oldestYear] || 0; - - // Find previous point to detect refactor - const idx = this.points.indexOf(point); - const prev = idx > 0 ? this.points[idx - 1] : null; - const prevOldVal = prev ? (prev[oldestYear] || 0) : null; - const isRefactor = prevOldVal && originalVal < prevOldVal * 0.85; - - const evolutionVal = point.total - originalVal; - - let refactorHTML = ''; - if (originalVal === 0) { - refactorHTML = ` -
- Ship of Theseus: The Great Rebirth - The original source code is now entirely gone.
Is this still the same codebase? -
- `; - } else if (isRefactor) { - refactorHTML = ` -
- Ship of Theseus: Major Refactor - A significant part of the original source was refactored here.
How much can you change before the identity shifts? -
- `; - } + const foundationYear = this.years[0]; + const foundationVal = point[foundationYear] || 0; + + const existingYears = Object.keys(point).filter(k => k !== 'date' && k !== 'total').sort(); + const oldestSurvivingYear = existingYears[0]; + const oldestSurvivingVal = point[oldestSurvivingYear] || 0; + + const isFoundationAlive = foundationVal > 0; + const refactoredVal = point.total - foundationVal; this.tooltip.innerHTML = ` - ${refactorHTML}
Snapshot: ${dateStr}
Total Project Size - ${point.total.toLocaleString()} lines + ${point.total.toLocaleString()} lines
- Original (${oldestYear}) + Foundation (${foundationYear})
- ${originalVal.toLocaleString()} - ${point.total > 0 ? ((originalVal / point.total) * 100).toFixed(1) : '0.0'}% + ${foundationVal.toLocaleString()} + ${point.total > 0 ? ((foundationVal / point.total) * 100).toFixed(1) : '0.0'}%
@@ -490,10 +467,22 @@ class TheseusVisualizer { Refactored
- ${evolutionVal.toLocaleString()} - ${point.total > 0 ? ((evolutionVal / point.total) * 100).toFixed(1) : '0.0'}% + ${refactoredVal.toLocaleString()} + ${point.total > 0 ? ((refactoredVal / point.total) * 100).toFixed(1) : '0.0'}% +
+

+ ${!isFoundationAlive && oldestSurvivingYear !== foundationYear ? ` +
+
+ + Oldest surviving (${oldestSurvivingYear}) +
+
+ ${oldestSurvivingVal.toLocaleString()} + ${point.total > 0 ? ((oldestSurvivingVal / point.total) * 100).toFixed(1) : '0.0'}%
+ ` : ''} `; // Positioning AFTER content injection @@ -552,54 +541,9 @@ class TheseusVisualizer { document.getElementById('percent-replaced').textContent = '--'; } - // Death counter: count times when original code dropped to 0 - let deathCount = 0; - let wasDead = false; - for (const point of this.points) { - const origLines = point[birthYear] || 0; - if (origLines === 0 && !wasDead) { - deathCount++; - wasDead = true; - } else if (origLines > 0) { - wasDead = false; - } - } - document.getElementById('death-count').textContent = deathCount; - - // 4. Modernization Velocity (Δ Old Code / Δ Time) + // Mean Code Age (Weighted average) const lastDate = new Date(last.date); const currentYear = lastDate.getFullYear(); - const oldThreshold = currentYear - 3; - - // Find snapshot approx 6 months ago (180 days) - const targetMs = lastDate.getTime() - (180 * 24 * 60 * 60 * 1000); - let prevSnapshot = this.points[0]; - for (let i = this.points.length - 1; i >= 0; i--) { - if (new Date(this.points[i].date).getTime() <= targetMs) { - prevSnapshot = this.points[i]; - break; - } - } - - const getOldLines = (snap) => { - return this.years - .filter(y => y <= oldThreshold) - .reduce((sum, y) => sum + (snap[y] || 0), 0); - }; - - const oldNow = getOldLines(last); - const oldThen = getOldLines(prevSnapshot); - const months = Math.max(1, (lastDate - new Date(prevSnapshot.date)) / (30 * 24 * 60 * 60 * 1000)); - const velocity = (oldThen - oldNow) / months; - - const velEl = document.getElementById('modernization-velocity'); - if (this.points.length < 2 || oldThen === 0) { - velEl.textContent = 'Stable'; - } else { - velEl.textContent = `${Math.max(0, Math.round(velocity)).toLocaleString()}`; - } - - // 5. Mean Code Age (Weighted average) const totalLines = last.total; if (totalLines > 0) { let totalAge = 0; @@ -614,7 +558,7 @@ class TheseusVisualizer { document.getElementById('mean-code-age').textContent = '0.0 yrs'; } - // 6. Peak Preservation (Largest legacy year) + // Peak Preservation (Largest legacy year) let peakYear = '--'; let peakVal = 0; this.years.forEach(y => { diff --git a/index.html b/index.html index 32519c2..84de155 100644 --- a/index.html +++ b/index.html @@ -163,30 +163,6 @@

-
-

- How fast is code being replaced? - ? -

-
-

- -- -

-

Lines replaced per month

-
-
-
-

- How many times did the original codebase die? - ? -

-
-

--

-

Complete rebuilds

-
-

What's the average code age? diff --git a/style.css b/style.css index 87fb96b..1605a5d 100644 --- a/style.css +++ b/style.css @@ -426,6 +426,7 @@ svg#main-chart { align-items: center; font-size: 0.95rem; padding: 0.35rem 0; + gap: 1rem; } .label-group { @@ -443,7 +444,7 @@ svg#main-chart { .value-group { display: flex; align-items: center; - gap: 0.75rem; + gap: 1rem; } .percent-tag { From 054bcaff4bc0c53d3d2aa806f1e724db95134da0 Mon Sep 17 00:00:00 2001 From: Asif Sayyed Date: Mon, 11 May 2026 13:12:23 +0530 Subject: [PATCH 3/8] #25 improve fossil section --- app.js | 7 +----- index.html | 7 +++--- style.css | 63 +++++++++++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 62 insertions(+), 15 deletions(-) diff --git a/app.js b/app.js index 5f1dd23..01bfc73 100644 --- a/app.js +++ b/app.js @@ -618,12 +618,7 @@ class TheseusVisualizer { a.target = '_blank'; a.rel = 'noopener noreferrer'; a.textContent = display; - a.style.color = 'inherit'; - a.style.textDecoration = 'underline'; - a.style.textDecorationColor = 'rgba(255,255,255,0.2)'; - a.style.transition = 'color 0.3s ease'; - a.addEventListener('mouseover', () => { a.style.color = 'var(--accent-cyan)'; }); - a.addEventListener('mouseout', () => { a.style.color = 'inherit'; }); + a.className = 'fossil-link'; return a; }; diff --git a/index.html b/index.html index 84de155..069a834 100644 --- a/index.html +++ b/index.html @@ -197,6 +197,7 @@

How the data is collected

Ancient Code Fragments

+

Click the file path below to view on GitHub

@@ -210,8 +211,7 @@

Ancient Code Fragments

Loading...
-

The - oldest line ever written in this repo's history, even if deleted long ago.

+

The oldest line ever written in this repo's history, even if deleted long ago.

@@ -225,8 +225,7 @@

Ancient Code Fragments

Loading...
-

The - oldest line that is still alive in the codebase today.

+

The oldest line that is still alive in the codebase today.

diff --git a/style.css b/style.css index 1605a5d..ce799c9 100644 --- a/style.css +++ b/style.css @@ -772,15 +772,24 @@ svg#main-chart { .section-title { font-family: var(--font-serif); font-size: 2rem; - margin-bottom: 2rem; + margin-bottom: 0.5rem; color: var(--text-primary); text-align: center; } +.fossil-hint { + text-align: center; + font-size: 0.8rem; + color: var(--text-secondary); + opacity: 0.6; + margin-bottom: 2.5rem; + font-style: italic; +} + .fossil-grid { display: grid; grid-template-columns: 1fr; - gap: 2rem; + gap: 2.5rem; } @media (min-width: 768px) { @@ -793,10 +802,12 @@ svg#main-chart { background: rgba(255, 255, 255, 0.02); border: 1px solid rgba(255, 255, 255, 0.1); border-radius: 1.5rem; - padding: 1.25rem 1.5rem; + padding: 1.5rem 2rem; position: relative; overflow: hidden; text-align: left; + cursor: pointer; + transition: all 0.3s ease; } .fossil-card::before { @@ -815,6 +826,7 @@ svg#main-chart { .fossil-card:hover { border-color: rgba(59, 199, 199, 0.3); box-shadow: 0 0 40px rgba(59, 199, 199, 0.1); + transform: translateY(-4px); } .fossil-header { @@ -829,6 +841,20 @@ svg#main-chart { text-transform: uppercase; letter-spacing: 0.1em; color: var(--accent-cyan); + display: flex; + align-items: center; + gap: 0.5rem; +} + +.fossil-label::after { + content: '↗'; + font-size: 0.7rem; + opacity: 0; + transition: opacity 0.3s ease; +} + +.fossil-card:hover .fossil-label::after { + opacity: 0.6; } .fossil-year { @@ -842,14 +868,32 @@ svg#main-chart { .fossil-meta { font-size: 0.8rem; color: var(--text-secondary); - margin-bottom: 1rem; + margin-bottom: 1.25rem; opacity: 0.6; display: flex; - gap: 0.5rem; + gap: 0.75rem; align-items: center; flex-wrap: wrap; } +.fossil-link { + color: var(--accent-cyan); + text-decoration: underline; + text-underline-offset: 3px; + text-decoration-color: rgba(59, 199, 199, 0.4); + cursor: pointer; + transition: all 0.2s ease; + padding: 0.25rem 0.5rem; + border-radius: 0.25rem; + background: rgba(59, 199, 199, 0.05); + display: inline-block; +} + +.fossil-link:hover { + background: rgba(59, 199, 199, 0.15); + text-decoration-color: rgba(59, 199, 199, 0.8); +} + .fossil-commit { font-family: var(--font-mono); font-size: 0.7rem; @@ -884,3 +928,12 @@ svg#main-chart { flex-shrink: 0; display: inline; } + +.fossil-description { + font-size: 0.75rem; + font-style: italic; + color: var(--text-secondary); + opacity: 0.5; + margin-top: 1.25rem; + line-height: 1.5; +} From 3a070edb069a35eebac83b65322dae50803f6255 Mon Sep 17 00:00:00 2001 From: Asif Sayyed Date: Mon, 11 May 2026 13:26:09 +0530 Subject: [PATCH 4/8] #25 fix data issue --- app.js | 17 +++++++---------- index.html | 6 +++--- 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/app.js b/app.js index 01bfc73..606d5af 100644 --- a/app.js +++ b/app.js @@ -528,15 +528,13 @@ class TheseusVisualizer { } document.getElementById('oldest-line').textContent = oldestSurviving; - if (birthYear && first.total > 0) { - const originalLinesInFirst = first[birthYear] || 0; - if (originalLinesInFirst > 0) { - const originalLinesInLast = last[birthYear] || 0; - const replaced = ((originalLinesInFirst - originalLinesInLast) / originalLinesInFirst) * 100; - document.getElementById('percent-replaced').textContent = `${Math.min(100, Math.max(0, replaced)).toFixed(1)}%`; - } else { - document.getElementById('percent-replaced').textContent = '0.0%'; - } + const foundationLines = last[birthYear] || 0; + const totalLines = last.total || 0; + if (birthYear && totalLines > 0) { + const foundationPercent = (foundationLines / totalLines) * 100; + document.getElementById('percent-replaced').textContent = `${foundationPercent.toFixed(1)}%`; + } else if (totalLines > 0) { + document.getElementById('percent-replaced').textContent = '0.0%'; } else { document.getElementById('percent-replaced').textContent = '--'; } @@ -544,7 +542,6 @@ class TheseusVisualizer { // Mean Code Age (Weighted average) const lastDate = new Date(last.date); const currentYear = lastDate.getFullYear(); - const totalLines = last.total; if (totalLines > 0) { let totalAge = 0; this.years.forEach(y => { diff --git a/index.html b/index.html index 069a834..1324b90 100644 --- a/index.html +++ b/index.html @@ -111,13 +111,13 @@

The Ship of Theseus

Insights

- How much has changed? + How much foundation remains? ? + data-tooltip="Percentage of the current codebase that originated in the foundation year">?

--

-

of original code replaced

+

of current codebase is foundation code

From 91db3d55e3f8998f8705d6c8e41b4f08916c6745 Mon Sep 17 00:00:00 2001 From: Asif Sayyed Date: Tue, 12 May 2026 12:15:29 +0530 Subject: [PATCH 5/8] #25 added stars in the sky --- app.js | 73 +++++++++++++++++++++++++++++++++++++++++++++ style.css | 43 ++++++++++++++++++++++++++ theseus.config.json | 63 ++++++++++++++++++++++++++++++++++++-- 3 files changed, 177 insertions(+), 2 deletions(-) diff --git a/app.js b/app.js index 606d5af..0e0e46d 100644 --- a/app.js +++ b/app.js @@ -272,9 +272,58 @@ class TheseusVisualizer { // Interaction Components (Legend, Axes, Scrubber) this.renderLegend(); this.renderAxes(g, chartWidth, chartHeight, xScale, yScale); + this.renderMilestoneMarkers(g, chartWidth, chartHeight, xScale); this.setupInteractivity(g, chartWidth, chartHeight, xScale, yScale); } + renderMilestoneMarkers(g, chartWidth, chartHeight, xScale) { + const repoInfo = this.manifest.find(r => r.name === this.currentRepo); + if (!repoInfo || !repoInfo.milestones) return; + + const tooltip = this; + + repoInfo.milestones.forEach(m => { + const milestoneDate = new Date(m.date + '-01'); + const xPos = xScale(milestoneDate); + + if (xPos >= 0 && xPos <= chartWidth) { + const marker = g.append('g') + .attr('class', 'milestone-marker') + .attr('transform', `translate(${xPos}, 0)`) + .style('cursor', 'pointer'); + + marker.append('text') + .attr('x', 0) + .attr('y', 18) + .attr('text-anchor', 'middle') + .attr('font-size', '14px') + .attr('fill', '#8b5cf6') + .text('★') + .style('opacity', 0.8) + .style('filter', 'drop-shadow(0 0 4px rgba(139, 92, 246, 0.6))'); + + marker.append('title') + .text(m.title + ': ' + m.description); + + marker.on('mouseenter', function() { + d3.select(this).select('text') + .transition() + .duration(200) + .attr('font-size', '18px') + .style('opacity', 1); + }); + + marker.on('mouseleave', function() { + d3.select(this).select('text') + .transition() + .duration(200) + .attr('font-size', '14px') + .style('opacity', 0.8); + }); + } + }); + } + renderLegend() { this.legend.innerHTML = ''; const items = this.vizMode === 'identity' @@ -444,7 +493,31 @@ class TheseusVisualizer { const isFoundationAlive = foundationVal > 0; const refactoredVal = point.total - foundationVal; + // Find milestone if close to current date + let milestoneHTML = ''; + const repoInfo = this.manifest.find(r => r.name === this.currentRepo); + if (repoInfo && repoInfo.milestones) { + const pointDate = new Date(point.date); + for (const m of repoInfo.milestones) { + const milestoneDate = new Date(m.date + '-01'); + const monthsDiff = Math.abs((pointDate - milestoneDate) / (1000 * 60 * 60 * 24 * 30)); + if (monthsDiff <= 3) { // Within 3 months + milestoneHTML = ` +
+
🏛️
+
+
${m.title}
+
${m.description}
+
+
+ `; + break; + } + } + } + this.tooltip.innerHTML = ` + ${milestoneHTML}
Snapshot: ${dateStr}
Total Project Size diff --git a/style.css b/style.css index ce799c9..31a91f2 100644 --- a/style.css +++ b/style.css @@ -407,6 +407,49 @@ svg#main-chart { z-index: 100; min-width: 340px; box-shadow: 0 30px 60px rgba(0, 0, 0, 0.8); +} + +.milestone-banner { + display: flex; + gap: 0.75rem; + align-items: flex-start; + background: linear-gradient(135deg, rgba(139, 92, 246, 0.15), rgba(59, 199, 199, 0.1)); + border: 1px solid rgba(139, 92, 246, 0.3); + border-radius: 0.75rem; + padding: 1rem; + margin-bottom: 1.25rem; +} + +.milestone-icon { + font-size: 1.5rem; + flex-shrink: 0; +} + +.milestone-content { + flex: 1; +} + +.milestone-title { + font-weight: 600; + font-size: 0.9rem; + color: var(--text-primary); + margin-bottom: 0.35rem; +} + +.milestone-desc { + font-size: 0.75rem; + color: var(--text-secondary); + line-height: 1.4; + opacity: 0.9; +} + +.milestone-marker text { + transition: all 0.2s ease; +} + +.milestone-marker:hover text { + filter: drop-shadow(0 0 8px rgba(139, 92, 246, 0.8)); +} transition: opacity 0.2s ease; } diff --git a/theseus.config.json b/theseus.config.json index ec4968d..60a52fc 100644 --- a/theseus.config.json +++ b/theseus.config.json @@ -11,13 +11,72 @@ "name": "react", "file": "react_data.json", "description": "Component-based JavaScript library for building user interfaces.", - "repo": "facebook/react" + "repo": "facebook/react", + "milestones": [ + { + "date": "2013-05", + "title": "React open sourced", + "description": "React was released as open source at JSConf 2013. Facebook engineers shared their internal tool with the world." + }, + { + "date": "2017-09", + "title": "React rebuilt from scratch", + "description": "React 16 launched with a complete internal rewrite. Same API for users, but the engine was entirely rebuilt to be faster and more flexible." + }, + { + "date": "2019-02", + "title": "Hooks changed everything", + "description": "React 16.8 introduced Hooks - a new way to use state and features without writing classes. This became the standard way to write React." + }, + { + "date": "2024-04", + "title": "React 19 major update", + "description": "React 19 brought Server Components and new ways to handle forms and data. Check the next two milestones for data quirks." + }, + { + "date": "2019-06", + "title": "Data quirk: code looks different", + "description": "The data shows weird patterns here because Facebook reorganized their code internally. Old code got re-attributed to new files." + }, + { + "date": "2023-06", + "title": "Data quirk: lots missing", + "description": "This is a data quirk - many years of code seem to vanish. It's just how the data was collected at this point." + } + ] }, { "name": "numpy", "file": "numpy_data.json", "description": "The fundamental package for scientific computing in Python.", - "repo": "numpy/numpy" + "repo": "numpy/numpy", + "milestones": [ + { + "date": "2005-09", + "title": "NumPy is born", + "description": "Travis Oliphant merges Numeric and Numarray to create NumPy - the foundation of Python's scientific computing ecosystem." + }, + { + "date": "2006-03", + "title": "NumPy 1.0 released", + "description": "NumPy 1.0 launches as a standalone package, separated from SciPy. This marks the official birth of NumPy as its own library." + }, + { + "date": "2013-04", + "title": "Python 2 & 3 unified", + "description": "Major refactoring to create a unified codebase supporting both Python 2 and Python 3 without 2to3 conversion. Shipped in NumPy 1.8.0 (Oct 2013)." + }, + { + "date": "2017-06", + "title": "Major features added", + "description": "NumPy 1.13 brings groundbreaking features: __array_ufunc__, np.block, and 50+ new functions transform the library." + }, + { + "date": "2024-06", + "title": "NumPy 2.0 released", + "description": "First major release since 2006. Massive breaking changes with ABI break, new dtype system, and 10% fewer namespace objects." + } + ] }, { "name": "zed", From 9ec3b9957cff459f06c9e8242eef926e3fad013f Mon Sep 17 00:00:00 2001 From: Asif Sayyed Date: Thu, 14 May 2026 12:26:52 +0530 Subject: [PATCH 6/8] #25 starry night for each opensource repo --- app.js | 4 +-- style.css | 6 ++-- theseus.config.json | 86 +++++++++++++++++++++++++++++++++++++-------- 3 files changed, 76 insertions(+), 20 deletions(-) diff --git a/app.js b/app.js index 0e0e46d..811a92b 100644 --- a/app.js +++ b/app.js @@ -297,10 +297,10 @@ class TheseusVisualizer { .attr('y', 18) .attr('text-anchor', 'middle') .attr('font-size', '14px') - .attr('fill', '#8b5cf6') + .attr('fill', '#3bc7c7') .text('★') .style('opacity', 0.8) - .style('filter', 'drop-shadow(0 0 4px rgba(139, 92, 246, 0.6))'); + .style('filter', 'drop-shadow(0 0 4px rgba(59, 199, 199, 0.6))'); marker.append('title') .text(m.title + ': ' + m.description); diff --git a/style.css b/style.css index 31a91f2..83c7c39 100644 --- a/style.css +++ b/style.css @@ -407,6 +407,7 @@ svg#main-chart { z-index: 100; min-width: 340px; box-shadow: 0 30px 60px rgba(0, 0, 0, 0.8); + transition: opacity 0.2s ease; } .milestone-banner { @@ -448,11 +449,10 @@ svg#main-chart { } .milestone-marker:hover text { - filter: drop-shadow(0 0 8px rgba(139, 92, 246, 0.8)); -} - transition: opacity 0.2s ease; + filter: drop-shadow(0 0 8px rgba(59, 199, 199, 0.8)); } + .tooltip-header { font-size: 0.75rem; text-transform: uppercase; diff --git a/theseus.config.json b/theseus.config.json index 60a52fc..d9345ec 100644 --- a/theseus.config.json +++ b/theseus.config.json @@ -5,7 +5,24 @@ "name": "langchain", "file": "langchain_data.json", "description": "Framework for developing LLM-driven applications and agents.", - "repo": "langchain-ai/langchain" + "repo": "langchain-ai/langchain", + "milestones": [ + { + "date": "2023-12", + "title": "LangChain v0.1", + "description": "First stable architecture release with standardized core components." + }, + { + "date": "2024-06", + "title": "Monorepo & LangGraph Cloud", + "description": "Massive expansion with LangGraph Cloud and integration packages." + }, + { + "date": "2025-10", + "title": "LangChain v1.0 (The Pruning)", + "description": "Legacy code moved to langchain-classic for a leaner, faster core." + } + ] }, { "name": "react", @@ -16,32 +33,32 @@ { "date": "2013-05", "title": "React open sourced", - "description": "React was released as open source at JSConf 2013. Facebook engineers shared their internal tool with the world." + "description": "Public release of React at JSConf 2013." }, { "date": "2017-09", "title": "React rebuilt from scratch", - "description": "React 16 launched with a complete internal rewrite. Same API for users, but the engine was entirely rebuilt to be faster and more flexible." + "description": "React 16 rewrite for better performance." }, { "date": "2019-02", "title": "Hooks changed everything", - "description": "React 16.8 introduced Hooks - a new way to use state and features without writing classes. This became the standard way to write React." + "description": "Introduced Hooks for state management without classes." }, { "date": "2024-04", "title": "React 19 major update", - "description": "React 19 brought Server Components and new ways to handle forms and data. Check the next two milestones for data quirks." + "description": "Added Server Components and new form handling." }, { "date": "2019-06", "title": "Data quirk: code looks different", - "description": "The data shows weird patterns here because Facebook reorganized their code internally. Old code got re-attributed to new files." + "description": "Data quirk: Internal code reorganization." }, { "date": "2023-06", "title": "Data quirk: lots missing", - "description": "This is a data quirk - many years of code seem to vanish. It's just how the data was collected at this point." + "description": "Data quirk: Missing historical data." } ] }, @@ -54,27 +71,27 @@ { "date": "2005-09", "title": "NumPy is born", - "description": "Travis Oliphant merges Numeric and Numarray to create NumPy - the foundation of Python's scientific computing ecosystem." + "description": "Created by merging Numeric and Numarray." }, { "date": "2006-03", "title": "NumPy 1.0 released", - "description": "NumPy 1.0 launches as a standalone package, separated from SciPy. This marks the official birth of NumPy as its own library." + "description": "Official 1.0 release as a standalone library." }, { "date": "2013-04", "title": "Python 2 & 3 unified", - "description": "Major refactoring to create a unified codebase supporting both Python 2 and Python 3 without 2to3 conversion. Shipped in NumPy 1.8.0 (Oct 2013)." + "description": "Unified support for Python 2 and 3." }, { "date": "2017-06", "title": "Major features added", - "description": "NumPy 1.13 brings groundbreaking features: __array_ufunc__, np.block, and 50+ new functions transform the library." + "description": "Major update with 50+ new functions." }, { "date": "2024-06", "title": "NumPy 2.0 released", - "description": "First major release since 2006. Massive breaking changes with ABI break, new dtype system, and 10% fewer namespace objects." + "description": "NumPy 2.0: Major update with new dtype system." } ] }, @@ -82,13 +99,52 @@ "name": "zed", "file": "zed_data.json", "description": "High-performance, GPU-accelerated code editor for teamwork.", - "repo": "zed-industries/zed" + "repo": "zed-industries/zed", + "milestones": [ + { + "date": "2023-03", + "title": "Zed Beta Launch", + "description": "High-performance code editor enters public beta on macOS." + }, + { + "date": "2023-12", + "title": "GPUI2 Transition and Open Sourced", + "description": "Major rewrite of the UI framework for 120 FPS performance and The Zed source code is made available to the public." + }, + { + "date": "2024-06", + "title": "Linux Release", + "description": "Official launch of Zed for Linux after months of development." + }, + { + "date": "2024-09", + "title": "Zed AI Launch", + "description": "Introduction of native AI features and the Zed AI ecosystem." + } + ] }, { "name": "claude-code", "file": "claude-code_data.json", "description": "Claude's agentic CLI tool for local coding tasks.", - "repo": "anthropics/claude-code" + "repo": "anthropics/claude-code", + "milestones": [ + { + "date": "2025-05", + "title": "Official v1.0 Launch", + "description": "General availability alongside the Claude 4 model family." + }, + { + "date": "2025-09", + "title": "v2.0 Major Overhaul", + "description": "Foundational rewrite with terminal-first architecture." + }, + { + "date": "2026-03", + "title": "Source Code Leak (v2.1.88)", + "description": "Accidental exposure of source code via npm map files." + } + ] } ] -} +} \ No newline at end of file From 77721944f7a71fe123d39ee36a00055ff8e585f5 Mon Sep 17 00:00:00 2001 From: Asif Sayyed Date: Thu, 14 May 2026 12:30:45 +0530 Subject: [PATCH 7/8] #25 docs: updated the config doc --- docs/CONFIGURATION.md | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/docs/CONFIGURATION.md b/docs/CONFIGURATION.md index 0a506fa..f3949ed 100644 --- a/docs/CONFIGURATION.md +++ b/docs/CONFIGURATION.md @@ -13,7 +13,10 @@ The Ship of Theseus engine operates centrally off a single file: `theseus.config "name": "react", "repo": "facebook/react", "displayName": "React", - "description": "A JavaScript library for building user interfaces" + "description": "A JavaScript library for building user interfaces", + "milestones": [ + { "date": "2013-05", "title": "Open Source", "description": "React is released." } + ] } ] } @@ -33,6 +36,20 @@ The `repositories` array takes objects consisting of the following key attribute | `repo` | *String* | The GitHub repository namespace (the URL ending). The engine automatically strips trailing slashes and resolves this to `https://github.com/namespace/repo.git`. | `"django/django"` | | `displayName` | *String* | The aesthetic name rendered on UI Cards. | `"Django"` | | `description` | *String* | A short UI subheading clarifying what the project is. | `"The web framework for perfectionists with deadlines."` | +| `milestones` | *Array* | An optional list of significant events to display on the timeline. | `[{"date": "2024-01", "title": "Launch"}]` | + +--- + +## Milestone Structure + +The `milestones` array contains objects with the following properties: + +| Key | Type | Description | Example | +| :--- | :---: | :--- | :--- | +| `date` | *String* | The date of the milestone in `YYYY-MM` format. | `"2024-06"` | +| `title` | *String* | A short, catchy name for the event shown in tooltips. | `"Monorepo Migration"` | +| `description` | *String* | A concise explanation of the event. | `"Unified all integrations into a single repository."` | + --- From 9db29b403a74cf40c416665866571c4a3e9facfe Mon Sep 17 00:00:00 2001 From: Asif Sayyed Date: Thu, 14 May 2026 13:08:35 +0530 Subject: [PATCH 8/8] #25 bux: fixes from the review --- app.js | 8 ++++---- style.css | 2 ++ 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/app.js b/app.js index 811a92b..e44244e 100644 --- a/app.js +++ b/app.js @@ -305,7 +305,7 @@ class TheseusVisualizer { marker.append('title') .text(m.title + ': ' + m.description); - marker.on('mouseenter', function() { + marker.on('mouseenter', function () { d3.select(this).select('text') .transition() .duration(200) @@ -313,7 +313,7 @@ class TheseusVisualizer { .style('opacity', 1); }); - marker.on('mouseleave', function() { + marker.on('mouseleave', function () { d3.select(this).select('text') .transition() .duration(200) @@ -486,7 +486,7 @@ class TheseusVisualizer { const foundationYear = this.years[0]; const foundationVal = point[foundationYear] || 0; - const existingYears = Object.keys(point).filter(k => k !== 'date' && k !== 'total').sort(); + const existingYears = Object.keys(point).filter(k => k !== 'date' && k !== 'total' && point[k] > 0).sort(); const oldestSurvivingYear = existingYears[0]; const oldestSurvivingVal = point[oldestSurvivingYear] || 0; @@ -544,7 +544,7 @@ class TheseusVisualizer { ${point.total > 0 ? ((refactoredVal / point.total) * 100).toFixed(1) : '0.0'}%
- ${!isFoundationAlive && oldestSurvivingYear !== foundationYear ? ` + ${!isFoundationAlive && oldestSurvivingYear && oldestSurvivingYear !== foundationYear ? `
diff --git a/style.css b/style.css index 83c7c39..75dff70 100644 --- a/style.css +++ b/style.css @@ -18,6 +18,8 @@ margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); + -webkit-clip-path: inset(50%); + clip-path: inset(50%); white-space: nowrap; border: 0; }