heyiam 0.2.29 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +45 -0
- package/dist/config.js +10 -1
- package/dist/db.js +1 -2
- package/dist/export.js +40 -25
- package/dist/format-utils.js +5 -0
- package/dist/index.js +168 -0
- package/dist/mount.js +300 -102
- package/dist/parsers/claude.js +2 -28
- package/dist/parsers/codex.js +2 -26
- package/dist/parsers/cursor.js +2 -26
- package/dist/parsers/duration.js +35 -0
- package/dist/parsers/gemini.js +2 -20
- package/dist/parsers/types.js +0 -1
- package/dist/public/assets/index-BZ65TU_Y.js +40 -0
- package/dist/public/assets/index-CqCaW2cb.css +1 -0
- package/dist/public/index.html +2 -2
- package/dist/redact.js +4 -104
- package/dist/render/build-render-data.js +9 -2
- package/dist/render/index.js +32 -5
- package/dist/render/liquid.js +147 -7
- package/dist/render/mock-data.js +303 -0
- package/dist/render/templates/aurora/portfolio.liquid +204 -0
- package/dist/render/templates/aurora/project.liquid +260 -0
- package/dist/render/templates/aurora/session.liquid +223 -0
- package/dist/render/templates/aurora/styles.css +1178 -0
- package/dist/render/templates/bauhaus/portfolio.liquid +179 -0
- package/dist/render/templates/bauhaus/project.liquid +300 -0
- package/dist/render/templates/bauhaus/session.liquid +333 -0
- package/dist/render/templates/bauhaus/styles.css +1641 -0
- package/dist/render/templates/blueprint/portfolio.liquid +167 -0
- package/dist/render/templates/blueprint/project.liquid +286 -0
- package/dist/render/templates/blueprint/session.liquid +248 -0
- package/dist/render/templates/blueprint/styles.css +1285 -0
- package/dist/render/templates/canvas/portfolio.liquid +215 -0
- package/dist/render/templates/canvas/project.liquid +235 -0
- package/dist/render/templates/canvas/session.liquid +223 -0
- package/dist/render/templates/canvas/styles.css +1436 -0
- package/dist/render/templates/carbon/portfolio.liquid +170 -0
- package/dist/render/templates/carbon/project.liquid +249 -0
- package/dist/render/templates/carbon/session.liquid +190 -0
- package/dist/render/templates/carbon/styles.css +1091 -0
- package/dist/render/templates/chalk/portfolio.liquid +199 -0
- package/dist/render/templates/chalk/project.liquid +245 -0
- package/dist/render/templates/chalk/session.liquid +215 -0
- package/dist/render/templates/chalk/styles.css +1157 -0
- package/dist/render/templates/circuit/portfolio.liquid +162 -0
- package/dist/render/templates/circuit/project.liquid +247 -0
- package/dist/render/templates/circuit/session.liquid +205 -0
- package/dist/render/templates/circuit/styles.css +1403 -0
- package/dist/render/templates/cosmos/portfolio.liquid +232 -0
- package/dist/render/templates/cosmos/project.liquid +327 -0
- package/dist/render/templates/cosmos/session.liquid +239 -0
- package/dist/render/templates/cosmos/styles.css +1151 -0
- package/dist/render/templates/daylight/portfolio.liquid +217 -0
- package/dist/render/templates/daylight/project.liquid +229 -0
- package/dist/render/templates/daylight/session.liquid +219 -0
- package/dist/render/templates/daylight/styles.css +1311 -0
- package/dist/render/templates/editorial/portfolio.liquid +126 -0
- package/dist/render/templates/editorial/project.liquid +202 -0
- package/dist/render/templates/editorial/session.liquid +171 -0
- package/dist/render/templates/editorial/styles.css +822 -0
- package/dist/render/templates/ember/portfolio.liquid +318 -0
- package/dist/render/templates/ember/project.liquid +232 -0
- package/dist/render/templates/ember/session.liquid +202 -0
- package/dist/render/templates/ember/styles.css +1283 -0
- package/dist/render/templates/glacier/portfolio.liquid +271 -0
- package/dist/render/templates/glacier/project.liquid +288 -0
- package/dist/render/templates/glacier/session.liquid +217 -0
- package/dist/render/templates/glacier/styles.css +1200 -0
- package/dist/render/templates/grid/portfolio.liquid +265 -0
- package/dist/render/templates/grid/project.liquid +306 -0
- package/dist/render/templates/grid/session.liquid +260 -0
- package/dist/render/templates/grid/styles.css +1441 -0
- package/dist/render/templates/kinetic/portfolio.liquid +170 -0
- package/dist/render/templates/kinetic/project.liquid +242 -0
- package/dist/render/templates/kinetic/session.liquid +228 -0
- package/dist/render/templates/kinetic/styles.css +944 -0
- package/dist/render/templates/meridian/portfolio.liquid +255 -0
- package/dist/render/templates/meridian/project.liquid +376 -0
- package/dist/render/templates/meridian/session.liquid +298 -0
- package/dist/render/templates/meridian/styles.css +1369 -0
- package/dist/render/templates/minimal/portfolio.liquid +71 -0
- package/dist/render/templates/minimal/project.liquid +154 -0
- package/dist/render/templates/minimal/session.liquid +140 -0
- package/dist/render/templates/minimal/styles.css +525 -0
- package/dist/render/templates/mono/portfolio.liquid +291 -0
- package/dist/render/templates/mono/project.liquid +275 -0
- package/dist/render/templates/mono/session.liquid +276 -0
- package/dist/render/templates/mono/styles.css +1016 -0
- package/dist/render/templates/neon/portfolio.liquid +217 -0
- package/dist/render/templates/neon/project.liquid +225 -0
- package/dist/render/templates/neon/session.liquid +195 -0
- package/dist/render/templates/neon/styles.css +1265 -0
- package/dist/render/templates/noir/portfolio.liquid +137 -0
- package/dist/render/templates/noir/project.liquid +220 -0
- package/dist/render/templates/noir/session.liquid +241 -0
- package/dist/render/templates/noir/styles.css +1223 -0
- package/dist/render/templates/obsidian/portfolio.liquid +257 -0
- package/dist/render/templates/obsidian/project.liquid +280 -0
- package/dist/render/templates/obsidian/session.liquid +241 -0
- package/dist/render/templates/obsidian/styles.css +1401 -0
- package/dist/render/templates/paper/portfolio.liquid +267 -0
- package/dist/render/templates/paper/project.liquid +235 -0
- package/dist/render/templates/paper/session.liquid +271 -0
- package/dist/render/templates/paper/styles.css +1509 -0
- package/dist/render/templates/parallax/portfolio.liquid +305 -0
- package/dist/render/templates/parallax/project.liquid +275 -0
- package/dist/render/templates/parallax/session.liquid +295 -0
- package/dist/render/templates/parallax/styles.css +1874 -0
- package/dist/render/templates/parchment/portfolio.liquid +290 -0
- package/dist/render/templates/parchment/project.liquid +289 -0
- package/dist/render/templates/parchment/session.liquid +346 -0
- package/dist/render/templates/parchment/styles.css +1397 -0
- package/dist/render/templates/partials/_beats.liquid +16 -0
- package/dist/render/templates/partials/_breadcrumb.liquid +9 -0
- package/dist/render/templates/partials/_footer.liquid +7 -0
- package/dist/render/templates/partials/_growth-chart.liquid +7 -0
- package/dist/render/templates/partials/_key-decisions.liquid +20 -0
- package/dist/render/templates/partials/_links.liquid +16 -0
- package/dist/render/templates/partials/_narrative.liquid +8 -0
- package/dist/render/templates/partials/_phases.liquid +20 -0
- package/dist/render/templates/partials/_portfolio-header.liquid +20 -0
- package/dist/render/templates/partials/_portfolio-projects.liquid +16 -0
- package/dist/render/templates/partials/_portfolio-stats.liquid +19 -0
- package/dist/render/templates/partials/_qa.liquid +13 -0
- package/dist/render/templates/partials/_screenshot.liquid +15 -0
- package/dist/render/templates/partials/_session-cards.liquid +30 -0
- package/dist/render/templates/partials/_session-header.liquid +39 -0
- package/dist/render/templates/partials/_session-sidebar.liquid +30 -0
- package/dist/render/templates/partials/_skills.liquid +12 -0
- package/dist/render/templates/partials/_source-breakdown.liquid +22 -0
- package/dist/render/templates/partials/_stats.liquid +38 -0
- package/dist/render/templates/partials/_work-timeline.liquid +7 -0
- package/dist/render/templates/project.liquid +7 -4
- package/dist/render/templates/radar/portfolio.liquid +233 -0
- package/dist/render/templates/radar/project.liquid +278 -0
- package/dist/render/templates/radar/session.liquid +300 -0
- package/dist/render/templates/radar/styles.css +1049 -0
- package/dist/render/templates/showcase/portfolio.liquid +231 -0
- package/dist/render/templates/showcase/project.liquid +237 -0
- package/dist/render/templates/showcase/session.liquid +210 -0
- package/dist/render/templates/showcase/styles.css +1279 -0
- package/dist/render/templates/signal/portfolio.liquid +227 -0
- package/dist/render/templates/signal/project.liquid +278 -0
- package/dist/render/templates/signal/session.liquid +282 -0
- package/dist/render/templates/signal/styles.css +1395 -0
- package/dist/render/templates/strata/portfolio.liquid +192 -0
- package/dist/render/templates/strata/project.liquid +282 -0
- package/dist/render/templates/strata/session.liquid +261 -0
- package/dist/render/templates/strata/styles.css +1350 -0
- package/dist/render/templates/styles.css +1190 -0
- package/dist/render/templates/terminal/portfolio.liquid +118 -0
- package/dist/render/templates/terminal/project.liquid +161 -0
- package/dist/render/templates/terminal/session.liquid +145 -0
- package/dist/render/templates/terminal/styles.css +492 -0
- package/dist/render/templates/verdant/portfolio.liquid +333 -0
- package/dist/render/templates/verdant/project.liquid +309 -0
- package/dist/render/templates/verdant/session.liquid +237 -0
- package/dist/render/templates/verdant/styles.css +1257 -0
- package/dist/render/templates/zen/portfolio.liquid +136 -0
- package/dist/render/templates/zen/project.liquid +187 -0
- package/dist/render/templates/zen/session.liquid +203 -0
- package/dist/render/templates/zen/styles.css +1207 -0
- package/dist/render/templates.js +90 -0
- package/dist/routes/context.js +15 -10
- package/dist/routes/enhance.js +17 -40
- package/dist/routes/export.js +14 -4
- package/dist/routes/preview.js +480 -108
- package/dist/routes/projects.js +11 -19
- package/dist/routes/publish.js +15 -17
- package/dist/routes/settings.js +94 -1
- package/dist/routes/sse.js +9 -0
- package/dist/server.js +8 -2
- package/dist/settings.js +17 -9
- package/package.json +2 -4
- package/dist/public/assets/index-CC9G8EF1.js +0 -21
- package/dist/public/assets/index-Dalqz2mC.css +0 -1
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
<div class="heyiam-portfolio kinetic" data-render-version="2" data-template="kinetic" data-username="{{ user.username }}">
|
|
2
|
+
|
|
3
|
+
{%- comment -%} Hero {%- endcomment -%}
|
|
4
|
+
{% if hasProfile %}
|
|
5
|
+
<section class="hero" aria-label="Developer profile">
|
|
6
|
+
<div class="hero-bg-text" aria-hidden="true">{{ user.username }}</div>
|
|
7
|
+
<div class="hero-content">
|
|
8
|
+
<div class="eyebrow">Developer Portfolio</div>
|
|
9
|
+
<div class="hero-profile-row">
|
|
10
|
+
{% if user.photoUrl %}
|
|
11
|
+
<img src="{{ user.photoUrl }}" alt="{{ user.displayName }}" class="profile-photo">
|
|
12
|
+
{% endif %}
|
|
13
|
+
<div>
|
|
14
|
+
{% if user.displayName != blank %}
|
|
15
|
+
<h1>{{ user.displayName }}</h1>
|
|
16
|
+
{% endif %}
|
|
17
|
+
{% if user.bio %}
|
|
18
|
+
<p class="hero-bio">{{ user.bio }}</p>
|
|
19
|
+
{% endif %}
|
|
20
|
+
{% if user.location %}
|
|
21
|
+
<span class="hero-location">{{ user.location }}</span>
|
|
22
|
+
{% endif %}
|
|
23
|
+
<div class="contact-row">
|
|
24
|
+
{% if user.email %}
|
|
25
|
+
<a href="mailto:{{ user.email }}"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="2" y="4" width="20" height="16" rx="2"/><path d="m2 4 10 8 10-8"/></svg> {{ user.email }}</a>
|
|
26
|
+
{% endif %}
|
|
27
|
+
{% if user.linkedinUrl %}
|
|
28
|
+
<a href="{{ user.linkedinUrl }}" target="_blank" rel="noopener"><svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor"><path d="M20.5 2h-17A1.5 1.5 0 002 3.5v17A1.5 1.5 0 003.5 22h17a1.5 1.5 0 001.5-1.5v-17A1.5 1.5 0 0020.5 2zM8 19H5v-9h3zM6.5 8.25A1.75 1.75 0 118.3 6.5a1.78 1.78 0 01-1.8 1.75zM19 19h-3v-4.74c0-1.42-.6-1.93-1.38-1.93A1.74 1.74 0 0013 14.19V19h-3v-9h2.9v1.3a3.11 3.11 0 012.7-1.4c1.55 0 3.36.86 3.36 3.66z"/></svg> LinkedIn</a>
|
|
29
|
+
{% endif %}
|
|
30
|
+
{% if user.githubUrl %}
|
|
31
|
+
<a href="{{ user.githubUrl }}" target="_blank" rel="noopener"><svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor"><path d="M12 2C6.477 2 2 6.484 2 12.017c0 4.425 2.865 8.18 6.839 9.504.5.092.682-.217.682-.483 0-.237-.008-.868-.013-1.703-2.782.605-3.369-1.343-3.369-1.343-.454-1.158-1.11-1.466-1.11-1.466-.908-.62.069-.608.069-.608 1.003.07 1.531 1.032 1.531 1.032.892 1.53 2.341 1.088 2.91.832.092-.647.35-1.088.636-1.338-2.22-.253-4.555-1.113-4.555-4.951 0-1.093.39-1.988 1.029-2.688-.103-.253-.446-1.272.098-2.65 0 0 .84-.27 2.75 1.026A9.564 9.564 0 0112 6.844c.85.004 1.705.115 2.504.337 1.909-1.296 2.747-1.027 2.747-1.027.546 1.379.202 2.398.1 2.651.64.7 1.028 1.595 1.028 2.688 0 3.848-2.339 4.695-4.566 4.943.359.309.678.92.678 1.855 0 1.338-.012 2.419-.012 2.747 0 .268.18.58.688.482A10.019 10.019 0 0022 12.017C22 6.484 17.522 2 12 2z"/></svg> GitHub</a>
|
|
32
|
+
{% endif %}
|
|
33
|
+
{% if user.twitterHandle %}
|
|
34
|
+
<a href="https://x.com/{{ user.twitterHandle }}" target="_blank" rel="noopener"><svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor"><path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z"/></svg> @{{ user.twitterHandle }}</a>
|
|
35
|
+
{% endif %}
|
|
36
|
+
{% if user.websiteUrl %}
|
|
37
|
+
<a href="{{ user.websiteUrl }}" target="_blank" rel="noopener">{{ user.websiteUrl | stripProtocol }}</a>
|
|
38
|
+
{% endif %}
|
|
39
|
+
{% if user.resumeUrl %}
|
|
40
|
+
<a href="{{ user.resumeUrl }}" class="resume-btn"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/><line x1="12" y1="18" x2="12" y2="12"/><polyline points="9 15 12 18 15 15"/></svg> Resume (PDF)</a>
|
|
41
|
+
{% endif %}
|
|
42
|
+
</div>
|
|
43
|
+
</div>
|
|
44
|
+
</div>
|
|
45
|
+
</div>
|
|
46
|
+
</section>
|
|
47
|
+
{% endif %}
|
|
48
|
+
|
|
49
|
+
{%- comment -%} Stats row {%- endcomment -%}
|
|
50
|
+
<div class="stats-row" aria-label="Portfolio statistics">
|
|
51
|
+
<div class="stat-item">
|
|
52
|
+
<span class="stat-value"><span class="counter" data-target="{{ projects.size }}">0</span></span>
|
|
53
|
+
<span class="stat-label">Projects</span>
|
|
54
|
+
</div>
|
|
55
|
+
<div class="stat-item">
|
|
56
|
+
<span class="stat-value"><span class="counter" data-target="{{ totalSessions }}">0</span></span>
|
|
57
|
+
<span class="stat-label">Sessions</span>
|
|
58
|
+
</div>
|
|
59
|
+
<div class="stat-item">
|
|
60
|
+
<span class="stat-value"><span class="counter" data-target="{{ totalLoc }}" data-format="comma">0</span></span>
|
|
61
|
+
<span class="stat-label">Lines Changed</span>
|
|
62
|
+
</div>
|
|
63
|
+
{% if efficiencyMultiplier %}
|
|
64
|
+
<div class="stat-item stat-item--leverage">
|
|
65
|
+
<div class="leverage-row">
|
|
66
|
+
<span><span class="leverage-num">{{ totalDurationMinutes | formatDuration }}</span> <span class="leverage-sub">/ you</span></span>
|
|
67
|
+
<span><span class="leverage-num leverage-num--agent">{{ totalAgentDurationMinutes | formatDuration }}</span> <span class="leverage-sub">/ agents</span></span>
|
|
68
|
+
<span><span class="leverage-num leverage-num--multi">{{ efficiencyMultiplier }}</span> <span class="leverage-sub">leverage</span></span>
|
|
69
|
+
</div>
|
|
70
|
+
{% assign totalCombined = totalDurationMinutes | plus: totalAgentDurationMinutes %}
|
|
71
|
+
{% if totalCombined > 0 %}
|
|
72
|
+
{% assign humanPct = totalDurationMinutes | times: 100 | divided_by: totalCombined %}
|
|
73
|
+
{% assign agentPct = 100 | minus: humanPct %}
|
|
74
|
+
<div class="leverage-bar">
|
|
75
|
+
<div class="leverage-bar__human" style="width: {{ humanPct }}%;"></div>
|
|
76
|
+
<div class="leverage-bar__agent" style="width: {{ agentPct }}%;"></div>
|
|
77
|
+
</div>
|
|
78
|
+
<div class="leverage-legend">
|
|
79
|
+
<span>you · {{ humanPct }}%</span>
|
|
80
|
+
<span>agents · {{ agentPct }}%</span>
|
|
81
|
+
</div>
|
|
82
|
+
{% endif %}
|
|
83
|
+
</div>
|
|
84
|
+
{% else %}
|
|
85
|
+
<div class="stat-item">
|
|
86
|
+
<span class="stat-value">{{ totalDurationMinutes | formatDuration }}</span>
|
|
87
|
+
<span class="stat-label">Total Time</span>
|
|
88
|
+
</div>
|
|
89
|
+
{% endif %}
|
|
90
|
+
</div>
|
|
91
|
+
|
|
92
|
+
{%- comment -%} Projects section {%- endcomment -%}
|
|
93
|
+
{% if projects.size > 0 %}
|
|
94
|
+
<section class="section" aria-label="Projects">
|
|
95
|
+
<div class="section-tag">Projects</div>
|
|
96
|
+
<h2 class="section-title">{{ projects.size }} project{{ projects.size | minus: 1 | at_least: 1 | times: 0 | plus: projects.size | minus: 1 }}{% if projects.size != 1 %}s{% endif %} built with AI</h2>
|
|
97
|
+
<p class="section-desc">Each project is a case study with real sessions, real decisions, and real stats.</p>
|
|
98
|
+
|
|
99
|
+
<div class="projects-grid">
|
|
100
|
+
{% for p in projects %}
|
|
101
|
+
<a href="/{{ user.username }}/{{ p.slug }}" class="project-card">
|
|
102
|
+
<div class="project-chrome">
|
|
103
|
+
<div class="project-chrome-dots" aria-hidden="true"><span></span><span></span><span></span></div>
|
|
104
|
+
<div class="project-chrome-url">heyi.am/{{ user.username }}/{{ p.slug }}</div>
|
|
105
|
+
</div>
|
|
106
|
+
<div class="project-body">
|
|
107
|
+
<h3 class="project-card-title">{{ p.title }}</h3>
|
|
108
|
+
<div class="project-stats-row">
|
|
109
|
+
<div class="project-stat-item">
|
|
110
|
+
<span class="project-stat-value">{{ p.totalSessions }}</span>
|
|
111
|
+
<span class="project-stat-label">Sessions</span>
|
|
112
|
+
</div>
|
|
113
|
+
<div class="project-stat-item">
|
|
114
|
+
<span class="project-stat-value">{{ p.totalDurationMinutes | formatDuration }}</span>
|
|
115
|
+
<span class="project-stat-label">Total time</span>
|
|
116
|
+
</div>
|
|
117
|
+
<div class="project-stat-item">
|
|
118
|
+
<span class="project-stat-value">{{ p.totalLoc | localeNumber }}</span>
|
|
119
|
+
<span class="project-stat-label">Lines changed</span>
|
|
120
|
+
</div>
|
|
121
|
+
</div>
|
|
122
|
+
{% if p.narrative %}
|
|
123
|
+
<div class="narrative-card">{{ p.narrative }}</div>
|
|
124
|
+
{% endif %}
|
|
125
|
+
{% if p.skills.size > 0 %}
|
|
126
|
+
<div class="chips">
|
|
127
|
+
{% for skill in p.skills %}
|
|
128
|
+
<span>{{ skill }}</span>
|
|
129
|
+
{% endfor %}
|
|
130
|
+
</div>
|
|
131
|
+
{% endif %}
|
|
132
|
+
</div>
|
|
133
|
+
</a>
|
|
134
|
+
{% endfor %}
|
|
135
|
+
</div>
|
|
136
|
+
</section>
|
|
137
|
+
{% endif %}
|
|
138
|
+
|
|
139
|
+
{%- comment -%} Source Mix {%- endcomment -%}
|
|
140
|
+
{% if sourceCounts.size > 0 %}
|
|
141
|
+
<section class="section" aria-label="Source breakdown">
|
|
142
|
+
<div class="section-tag">Source mix</div>
|
|
143
|
+
<h2 class="section-title">Tools of the trade</h2>
|
|
144
|
+
<p class="section-desc">How work is distributed across AI coding tools.</p>
|
|
145
|
+
|
|
146
|
+
<div class="split">
|
|
147
|
+
{% for src in sourceCounts %}
|
|
148
|
+
<div class="split-panel">
|
|
149
|
+
<h3>{{ src.tool }}</h3>
|
|
150
|
+
{% if totalSourceSessions > 0 %}
|
|
151
|
+
{% assign srcPct = src.count | times: 100 | divided_by: totalSourceSessions %}
|
|
152
|
+
{% else %}
|
|
153
|
+
{% assign srcPct = 0 %}
|
|
154
|
+
{% endif %}
|
|
155
|
+
<div class="split-stat">
|
|
156
|
+
<span class="split-stat-value{% if forloop.first %} hl-orange{% endif %}">{{ srcPct }}%</span>
|
|
157
|
+
<span class="split-stat-label">of sessions</span>
|
|
158
|
+
</div>
|
|
159
|
+
<div class="split-detail">
|
|
160
|
+
<span class="hl-orange">→</span> {{ src.count }} sessions total
|
|
161
|
+
</div>
|
|
162
|
+
</div>
|
|
163
|
+
{% endfor %}
|
|
164
|
+
</div>
|
|
165
|
+
</section>
|
|
166
|
+
{% endif %}
|
|
167
|
+
|
|
168
|
+
{%- comment -%} Counter animation script {%- endcomment -%}
|
|
169
|
+
|
|
170
|
+
</div>
|
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
<div class="heyiam-project kinetic" data-render-version="2" data-template="kinetic"{% if sessionBaseUrl %} data-session-base-url="{{ sessionBaseUrl }}"{% endif %} data-username="{{ user.username }}" data-project-slug="{{ project.slug }}">
|
|
2
|
+
|
|
3
|
+
{%- comment -%} Hero {%- endcomment -%}
|
|
4
|
+
<section class="hero hero--project" aria-label="Project header">
|
|
5
|
+
<div class="hero-bg-text" aria-hidden="true">{{ project.slug }}</div>
|
|
6
|
+
<div class="hero-content">
|
|
7
|
+
<div class="breadcrumb" aria-label="Breadcrumb">
|
|
8
|
+
<a href="/{{ user.username }}">{{ user.username }}</a>
|
|
9
|
+
<span class="breadcrumb-sep">/</span>
|
|
10
|
+
<span>{{ project.slug }}</span>
|
|
11
|
+
</div>
|
|
12
|
+
<div class="eyebrow">Project Case Study</div>
|
|
13
|
+
<h1 data-editable="title">{{ project.title }}</h1>
|
|
14
|
+
{% if project.repoUrl or project.projectUrl %}
|
|
15
|
+
<div class="hero-links">
|
|
16
|
+
{% if project.repoUrl %}
|
|
17
|
+
<a href="{{ project.repoUrl }}" target="_blank" rel="noopener">{{ project.repoUrl | stripProtocol }}</a>
|
|
18
|
+
{% endif %}
|
|
19
|
+
{% if project.projectUrl %}
|
|
20
|
+
<a href="{{ project.projectUrl }}" target="_blank" rel="noopener">{{ project.projectUrl | stripProtocol }}</a>
|
|
21
|
+
{% endif %}
|
|
22
|
+
</div>
|
|
23
|
+
{% endif %}
|
|
24
|
+
</div>
|
|
25
|
+
</section>
|
|
26
|
+
|
|
27
|
+
{%- comment -%} Stats row {%- endcomment -%}
|
|
28
|
+
<div class="stats-row stats-row--project" role="region" aria-label="Project statistics">
|
|
29
|
+
<div class="stat-item">
|
|
30
|
+
<span class="stat-value"><span class="counter" data-target="{{ project.totalSessions }}">0</span></span>
|
|
31
|
+
<span class="stat-label">Sessions</span>
|
|
32
|
+
</div>
|
|
33
|
+
<div class="stat-item">
|
|
34
|
+
<span class="stat-value"><span class="counter" data-target="{{ project.totalLoc }}" data-format="comma">0</span></span>
|
|
35
|
+
<span class="stat-label">Lines Changed</span>
|
|
36
|
+
</div>
|
|
37
|
+
<div class="stat-item">
|
|
38
|
+
<span class="stat-value"><span class="counter" data-target="{{ project.totalFilesChanged }}">0</span></span>
|
|
39
|
+
<span class="stat-label">Files</span>
|
|
40
|
+
</div>
|
|
41
|
+
{% if project.totalTokens %}
|
|
42
|
+
<div class="stat-item">
|
|
43
|
+
<span class="stat-value">{{ project.totalTokens | formatTokens }}</span>
|
|
44
|
+
<span class="stat-label">Tokens</span>
|
|
45
|
+
</div>
|
|
46
|
+
{% endif %}
|
|
47
|
+
{% if efficiencyMultiplier %}
|
|
48
|
+
<div class="stat-item stat-item--leverage">
|
|
49
|
+
<div class="leverage-row">
|
|
50
|
+
<span><span class="leverage-num">{{ project.totalDurationMinutes | formatDuration }}</span> <span class="leverage-sub">/ you</span></span>
|
|
51
|
+
<span><span class="leverage-num" style="color:var(--orange)">{{ project.totalAgentDurationMinutes | formatDuration }}</span> <span class="leverage-sub">/ agents</span></span>
|
|
52
|
+
<span><span class="leverage-num leverage-num--multi">{{ efficiencyMultiplier }}</span> <span class="leverage-sub">leverage</span></span>
|
|
53
|
+
</div>
|
|
54
|
+
{% assign totalCombined = project.totalDurationMinutes | plus: project.totalAgentDurationMinutes %}
|
|
55
|
+
{% if totalCombined > 0 %}
|
|
56
|
+
{% assign humanPct = project.totalDurationMinutes | times: 100 | divided_by: totalCombined %}
|
|
57
|
+
{% assign agentPct = 100 | minus: humanPct %}
|
|
58
|
+
<div class="leverage-bar">
|
|
59
|
+
<div class="leverage-bar__human" style="width: {{ humanPct }}%;"></div>
|
|
60
|
+
<div class="leverage-bar__agent" style="width: {{ agentPct }}%;"></div>
|
|
61
|
+
</div>
|
|
62
|
+
<div class="leverage-legend">
|
|
63
|
+
<span>you</span>
|
|
64
|
+
<span>agents</span>
|
|
65
|
+
</div>
|
|
66
|
+
{% endif %}
|
|
67
|
+
</div>
|
|
68
|
+
{% else %}
|
|
69
|
+
<div class="stat-item">
|
|
70
|
+
<span class="stat-value">{{ project.totalDurationMinutes | formatDuration }}</span>
|
|
71
|
+
<span class="stat-label">Time</span>
|
|
72
|
+
</div>
|
|
73
|
+
{% endif %}
|
|
74
|
+
</div>
|
|
75
|
+
|
|
76
|
+
{%- comment -%} Screenshot {%- endcomment -%}
|
|
77
|
+
{% if project.screenshotUrl %}
|
|
78
|
+
<section class="section section--flush" aria-label="Project screenshot">
|
|
79
|
+
<div class="browser-frame" data-editable="screenshot">
|
|
80
|
+
<div class="browser-frame__bar">
|
|
81
|
+
<div class="browser-frame__dot"></div>
|
|
82
|
+
<div class="browser-frame__dot"></div>
|
|
83
|
+
<div class="browser-frame__dot"></div>
|
|
84
|
+
<div class="browser-frame__url">Preview</div>
|
|
85
|
+
</div>
|
|
86
|
+
<div class="browser-frame__viewport">
|
|
87
|
+
<img src="{{ project.screenshotUrl }}" alt="{{ project.title }} screenshot">
|
|
88
|
+
</div>
|
|
89
|
+
</div>
|
|
90
|
+
</section>
|
|
91
|
+
{% endif %}
|
|
92
|
+
|
|
93
|
+
{%- comment -%} Narrative {%- endcomment -%}
|
|
94
|
+
{% if project.narrative %}
|
|
95
|
+
<section class="section" aria-label="Project narrative">
|
|
96
|
+
<div class="section-tag">Narrative</div>
|
|
97
|
+
<h2 class="section-title">The build story</h2>
|
|
98
|
+
<div class="narrative-card">
|
|
99
|
+
{{ project.narrative }}
|
|
100
|
+
</div>
|
|
101
|
+
</section>
|
|
102
|
+
{% endif %}
|
|
103
|
+
|
|
104
|
+
{%- comment -%} Work timeline chart {%- endcomment -%}
|
|
105
|
+
{% if sessionsJson %}
|
|
106
|
+
<section class="section section--flush" aria-label="Agent work timeline">
|
|
107
|
+
<div class="section-tag">Agent work</div>
|
|
108
|
+
<h2 class="section-title">Work timeline</h2>
|
|
109
|
+
<div class="timeline-container">
|
|
110
|
+
<div data-work-timeline data-sessions='{{ sessionsJson | raw }}'></div>
|
|
111
|
+
</div>
|
|
112
|
+
</section>
|
|
113
|
+
{% endif %}
|
|
114
|
+
|
|
115
|
+
{%- comment -%} Growth chart {%- endcomment -%}
|
|
116
|
+
{% if growthJson %}
|
|
117
|
+
<section class="section section--flush" aria-label="Growth over time">
|
|
118
|
+
<div class="section-tag">Growth</div>
|
|
119
|
+
<h2 class="section-title">Lines of code over time</h2>
|
|
120
|
+
<div class="growth-container">
|
|
121
|
+
<div data-growth-chart data-project-slug="{{ project.slug }}" data-total-loc="{{ project.totalLoc }}" data-total-files="{{ project.totalFilesChanged }}" data-sessions='{{ growthJson | raw }}'></div>
|
|
122
|
+
</div>
|
|
123
|
+
</section>
|
|
124
|
+
{% endif %}
|
|
125
|
+
|
|
126
|
+
{%- comment -%} Key decisions + Source breakdown {%- endcomment -%}
|
|
127
|
+
{% if arc.size > 0 or sourceCounts.size > 0 %}
|
|
128
|
+
<section class="section section--flush" aria-label="Decisions and sources">
|
|
129
|
+
<div class="split">
|
|
130
|
+
{% if arc.size > 0 %}
|
|
131
|
+
<div class="split-panel">
|
|
132
|
+
<h3>Key Decisions</h3>
|
|
133
|
+
{% for item in arc %}
|
|
134
|
+
<div class="decision-item">
|
|
135
|
+
<div class="decision-num">{{ item.phase | prepend: '0' | slice: -2, 2 }}</div>
|
|
136
|
+
<div class="decision-text">{{ item.description }}</div>
|
|
137
|
+
</div>
|
|
138
|
+
{% endfor %}
|
|
139
|
+
</div>
|
|
140
|
+
{% endif %}
|
|
141
|
+
{% if sourceCounts.size > 0 %}
|
|
142
|
+
<div class="split-panel">
|
|
143
|
+
<h3>Source Breakdown</h3>
|
|
144
|
+
{% assign totalSourceSessions = 0 %}
|
|
145
|
+
{% for src in sourceCounts %}
|
|
146
|
+
{% assign totalSourceSessions = totalSourceSessions | plus: src.count %}
|
|
147
|
+
{% endfor %}
|
|
148
|
+
{% for src in sourceCounts %}
|
|
149
|
+
<div class="source-item">
|
|
150
|
+
{% if forloop.first %}
|
|
151
|
+
<span class="source-name hl-orange">{{ src.tool }}</span>
|
|
152
|
+
{% else %}
|
|
153
|
+
<span class="source-name">{{ src.tool }}</span>
|
|
154
|
+
{% endif %}
|
|
155
|
+
<div class="source-bar-wrap">
|
|
156
|
+
{% if totalSourceSessions > 0 %}
|
|
157
|
+
{% assign srcPct = src.count | times: 100 | divided_by: totalSourceSessions | round %}
|
|
158
|
+
<div class="source-bar"><div class="source-fill" style="width: {{ srcPct }}%;{% unless forloop.first %} background: var(--text-3);{% endunless %}"></div></div>
|
|
159
|
+
{% endif %}
|
|
160
|
+
</div>
|
|
161
|
+
{% if totalSourceSessions > 0 %}
|
|
162
|
+
{% assign srcPctDisplay = src.count | times: 100 | divided_by: totalSourceSessions | round %}
|
|
163
|
+
<span class="source-pct">{{ srcPctDisplay }}%</span>
|
|
164
|
+
{% endif %}
|
|
165
|
+
</div>
|
|
166
|
+
<div style="font-family: var(--font-mono); font-size: 0.625rem; color: var(--text-3); padding-left: 0.25rem;">{{ src.count }} session{% if src.count != 1 %}s{% endif %}</div>
|
|
167
|
+
{% endfor %}
|
|
168
|
+
</div>
|
|
169
|
+
{% endif %}
|
|
170
|
+
</div>
|
|
171
|
+
</section>
|
|
172
|
+
{% endif %}
|
|
173
|
+
|
|
174
|
+
{%- comment -%} Phases {%- endcomment -%}
|
|
175
|
+
{% if arc.size > 0 %}
|
|
176
|
+
<section class="section section--flush" aria-label="Project phases">
|
|
177
|
+
<div class="section-tag">Phases</div>
|
|
178
|
+
<h2 class="section-title">Project arc</h2>
|
|
179
|
+
<div class="phases phases--large">
|
|
180
|
+
{% assign dot_colors = 'dot-orange,dot-blue,dot-green,dot-purple' | split: ',' %}
|
|
181
|
+
{% for item in arc %}
|
|
182
|
+
<div class="phase-item">
|
|
183
|
+
{% assign colorIdx = forloop.index0 | modulo: 4 %}
|
|
184
|
+
<div class="phase-dot {{ dot_colors[colorIdx] }}"></div>
|
|
185
|
+
<div>
|
|
186
|
+
<div class="phase-title">{{ item.title }}</div>
|
|
187
|
+
<div class="phase-desc">{{ item.description }}</div>
|
|
188
|
+
</div>
|
|
189
|
+
</div>
|
|
190
|
+
{% endfor %}
|
|
191
|
+
</div>
|
|
192
|
+
</section>
|
|
193
|
+
{% endif %}
|
|
194
|
+
|
|
195
|
+
{%- comment -%} Skills {%- endcomment -%}
|
|
196
|
+
{% if project.skills.size > 0 %}
|
|
197
|
+
<section class="section section--flush" aria-label="Skills used">
|
|
198
|
+
<div class="section-tag">Skills</div>
|
|
199
|
+
<h2 class="section-title">Technologies</h2>
|
|
200
|
+
<div class="chips">
|
|
201
|
+
{% for skill in project.skills %}
|
|
202
|
+
<span>{{ skill }}</span>
|
|
203
|
+
{% endfor %}
|
|
204
|
+
</div>
|
|
205
|
+
</section>
|
|
206
|
+
{% endif %}
|
|
207
|
+
|
|
208
|
+
{%- comment -%} Session cards {%- endcomment -%}
|
|
209
|
+
{% if featuredSessions.size > 0 %}
|
|
210
|
+
<section class="section section--flush" aria-label="Featured sessions">
|
|
211
|
+
<div class="section-tag">Sessions</div>
|
|
212
|
+
<h2 class="section-title">{{ featuredSessions.size }} featured session{% if featuredSessions.size != 1 %}s{% endif %}</h2>
|
|
213
|
+
|
|
214
|
+
<div class="sessions-grid">
|
|
215
|
+
{% for s in featuredSessions %}
|
|
216
|
+
<a href="{{ sessionBaseUrl }}/{{ s.slug }}{{ sessionSuffix }}" class="session-card">
|
|
217
|
+
<div class="session-chrome">
|
|
218
|
+
<div class="session-chrome-dots" aria-hidden="true"><span></span><span></span><span></span></div>
|
|
219
|
+
<div class="session-chrome-url">session {{ forloop.index }}</div>
|
|
220
|
+
</div>
|
|
221
|
+
<div class="session-body">
|
|
222
|
+
<h3 class="session-title">{{ s.title }}</h3>
|
|
223
|
+
<div class="session-meta">
|
|
224
|
+
<span class="session-meta-item"><span class="session-meta-value">{{ s.durationMinutes | formatDuration }}</span></span>
|
|
225
|
+
<span class="session-meta-item"><span class="session-meta-value">{{ s.locChanged | localeNumber }}</span> LOC</span>
|
|
226
|
+
{% if s.agentSummary %}
|
|
227
|
+
<span class="session-meta-item"><span class="session-meta-value">{{ s.agentSummary.agents.size }}</span> agents</span>
|
|
228
|
+
{% endif %}
|
|
229
|
+
</div>
|
|
230
|
+
{% if s.skills.size > 0 %}
|
|
231
|
+
<span class="session-tag">{{ s.skills | first }}</span>
|
|
232
|
+
{% endif %}
|
|
233
|
+
</div>
|
|
234
|
+
</a>
|
|
235
|
+
{% endfor %}
|
|
236
|
+
</div>
|
|
237
|
+
</section>
|
|
238
|
+
{% endif %}
|
|
239
|
+
|
|
240
|
+
{%- comment -%} Counter animation script {%- endcomment -%}
|
|
241
|
+
|
|
242
|
+
</div>
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
<div class="heyiam-session kinetic" data-render-version="2" data-template="kinetic">
|
|
2
|
+
|
|
3
|
+
{%- comment -%} Hero {%- endcomment -%}
|
|
4
|
+
<header class="hero hero--session" aria-label="Session header">
|
|
5
|
+
<div class="hero-content">
|
|
6
|
+
<div class="breadcrumb" aria-label="Breadcrumb">
|
|
7
|
+
<a href="/{{ user.username }}">{{ user.username }}</a>
|
|
8
|
+
{% if projectSlug %}
|
|
9
|
+
<span class="breadcrumb-sep">/</span>
|
|
10
|
+
<a href="/{{ user.username }}/{{ projectSlug }}">{{ projectSlug }}</a>
|
|
11
|
+
{% endif %}
|
|
12
|
+
<span class="breadcrumb-sep">/</span>
|
|
13
|
+
<span>{{ session.title }}</span>
|
|
14
|
+
</div>
|
|
15
|
+
<div class="eyebrow">Session Detail</div>
|
|
16
|
+
<h1>{{ session.title }}</h1>
|
|
17
|
+
<div class="hero-meta">
|
|
18
|
+
{% if session.recordedAt %}
|
|
19
|
+
<span><span class="hero-meta-value">{{ session.recordedAt | formatDate }}</span></span>
|
|
20
|
+
<span class="hero-meta-sep" aria-hidden="true">·</span>
|
|
21
|
+
{% endif %}
|
|
22
|
+
{% if session.sourceTool %}
|
|
23
|
+
<span><span class="hero-meta-value">{{ session.sourceTool }}</span></span>
|
|
24
|
+
<span class="hero-meta-sep" aria-hidden="true">·</span>
|
|
25
|
+
{% endif %}
|
|
26
|
+
<span><span class="hero-meta-value">{{ session.durationMinutes | formatDuration }}</span></span>
|
|
27
|
+
<span class="hero-meta-sep" aria-hidden="true">·</span>
|
|
28
|
+
<span><span class="hero-meta-value">{{ session.turns }}</span> turns</span>
|
|
29
|
+
<span class="hero-meta-sep" aria-hidden="true">·</span>
|
|
30
|
+
<span><span class="hero-meta-value">{{ session.locChanged | localeNumber }}</span> LOC</span>
|
|
31
|
+
<span class="hero-meta-sep" aria-hidden="true">·</span>
|
|
32
|
+
<span><span class="hero-meta-value">{{ session.filesChanged }}</span> files</span>
|
|
33
|
+
</div>
|
|
34
|
+
</div>
|
|
35
|
+
</header>
|
|
36
|
+
|
|
37
|
+
{%- comment -%} Dev Take {%- endcomment -%}
|
|
38
|
+
{% if session.devTake %}
|
|
39
|
+
<div class="dev-take-section">
|
|
40
|
+
<div class="section-tag">Dev take</div>
|
|
41
|
+
<div class="narrative-card">
|
|
42
|
+
{{ session.devTake }}
|
|
43
|
+
</div>
|
|
44
|
+
</div>
|
|
45
|
+
{% endif %}
|
|
46
|
+
|
|
47
|
+
{%- comment -%} Main + Sidebar layout {%- endcomment -%}
|
|
48
|
+
<div class="content-layout">
|
|
49
|
+
{%- comment -%} Main content column {%- endcomment -%}
|
|
50
|
+
<div>
|
|
51
|
+
{%- comment -%} Execution Path (Beats) {%- endcomment -%}
|
|
52
|
+
{% if session.beats.size > 0 %}
|
|
53
|
+
<section class="execution-path" aria-label="Execution path">
|
|
54
|
+
<div class="section-tag">Execution path</div>
|
|
55
|
+
<h2 class="section-title">{{ session.beats.size }} beat{% if session.beats.size != 1 %}s{% endif %}</h2>
|
|
56
|
+
|
|
57
|
+
{% for beat in session.beats %}
|
|
58
|
+
<div class="beat">
|
|
59
|
+
<div class="beat-number" aria-hidden="true">{{ beat.stepNumber }}</div>
|
|
60
|
+
<div class="beat-content">
|
|
61
|
+
<div class="beat-title">{{ beat.title }}</div>
|
|
62
|
+
<div class="beat-desc">{{ beat.body }}</div>
|
|
63
|
+
</div>
|
|
64
|
+
</div>
|
|
65
|
+
{% endfor %}
|
|
66
|
+
</section>
|
|
67
|
+
{% endif %}
|
|
68
|
+
|
|
69
|
+
{%- comment -%} Q&A {%- endcomment -%}
|
|
70
|
+
{% if session.qaPairs.size > 0 %}
|
|
71
|
+
<section class="qa-section" aria-label="Questions and answers">
|
|
72
|
+
<div class="section-tag">Decisions</div>
|
|
73
|
+
<h2 class="section-title">Q&A</h2>
|
|
74
|
+
|
|
75
|
+
{% for qa in session.qaPairs %}
|
|
76
|
+
<div class="qa-split">
|
|
77
|
+
<div class="qa-panel">
|
|
78
|
+
<div class="qa-label">Question</div>
|
|
79
|
+
<div class="qa-text">{{ qa.question }}</div>
|
|
80
|
+
</div>
|
|
81
|
+
<div class="qa-panel">
|
|
82
|
+
<div class="qa-label">Answer</div>
|
|
83
|
+
<div class="qa-text">{{ qa.answer }}</div>
|
|
84
|
+
</div>
|
|
85
|
+
</div>
|
|
86
|
+
{% endfor %}
|
|
87
|
+
</section>
|
|
88
|
+
{% endif %}
|
|
89
|
+
|
|
90
|
+
{%- comment -%} Narrative {%- endcomment -%}
|
|
91
|
+
{% if session.narrative %}
|
|
92
|
+
<section style="margin-bottom: 3rem;" aria-label="Session narrative">
|
|
93
|
+
<div class="section-tag">Narrative</div>
|
|
94
|
+
<div class="narrative-card">
|
|
95
|
+
{{ session.narrative }}
|
|
96
|
+
</div>
|
|
97
|
+
</section>
|
|
98
|
+
{% endif %}
|
|
99
|
+
|
|
100
|
+
{%- comment -%} Highlights {%- endcomment -%}
|
|
101
|
+
{% if session.highlights.size > 0 %}
|
|
102
|
+
<section style="margin-bottom: 3rem;" aria-label="Session highlights">
|
|
103
|
+
<div class="section-tag">Highlights</div>
|
|
104
|
+
<ul style="list-style: none; padding: 0;">
|
|
105
|
+
{% for h in session.highlights %}
|
|
106
|
+
<li style="font-size: 0.8125rem; color: var(--text-2); line-height: 1.7; padding: 0.375rem 0; border-bottom: 1px solid var(--border);">{{ h }}</li>
|
|
107
|
+
{% endfor %}
|
|
108
|
+
</ul>
|
|
109
|
+
</section>
|
|
110
|
+
{% endif %}
|
|
111
|
+
|
|
112
|
+
{%- comment -%} Agent Summary {%- endcomment -%}
|
|
113
|
+
{% if session.agentSummary %}
|
|
114
|
+
<section class="agent-section" aria-label="Agent summary">
|
|
115
|
+
<div class="section-tag">Agents</div>
|
|
116
|
+
<h2 class="section-title">{{ session.agentSummary.agents.size }} sub-session{% if session.agentSummary.agents.size != 1 %}s{% endif %}</h2>
|
|
117
|
+
|
|
118
|
+
{% assign maxAgentLoc = 0 %}
|
|
119
|
+
{% for agent in session.agentSummary.agents %}
|
|
120
|
+
{% if agent.loc_changed > maxAgentLoc %}
|
|
121
|
+
{% assign maxAgentLoc = agent.loc_changed %}
|
|
122
|
+
{% endif %}
|
|
123
|
+
{% endfor %}
|
|
124
|
+
|
|
125
|
+
{% assign agent_colors = '#0891b2,#059669,#7c3aed,#475569,#e11d48,#d97706' | split: ',' %}
|
|
126
|
+
{% for agent in session.agentSummary.agents %}
|
|
127
|
+
<div class="agent-bar-row">
|
|
128
|
+
<span class="agent-bar-label">{{ agent.role }}</span>
|
|
129
|
+
<div class="agent-bar-track">
|
|
130
|
+
{% if maxAgentLoc > 0 %}
|
|
131
|
+
{% assign barPct = agent.loc_changed | times: 100 | divided_by: maxAgentLoc %}
|
|
132
|
+
{% else %}
|
|
133
|
+
{% assign barPct = 0 %}
|
|
134
|
+
{% endif %}
|
|
135
|
+
{% assign colorIdx = forloop.index0 | modulo: 6 %}
|
|
136
|
+
<div class="agent-bar-fill" style="width: {{ barPct }}%; background: {{ agent_colors[colorIdx] }};"></div>
|
|
137
|
+
</div>
|
|
138
|
+
<span class="agent-bar-meta">{{ agent.duration_minutes }}m / {{ agent.loc_changed }} LOC</span>
|
|
139
|
+
</div>
|
|
140
|
+
{% endfor %}
|
|
141
|
+
</section>
|
|
142
|
+
{% endif %}
|
|
143
|
+
</div>
|
|
144
|
+
|
|
145
|
+
{%- comment -%} Sidebar {%- endcomment -%}
|
|
146
|
+
<aside class="sidebar" aria-label="Session details">
|
|
147
|
+
{%- comment -%} Tools Used {%- endcomment -%}
|
|
148
|
+
{% if session.toolBreakdown.size > 0 %}
|
|
149
|
+
<div class="sidebar-card">
|
|
150
|
+
<div class="sidebar-card-title">Tools Used</div>
|
|
151
|
+
<div class="tools-table" role="table" aria-label="Tool usage counts">
|
|
152
|
+
{% for t in session.toolBreakdown %}
|
|
153
|
+
<div class="tools-row" role="row">
|
|
154
|
+
<span class="tools-name" role="cell">{{ t.tool }}</span>
|
|
155
|
+
<span class="tools-count" role="cell">{{ t.count }}</span>
|
|
156
|
+
</div>
|
|
157
|
+
{% endfor %}
|
|
158
|
+
</div>
|
|
159
|
+
</div>
|
|
160
|
+
{% endif %}
|
|
161
|
+
|
|
162
|
+
{%- comment -%} Files Changed {%- endcomment -%}
|
|
163
|
+
{% if session.topFiles.size > 0 %}
|
|
164
|
+
<div class="sidebar-card">
|
|
165
|
+
<div class="sidebar-card-title">Files Changed</div>
|
|
166
|
+
{% for f in session.topFiles %}
|
|
167
|
+
<div class="files-row">
|
|
168
|
+
<span class="files-name">{{ f.path }}</span>
|
|
169
|
+
<span class="files-diff"><span class="files-adds">+{{ f.additions }}</span>{% if f.deletions > 0 %} <span class="files-dels">-{{ f.deletions }}</span>{% endif %}</span>
|
|
170
|
+
</div>
|
|
171
|
+
{% endfor %}
|
|
172
|
+
</div>
|
|
173
|
+
{% endif %}
|
|
174
|
+
|
|
175
|
+
{%- comment -%} Skills {%- endcomment -%}
|
|
176
|
+
{% if session.skills.size > 0 %}
|
|
177
|
+
<div class="sidebar-card">
|
|
178
|
+
<div class="sidebar-card-title">Skills</div>
|
|
179
|
+
<div class="chips">
|
|
180
|
+
{% for skill in session.skills %}
|
|
181
|
+
<span>{{ skill }}</span>
|
|
182
|
+
{% endfor %}
|
|
183
|
+
</div>
|
|
184
|
+
</div>
|
|
185
|
+
{% endif %}
|
|
186
|
+
|
|
187
|
+
{%- comment -%} Session Stats {%- endcomment -%}
|
|
188
|
+
<div class="sidebar-card">
|
|
189
|
+
<div class="sidebar-card-title">Stats</div>
|
|
190
|
+
<div class="tools-table">
|
|
191
|
+
<div class="tools-row">
|
|
192
|
+
<span class="tools-name">Duration</span>
|
|
193
|
+
<span class="tools-count" style="color: var(--text);">{{ session.durationMinutes | formatDuration }}</span>
|
|
194
|
+
</div>
|
|
195
|
+
{% if session.wallClockMinutes %}
|
|
196
|
+
<div class="tools-row">
|
|
197
|
+
<span class="tools-name">Wall clock</span>
|
|
198
|
+
<span class="tools-count" style="color: var(--text);">{{ session.wallClockMinutes | formatDuration }}</span>
|
|
199
|
+
</div>
|
|
200
|
+
{% endif %}
|
|
201
|
+
<div class="tools-row">
|
|
202
|
+
<span class="tools-name">Turns</span>
|
|
203
|
+
<span class="tools-count" style="color: var(--text);">{{ session.turns }}</span>
|
|
204
|
+
</div>
|
|
205
|
+
<div class="tools-row">
|
|
206
|
+
<span class="tools-name">LOC</span>
|
|
207
|
+
<span class="tools-count" style="color: var(--text);">{{ session.locChanged | localeNumber }}</span>
|
|
208
|
+
</div>
|
|
209
|
+
<div class="tools-row">
|
|
210
|
+
<span class="tools-name">Files</span>
|
|
211
|
+
<span class="tools-count" style="color: var(--text);">{{ session.filesChanged }}</span>
|
|
212
|
+
</div>
|
|
213
|
+
{% if session.sourceTool %}
|
|
214
|
+
<div class="tools-row">
|
|
215
|
+
<span class="tools-name">Source</span>
|
|
216
|
+
<span class="tools-count">{{ session.sourceTool }}</span>
|
|
217
|
+
</div>
|
|
218
|
+
{% endif %}
|
|
219
|
+
</div>
|
|
220
|
+
</div>
|
|
221
|
+
</aside>
|
|
222
|
+
</div>
|
|
223
|
+
|
|
224
|
+
{%- comment -%} Agent bar animation script {%- endcomment -%}
|
|
225
|
+
{% if session.agentSummary %}
|
|
226
|
+
{% endif %}
|
|
227
|
+
|
|
228
|
+
</div>
|