@hustle-together/api-dev-tools 3.0.0 → 3.1.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 +71 -0
- package/bin/cli.js +184 -14
- package/demo/audio/generate-all-narrations.js +124 -59
- package/demo/audio/generate-narration.js +120 -56
- package/demo/audio/narration-adam-timing.json +3086 -2077
- package/demo/audio/narration-adam.mp3 +0 -0
- package/demo/audio/narration-creature-timing.json +3094 -2085
- package/demo/audio/narration-creature.mp3 +0 -0
- package/demo/audio/narration-gaming-timing.json +3091 -2082
- package/demo/audio/narration-gaming.mp3 +0 -0
- package/demo/audio/narration-hope-timing.json +3072 -2063
- package/demo/audio/narration-hope.mp3 +0 -0
- package/demo/audio/narration-mark-timing.json +3090 -2081
- package/demo/audio/narration-mark.mp3 +0 -0
- package/demo/audio/voices-manifest.json +16 -16
- package/demo/workflow-demo.html +1528 -411
- package/hooks/api-workflow-check.py +2 -0
- package/hooks/enforce-deep-research.py +180 -0
- package/hooks/enforce-disambiguation.py +149 -0
- package/hooks/enforce-documentation.py +187 -0
- package/hooks/enforce-environment.py +249 -0
- package/hooks/enforce-refactor.py +187 -0
- package/hooks/enforce-research.py +93 -46
- package/hooks/enforce-schema.py +186 -0
- package/hooks/enforce-scope.py +156 -0
- package/hooks/enforce-tdd-red.py +246 -0
- package/hooks/enforce-verify.py +186 -0
- package/hooks/verify-after-green.py +136 -6
- package/package.json +2 -1
- package/scripts/collect-test-results.ts +404 -0
- package/scripts/extract-parameters.ts +483 -0
- package/scripts/generate-test-manifest.ts +520 -0
- package/templates/CLAUDE-SECTION.md +84 -0
- package/templates/api-dev-state.json +45 -5
- package/templates/api-test/page.tsx +315 -0
- package/templates/api-test/test-structure/route.ts +269 -0
- package/templates/settings.json +36 -0
package/demo/workflow-demo.html
CHANGED
|
@@ -31,8 +31,12 @@
|
|
|
31
31
|
--border-color: #333;
|
|
32
32
|
--grey: #888;
|
|
33
33
|
--white: #f0f0f0;
|
|
34
|
+
/* Main accent - Hustle red */
|
|
34
35
|
--accent-red: #ba0c2f;
|
|
35
36
|
--accent-red-glow: rgba(186, 12, 47, 0.4);
|
|
37
|
+
/* Claude Code section only - orange */
|
|
38
|
+
--claude-orange: #f97316;
|
|
39
|
+
--claude-orange-glow: rgba(249, 115, 22, 0.4);
|
|
36
40
|
}
|
|
37
41
|
|
|
38
42
|
body {
|
|
@@ -338,17 +342,10 @@
|
|
|
338
342
|
height: 16px;
|
|
339
343
|
background: var(--white);
|
|
340
344
|
opacity: 0.5;
|
|
341
|
-
pointer-events:
|
|
342
|
-
cursor: pointer;
|
|
345
|
+
pointer-events: none; /* Don't intercept clicks - let them pass to progress bar */
|
|
343
346
|
margin-left: -1px;
|
|
344
347
|
}
|
|
345
348
|
|
|
346
|
-
.audio-section-marker:hover {
|
|
347
|
-
opacity: 1;
|
|
348
|
-
background: var(--accent-red);
|
|
349
|
-
box-shadow: 0 0 8px var(--accent-red-glow);
|
|
350
|
-
}
|
|
351
|
-
|
|
352
349
|
/* Chapter buttons */
|
|
353
350
|
.chapter-buttons {
|
|
354
351
|
display: flex;
|
|
@@ -575,13 +572,23 @@
|
|
|
575
572
|
SECTIONS & CONTENT
|
|
576
573
|
============================================ */
|
|
577
574
|
section {
|
|
578
|
-
|
|
575
|
+
/* Account for fixed header (60px) and audio player bottom bar (120px) */
|
|
576
|
+
min-height: calc(100vh - 180px);
|
|
577
|
+
max-height: calc(100vh - 100px);
|
|
579
578
|
display: flex;
|
|
580
579
|
flex-direction: column;
|
|
581
580
|
justify-content: center;
|
|
582
581
|
align-items: center;
|
|
583
|
-
padding:
|
|
582
|
+
padding: 80px 40px 60px;
|
|
584
583
|
position: relative;
|
|
584
|
+
overflow-y: auto;
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
/* When audio is playing, reduce section height to fit */
|
|
588
|
+
body.audio-playing section {
|
|
589
|
+
min-height: calc(100vh - 240px);
|
|
590
|
+
max-height: calc(100vh - 160px);
|
|
591
|
+
padding: 60px 40px 40px;
|
|
585
592
|
}
|
|
586
593
|
|
|
587
594
|
.ascii-border {
|
|
@@ -974,11 +981,14 @@
|
|
|
974
981
|
.gap-item {
|
|
975
982
|
border: 2px solid var(--border-color);
|
|
976
983
|
background: var(--darker-grey);
|
|
977
|
-
padding:
|
|
984
|
+
padding: 20px 25px;
|
|
978
985
|
opacity: 0;
|
|
979
986
|
transform: translateX(-30px);
|
|
980
987
|
transition: all 0.2s;
|
|
981
988
|
position: relative;
|
|
989
|
+
display: flex;
|
|
990
|
+
gap: 20px;
|
|
991
|
+
align-items: flex-start;
|
|
982
992
|
}
|
|
983
993
|
|
|
984
994
|
.gap-item:hover {
|
|
@@ -986,14 +996,14 @@
|
|
|
986
996
|
transform: translateX(5px);
|
|
987
997
|
}
|
|
988
998
|
|
|
989
|
-
.gap-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
999
|
+
.gap-icon {
|
|
1000
|
+
font-size: 2rem;
|
|
1001
|
+
flex-shrink: 0;
|
|
1002
|
+
line-height: 1;
|
|
1003
|
+
}
|
|
1004
|
+
|
|
1005
|
+
.gap-content {
|
|
1006
|
+
flex: 1;
|
|
997
1007
|
}
|
|
998
1008
|
|
|
999
1009
|
.gap-number {
|
|
@@ -1060,11 +1070,9 @@
|
|
|
1060
1070
|
}
|
|
1061
1071
|
|
|
1062
1072
|
.solution-icon {
|
|
1063
|
-
font-size:
|
|
1073
|
+
font-size: 2.5rem;
|
|
1064
1074
|
margin-bottom: 15px;
|
|
1065
1075
|
display: block;
|
|
1066
|
-
color: var(--accent-red);
|
|
1067
|
-
font-weight: bold;
|
|
1068
1076
|
}
|
|
1069
1077
|
|
|
1070
1078
|
.solution-title {
|
|
@@ -1421,6 +1429,483 @@
|
|
|
1421
1429
|
margin-bottom: 5px;
|
|
1422
1430
|
}
|
|
1423
1431
|
|
|
1432
|
+
/* ============================================
|
|
1433
|
+
CLAUDE CODE TERMINAL SIMULATION
|
|
1434
|
+
With side panel for explanations
|
|
1435
|
+
============================================ */
|
|
1436
|
+
.claude-code-container {
|
|
1437
|
+
display: flex;
|
|
1438
|
+
gap: 20px;
|
|
1439
|
+
width: 100%;
|
|
1440
|
+
max-width: 1400px;
|
|
1441
|
+
margin: 0 auto;
|
|
1442
|
+
}
|
|
1443
|
+
|
|
1444
|
+
.claude-code-terminal {
|
|
1445
|
+
flex: 2;
|
|
1446
|
+
background: #1e1e1e;
|
|
1447
|
+
border-radius: 12px;
|
|
1448
|
+
overflow: hidden;
|
|
1449
|
+
box-shadow: 0 4px 30px rgba(0, 0, 0, 0.5);
|
|
1450
|
+
border: 1px solid rgba(249, 115, 22, 0.2);
|
|
1451
|
+
}
|
|
1452
|
+
|
|
1453
|
+
.claude-code-header {
|
|
1454
|
+
display: flex;
|
|
1455
|
+
align-items: center;
|
|
1456
|
+
gap: 12px;
|
|
1457
|
+
padding: 12px 16px;
|
|
1458
|
+
background: #2d2d2d;
|
|
1459
|
+
border-bottom: 1px solid #3d3d3d;
|
|
1460
|
+
}
|
|
1461
|
+
|
|
1462
|
+
.claude-code-dots {
|
|
1463
|
+
display: flex;
|
|
1464
|
+
gap: 8px;
|
|
1465
|
+
}
|
|
1466
|
+
|
|
1467
|
+
.claude-code-dot {
|
|
1468
|
+
width: 12px;
|
|
1469
|
+
height: 12px;
|
|
1470
|
+
border-radius: 50%;
|
|
1471
|
+
}
|
|
1472
|
+
|
|
1473
|
+
.claude-code-dot.red { background: #ff5f56; }
|
|
1474
|
+
.claude-code-dot.yellow { background: #ffbd2e; }
|
|
1475
|
+
.claude-code-dot.green { background: #27ca40; }
|
|
1476
|
+
|
|
1477
|
+
.claude-code-title {
|
|
1478
|
+
flex: 1;
|
|
1479
|
+
text-align: center;
|
|
1480
|
+
color: #888;
|
|
1481
|
+
font-size: 0.85rem;
|
|
1482
|
+
font-family: 'SF Mono', 'Monaco', 'Inconsolata', monospace;
|
|
1483
|
+
}
|
|
1484
|
+
|
|
1485
|
+
.claude-code-badge {
|
|
1486
|
+
display: flex;
|
|
1487
|
+
align-items: center;
|
|
1488
|
+
gap: 6px;
|
|
1489
|
+
padding: 4px 12px;
|
|
1490
|
+
background: rgba(249, 115, 22, 0.15);
|
|
1491
|
+
border: 1px solid var(--claude-orange);
|
|
1492
|
+
border-radius: 4px;
|
|
1493
|
+
color: var(--claude-orange);
|
|
1494
|
+
font-size: 0.75rem;
|
|
1495
|
+
font-weight: 600;
|
|
1496
|
+
}
|
|
1497
|
+
|
|
1498
|
+
.claude-code-badge::before {
|
|
1499
|
+
content: '◉';
|
|
1500
|
+
animation: pulse-orange 1.5s infinite;
|
|
1501
|
+
}
|
|
1502
|
+
|
|
1503
|
+
@keyframes pulse-orange {
|
|
1504
|
+
0%, 100% { opacity: 1; }
|
|
1505
|
+
50% { opacity: 0.5; }
|
|
1506
|
+
}
|
|
1507
|
+
|
|
1508
|
+
.claude-code-body {
|
|
1509
|
+
padding: 20px;
|
|
1510
|
+
font-family: 'SF Mono', 'Monaco', 'Inconsolata', 'Courier New', monospace;
|
|
1511
|
+
font-size: 0.9rem;
|
|
1512
|
+
line-height: 1.6;
|
|
1513
|
+
max-height: 600px;
|
|
1514
|
+
overflow-y: auto;
|
|
1515
|
+
scroll-behavior: smooth;
|
|
1516
|
+
position: relative;
|
|
1517
|
+
}
|
|
1518
|
+
|
|
1519
|
+
.claude-msg {
|
|
1520
|
+
margin-bottom: 16px;
|
|
1521
|
+
opacity: 0;
|
|
1522
|
+
transform: translateY(10px);
|
|
1523
|
+
}
|
|
1524
|
+
|
|
1525
|
+
.claude-msg.visible {
|
|
1526
|
+
opacity: 1;
|
|
1527
|
+
transform: translateY(0);
|
|
1528
|
+
transition: all 0.3s ease;
|
|
1529
|
+
}
|
|
1530
|
+
|
|
1531
|
+
.claude-msg-role {
|
|
1532
|
+
display: flex;
|
|
1533
|
+
align-items: center;
|
|
1534
|
+
gap: 8px;
|
|
1535
|
+
margin-bottom: 8px;
|
|
1536
|
+
}
|
|
1537
|
+
|
|
1538
|
+
.claude-msg-role.ai {
|
|
1539
|
+
color: var(--claude-orange);
|
|
1540
|
+
}
|
|
1541
|
+
|
|
1542
|
+
.claude-msg-role.user {
|
|
1543
|
+
color: #3b82f6;
|
|
1544
|
+
}
|
|
1545
|
+
|
|
1546
|
+
.claude-msg-role.system {
|
|
1547
|
+
color: #22c55e;
|
|
1548
|
+
}
|
|
1549
|
+
|
|
1550
|
+
.claude-msg-icon {
|
|
1551
|
+
font-size: 1rem;
|
|
1552
|
+
}
|
|
1553
|
+
|
|
1554
|
+
.claude-msg-name {
|
|
1555
|
+
font-weight: 600;
|
|
1556
|
+
text-transform: uppercase;
|
|
1557
|
+
letter-spacing: 0.5px;
|
|
1558
|
+
font-size: 0.75rem;
|
|
1559
|
+
}
|
|
1560
|
+
|
|
1561
|
+
.claude-msg-content {
|
|
1562
|
+
padding-left: 28px;
|
|
1563
|
+
color: #e0e0e0;
|
|
1564
|
+
}
|
|
1565
|
+
|
|
1566
|
+
.claude-msg-content code {
|
|
1567
|
+
background: rgba(249, 115, 22, 0.15);
|
|
1568
|
+
color: var(--claude-orange);
|
|
1569
|
+
padding: 2px 6px;
|
|
1570
|
+
border-radius: 4px;
|
|
1571
|
+
font-size: 0.85em;
|
|
1572
|
+
}
|
|
1573
|
+
|
|
1574
|
+
.claude-tool-call {
|
|
1575
|
+
margin: 8px 0;
|
|
1576
|
+
padding: 12px;
|
|
1577
|
+
background: rgba(0, 0, 0, 0.3);
|
|
1578
|
+
border: 1px solid #3d3d3d;
|
|
1579
|
+
border-radius: 6px;
|
|
1580
|
+
border-left: 3px solid var(--claude-orange);
|
|
1581
|
+
}
|
|
1582
|
+
|
|
1583
|
+
.claude-tool-name {
|
|
1584
|
+
color: var(--claude-orange);
|
|
1585
|
+
font-weight: 600;
|
|
1586
|
+
margin-bottom: 4px;
|
|
1587
|
+
}
|
|
1588
|
+
|
|
1589
|
+
.claude-tool-result {
|
|
1590
|
+
color: #888;
|
|
1591
|
+
font-size: 0.85rem;
|
|
1592
|
+
}
|
|
1593
|
+
|
|
1594
|
+
.claude-user-choice {
|
|
1595
|
+
margin: 12px 0;
|
|
1596
|
+
padding: 12px;
|
|
1597
|
+
background: rgba(59, 130, 246, 0.1);
|
|
1598
|
+
border: 1px solid rgba(59, 130, 246, 0.3);
|
|
1599
|
+
border-radius: 6px;
|
|
1600
|
+
}
|
|
1601
|
+
|
|
1602
|
+
.claude-choice-option {
|
|
1603
|
+
display: flex;
|
|
1604
|
+
align-items: center;
|
|
1605
|
+
gap: 8px;
|
|
1606
|
+
padding: 8px 12px;
|
|
1607
|
+
margin: 4px 0;
|
|
1608
|
+
background: rgba(0, 0, 0, 0.2);
|
|
1609
|
+
border-radius: 4px;
|
|
1610
|
+
cursor: pointer;
|
|
1611
|
+
transition: all 0.2s;
|
|
1612
|
+
}
|
|
1613
|
+
|
|
1614
|
+
.claude-choice-option:hover {
|
|
1615
|
+
background: rgba(59, 130, 246, 0.2);
|
|
1616
|
+
}
|
|
1617
|
+
|
|
1618
|
+
.claude-choice-option.selected {
|
|
1619
|
+
background: rgba(59, 130, 246, 0.3);
|
|
1620
|
+
border: 1px solid #3b82f6;
|
|
1621
|
+
}
|
|
1622
|
+
|
|
1623
|
+
.claude-choice-marker {
|
|
1624
|
+
width: 18px;
|
|
1625
|
+
height: 18px;
|
|
1626
|
+
border: 2px solid #888;
|
|
1627
|
+
border-radius: 50%;
|
|
1628
|
+
display: flex;
|
|
1629
|
+
align-items: center;
|
|
1630
|
+
justify-content: center;
|
|
1631
|
+
}
|
|
1632
|
+
|
|
1633
|
+
.claude-choice-option.selected .claude-choice-marker {
|
|
1634
|
+
border-color: #3b82f6;
|
|
1635
|
+
background: #3b82f6;
|
|
1636
|
+
}
|
|
1637
|
+
|
|
1638
|
+
.claude-choice-option.selected .claude-choice-marker::after {
|
|
1639
|
+
content: '✓';
|
|
1640
|
+
color: white;
|
|
1641
|
+
font-size: 0.7rem;
|
|
1642
|
+
}
|
|
1643
|
+
|
|
1644
|
+
/* ASCII Art Startup Screen */
|
|
1645
|
+
.ascii-startup {
|
|
1646
|
+
font-family: 'SF Mono', 'Monaco', 'Inconsolata', 'Courier New', monospace;
|
|
1647
|
+
font-size: 11px;
|
|
1648
|
+
line-height: 1.3;
|
|
1649
|
+
color: var(--claude-orange);
|
|
1650
|
+
white-space: pre;
|
|
1651
|
+
margin: 0;
|
|
1652
|
+
padding: 16px;
|
|
1653
|
+
opacity: 0;
|
|
1654
|
+
display: none;
|
|
1655
|
+
}
|
|
1656
|
+
|
|
1657
|
+
.ascii-startup.visible {
|
|
1658
|
+
opacity: 1;
|
|
1659
|
+
display: block;
|
|
1660
|
+
}
|
|
1661
|
+
|
|
1662
|
+
.ascii-startup .welcome-text {
|
|
1663
|
+
color: #e5e5e5;
|
|
1664
|
+
}
|
|
1665
|
+
|
|
1666
|
+
.ascii-startup .tips-text {
|
|
1667
|
+
color: #888;
|
|
1668
|
+
}
|
|
1669
|
+
|
|
1670
|
+
.ascii-startup .model-text {
|
|
1671
|
+
color: var(--claude-orange);
|
|
1672
|
+
}
|
|
1673
|
+
|
|
1674
|
+
.ascii-startup .path-text {
|
|
1675
|
+
color: #666;
|
|
1676
|
+
}
|
|
1677
|
+
|
|
1678
|
+
/* Prompt Line */
|
|
1679
|
+
.claude-prompt-line {
|
|
1680
|
+
display: flex;
|
|
1681
|
+
align-items: center;
|
|
1682
|
+
gap: 8px;
|
|
1683
|
+
padding: 12px 16px;
|
|
1684
|
+
background: rgba(0, 0, 0, 0.2);
|
|
1685
|
+
border-top: 1px solid #3d3d3d;
|
|
1686
|
+
opacity: 0;
|
|
1687
|
+
}
|
|
1688
|
+
|
|
1689
|
+
.claude-prompt-line.visible {
|
|
1690
|
+
opacity: 1;
|
|
1691
|
+
}
|
|
1692
|
+
|
|
1693
|
+
.claude-prompt {
|
|
1694
|
+
color: var(--claude-orange);
|
|
1695
|
+
font-size: 1.1rem;
|
|
1696
|
+
font-weight: bold;
|
|
1697
|
+
}
|
|
1698
|
+
|
|
1699
|
+
.claude-input {
|
|
1700
|
+
color: #e5e5e5;
|
|
1701
|
+
font-family: 'SF Mono', 'Monaco', 'Inconsolata', monospace;
|
|
1702
|
+
}
|
|
1703
|
+
|
|
1704
|
+
.claude-cursor {
|
|
1705
|
+
display: inline-block;
|
|
1706
|
+
width: 8px;
|
|
1707
|
+
height: 16px;
|
|
1708
|
+
background: var(--claude-orange);
|
|
1709
|
+
animation: blink-cursor 1s infinite;
|
|
1710
|
+
margin-left: 2px;
|
|
1711
|
+
vertical-align: middle;
|
|
1712
|
+
}
|
|
1713
|
+
|
|
1714
|
+
@keyframes blink-cursor {
|
|
1715
|
+
0%, 50% { opacity: 1; }
|
|
1716
|
+
51%, 100% { opacity: 0; }
|
|
1717
|
+
}
|
|
1718
|
+
|
|
1719
|
+
/* Loading Dots Animation */
|
|
1720
|
+
.loading-dots {
|
|
1721
|
+
display: inline-flex;
|
|
1722
|
+
gap: 4px;
|
|
1723
|
+
padding: 8px 16px;
|
|
1724
|
+
margin: 8px 0;
|
|
1725
|
+
}
|
|
1726
|
+
|
|
1727
|
+
.loading-dots span {
|
|
1728
|
+
width: 8px;
|
|
1729
|
+
height: 8px;
|
|
1730
|
+
background: var(--claude-orange);
|
|
1731
|
+
border-radius: 50%;
|
|
1732
|
+
animation: pulse-dot 1.2s infinite ease-in-out;
|
|
1733
|
+
}
|
|
1734
|
+
|
|
1735
|
+
.loading-dots span:nth-child(2) {
|
|
1736
|
+
animation-delay: 0.2s;
|
|
1737
|
+
}
|
|
1738
|
+
|
|
1739
|
+
.loading-dots span:nth-child(3) {
|
|
1740
|
+
animation-delay: 0.4s;
|
|
1741
|
+
}
|
|
1742
|
+
|
|
1743
|
+
@keyframes pulse-dot {
|
|
1744
|
+
0%, 80%, 100% {
|
|
1745
|
+
opacity: 0.3;
|
|
1746
|
+
transform: scale(0.8);
|
|
1747
|
+
}
|
|
1748
|
+
40% {
|
|
1749
|
+
opacity: 1;
|
|
1750
|
+
transform: scale(1);
|
|
1751
|
+
}
|
|
1752
|
+
}
|
|
1753
|
+
|
|
1754
|
+
/* Thinking indicator */
|
|
1755
|
+
.claude-thinking {
|
|
1756
|
+
display: flex;
|
|
1757
|
+
align-items: center;
|
|
1758
|
+
gap: 8px;
|
|
1759
|
+
padding: 8px 28px;
|
|
1760
|
+
color: #888;
|
|
1761
|
+
font-style: italic;
|
|
1762
|
+
opacity: 0;
|
|
1763
|
+
}
|
|
1764
|
+
|
|
1765
|
+
.claude-thinking.visible {
|
|
1766
|
+
opacity: 1;
|
|
1767
|
+
}
|
|
1768
|
+
|
|
1769
|
+
/* Loop-back message styling */
|
|
1770
|
+
.claude-msg.loop-back .claude-msg-content {
|
|
1771
|
+
border-left: 3px solid #f59e0b;
|
|
1772
|
+
padding-left: 12px;
|
|
1773
|
+
background: rgba(245, 158, 11, 0.1);
|
|
1774
|
+
border-radius: 0 6px 6px 0;
|
|
1775
|
+
padding: 8px 12px;
|
|
1776
|
+
}
|
|
1777
|
+
|
|
1778
|
+
.loop-back-badge {
|
|
1779
|
+
display: inline-block;
|
|
1780
|
+
background: rgba(245, 158, 11, 0.2);
|
|
1781
|
+
color: #f59e0b;
|
|
1782
|
+
padding: 2px 8px;
|
|
1783
|
+
border-radius: 4px;
|
|
1784
|
+
font-size: 0.75rem;
|
|
1785
|
+
margin-bottom: 8px;
|
|
1786
|
+
}
|
|
1787
|
+
|
|
1788
|
+
/* Gap found styling */
|
|
1789
|
+
.gap-found {
|
|
1790
|
+
background: rgba(239, 68, 68, 0.1);
|
|
1791
|
+
border: 1px solid rgba(239, 68, 68, 0.3);
|
|
1792
|
+
border-radius: 6px;
|
|
1793
|
+
padding: 12px;
|
|
1794
|
+
margin: 8px 0;
|
|
1795
|
+
}
|
|
1796
|
+
|
|
1797
|
+
.gap-found-title {
|
|
1798
|
+
color: #ef4444;
|
|
1799
|
+
font-weight: 600;
|
|
1800
|
+
margin-bottom: 4px;
|
|
1801
|
+
}
|
|
1802
|
+
|
|
1803
|
+
/* Explanation Side Panel */
|
|
1804
|
+
.explanation-panel {
|
|
1805
|
+
flex: 1;
|
|
1806
|
+
min-width: 300px;
|
|
1807
|
+
background: var(--darker-grey);
|
|
1808
|
+
border: 1px solid var(--border-color);
|
|
1809
|
+
border-radius: 8px;
|
|
1810
|
+
overflow: hidden;
|
|
1811
|
+
}
|
|
1812
|
+
|
|
1813
|
+
.explanation-panel-header {
|
|
1814
|
+
padding: 12px 16px;
|
|
1815
|
+
background: rgba(249, 115, 22, 0.1);
|
|
1816
|
+
border-bottom: 1px solid var(--border-color);
|
|
1817
|
+
font-weight: 600;
|
|
1818
|
+
color: var(--claude-orange);
|
|
1819
|
+
font-size: 0.85rem;
|
|
1820
|
+
text-transform: uppercase;
|
|
1821
|
+
letter-spacing: 1px;
|
|
1822
|
+
}
|
|
1823
|
+
|
|
1824
|
+
.explanation-panel-body {
|
|
1825
|
+
padding: 16px;
|
|
1826
|
+
max-height: 600px;
|
|
1827
|
+
overflow-y: auto;
|
|
1828
|
+
}
|
|
1829
|
+
|
|
1830
|
+
.explanation-step {
|
|
1831
|
+
padding: 16px;
|
|
1832
|
+
margin-bottom: 12px;
|
|
1833
|
+
background: rgba(0, 0, 0, 0.2);
|
|
1834
|
+
border-radius: 6px;
|
|
1835
|
+
border-left: 3px solid var(--border-color);
|
|
1836
|
+
opacity: 0.5;
|
|
1837
|
+
transition: all 0.3s ease;
|
|
1838
|
+
}
|
|
1839
|
+
|
|
1840
|
+
.explanation-step.active {
|
|
1841
|
+
opacity: 1;
|
|
1842
|
+
border-left-color: var(--claude-orange);
|
|
1843
|
+
background: rgba(249, 115, 22, 0.05);
|
|
1844
|
+
}
|
|
1845
|
+
|
|
1846
|
+
.explanation-step-phase {
|
|
1847
|
+
display: flex;
|
|
1848
|
+
align-items: center;
|
|
1849
|
+
gap: 8px;
|
|
1850
|
+
margin-bottom: 8px;
|
|
1851
|
+
}
|
|
1852
|
+
|
|
1853
|
+
.explanation-step-num {
|
|
1854
|
+
width: 24px;
|
|
1855
|
+
height: 24px;
|
|
1856
|
+
background: var(--border-color);
|
|
1857
|
+
border-radius: 50%;
|
|
1858
|
+
display: flex;
|
|
1859
|
+
align-items: center;
|
|
1860
|
+
justify-content: center;
|
|
1861
|
+
font-size: 0.75rem;
|
|
1862
|
+
font-weight: 600;
|
|
1863
|
+
color: var(--grey);
|
|
1864
|
+
}
|
|
1865
|
+
|
|
1866
|
+
.explanation-step.active .explanation-step-num {
|
|
1867
|
+
background: var(--claude-orange);
|
|
1868
|
+
color: white;
|
|
1869
|
+
}
|
|
1870
|
+
|
|
1871
|
+
.explanation-step-name {
|
|
1872
|
+
font-weight: 600;
|
|
1873
|
+
color: var(--grey);
|
|
1874
|
+
font-size: 0.85rem;
|
|
1875
|
+
}
|
|
1876
|
+
|
|
1877
|
+
.explanation-step.active .explanation-step-name {
|
|
1878
|
+
color: var(--white);
|
|
1879
|
+
}
|
|
1880
|
+
|
|
1881
|
+
.explanation-step-desc {
|
|
1882
|
+
color: var(--grey);
|
|
1883
|
+
font-size: 0.8rem;
|
|
1884
|
+
line-height: 1.5;
|
|
1885
|
+
}
|
|
1886
|
+
|
|
1887
|
+
.explanation-step.active .explanation-step-desc {
|
|
1888
|
+
color: #aaa;
|
|
1889
|
+
}
|
|
1890
|
+
|
|
1891
|
+
.explanation-step-why {
|
|
1892
|
+
margin-top: 8px;
|
|
1893
|
+
padding-top: 8px;
|
|
1894
|
+
border-top: 1px dashed var(--border-color);
|
|
1895
|
+
font-size: 0.75rem;
|
|
1896
|
+
color: var(--claude-orange);
|
|
1897
|
+
font-style: italic;
|
|
1898
|
+
}
|
|
1899
|
+
|
|
1900
|
+
@media (max-width: 1000px) {
|
|
1901
|
+
.claude-code-container {
|
|
1902
|
+
flex-direction: column;
|
|
1903
|
+
}
|
|
1904
|
+
.explanation-panel {
|
|
1905
|
+
min-width: unset;
|
|
1906
|
+
}
|
|
1907
|
+
}
|
|
1908
|
+
|
|
1424
1909
|
/* ============================================
|
|
1425
1910
|
SECTION 8: STATE FILE - boxy JSON viewer
|
|
1426
1911
|
============================================ */
|
|
@@ -1507,14 +1992,11 @@
|
|
|
1507
1992
|
.install-icon {
|
|
1508
1993
|
width: 50px;
|
|
1509
1994
|
height: 50px;
|
|
1510
|
-
border: 2px solid var(--accent-red);
|
|
1511
|
-
background: transparent;
|
|
1512
1995
|
display: flex;
|
|
1513
1996
|
align-items: center;
|
|
1514
1997
|
justify-content: center;
|
|
1515
1998
|
flex-shrink: 0;
|
|
1516
|
-
font-size: 1.
|
|
1517
|
-
color: var(--accent-red);
|
|
1999
|
+
font-size: 1.8rem;
|
|
1518
2000
|
}
|
|
1519
2001
|
|
|
1520
2002
|
.install-content {
|
|
@@ -1522,8 +2004,9 @@
|
|
|
1522
2004
|
}
|
|
1523
2005
|
|
|
1524
2006
|
.install-from {
|
|
1525
|
-
color: var(--
|
|
1526
|
-
font-size:
|
|
2007
|
+
color: var(--white);
|
|
2008
|
+
font-size: 1rem;
|
|
2009
|
+
font-weight: 500;
|
|
1527
2010
|
}
|
|
1528
2011
|
|
|
1529
2012
|
.install-arrow {
|
|
@@ -1537,6 +2020,9 @@
|
|
|
1537
2020
|
color: var(--white);
|
|
1538
2021
|
font-size: 0.9rem;
|
|
1539
2022
|
font-weight: 500;
|
|
2023
|
+
min-width: 180px;
|
|
2024
|
+
text-align: right;
|
|
2025
|
+
font-family: 'JetBrains Mono', 'SF Mono', monospace;
|
|
1540
2026
|
}
|
|
1541
2027
|
|
|
1542
2028
|
.install-note {
|
|
@@ -1851,63 +2337,52 @@
|
|
|
1851
2337
|
<section id="problems">
|
|
1852
2338
|
<div class="ascii-border">
|
|
1853
2339
|
<h2>THE PROBLEM</h2>
|
|
1854
|
-
<h3>
|
|
2340
|
+
<h3>LLMs Make Their Own Decisions</h3>
|
|
1855
2341
|
|
|
1856
2342
|
<div class="explanation">
|
|
1857
2343
|
<div class="explanation-title">Why This Matters</div>
|
|
1858
2344
|
<p>
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
or claim tasks are complete without actually verifying them.
|
|
1862
|
-
</p>
|
|
1863
|
-
<p>
|
|
1864
|
-
These are the <strong>5 most common gaps</strong> we've identified - and the problems they cause:
|
|
2345
|
+
LLMs are powerful but <strong>ungrounded</strong>. Without structure, they default to training data,
|
|
2346
|
+
make assumptions, and forget context. These are the <strong>3 critical gaps</strong> that compound:
|
|
1865
2347
|
</p>
|
|
1866
2348
|
</div>
|
|
1867
2349
|
|
|
1868
2350
|
<ul class="gap-list">
|
|
1869
2351
|
<li class="gap-item">
|
|
1870
|
-
<span class="gap-
|
|
1871
|
-
<div class="gap-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
<
|
|
1875
|
-
<
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
<span class="gap-number">Gap 02</span>
|
|
1881
|
-
<div class="gap-title">No Proof Files Were Actually Changed</div>
|
|
1882
|
-
<div class="gap-desc">AI says "I updated all the files" but never runs git diff to prove it.</div>
|
|
1883
|
-
<div class="gap-example">
|
|
1884
|
-
AI: "Migration complete! All 6 files updated."<br>
|
|
1885
|
-
Reality: Only 4 files were changed, 2 were missed.
|
|
2352
|
+
<span class="gap-icon">🔍</span>
|
|
2353
|
+
<div class="gap-content">
|
|
2354
|
+
<span class="gap-number">Gap 01</span>
|
|
2355
|
+
<div class="gap-title">AI Doesn't Use Your Exact Words</div>
|
|
2356
|
+
<div class="gap-desc">You say one thing, but the AI searches for something different. Wrong library. Wrong documentation.</div>
|
|
2357
|
+
<div class="gap-example">
|
|
2358
|
+
<span class="bad">You: "Use Brandfetch API"</span><br>
|
|
2359
|
+
<span class="bad">AI searches: "brand fetch library" (wrong!)</span><br>
|
|
2360
|
+
<span class="good">Solution: Phase 0 disambiguation before research</span>
|
|
2361
|
+
</div>
|
|
1886
2362
|
</div>
|
|
1887
2363
|
</li>
|
|
1888
2364
|
<li class="gap-item">
|
|
1889
|
-
<span class="gap-
|
|
1890
|
-
<div class="gap-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
2365
|
+
<span class="gap-icon">🧠</span>
|
|
2366
|
+
<div class="gap-content">
|
|
2367
|
+
<span class="gap-number">Gap 02</span>
|
|
2368
|
+
<div class="gap-title">Memory-Based Implementation</div>
|
|
2369
|
+
<div class="gap-desc">After research, the AI forgets what it learned and implements from training data instead.</div>
|
|
2370
|
+
<div class="gap-example">
|
|
2371
|
+
AI researches Brandfetch v2 API, then implements v1 patterns from memory.<br>
|
|
2372
|
+
<span class="good">Solution: Phase 9 verification re-reads docs after implementation</span>
|
|
2373
|
+
</div>
|
|
1894
2374
|
</div>
|
|
1895
2375
|
</li>
|
|
1896
2376
|
<li class="gap-item">
|
|
1897
|
-
<span class="gap-
|
|
1898
|
-
<div class="gap-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
<div class="gap-title">Tests Don't Match Production Code</div>
|
|
1907
|
-
<div class="gap-desc">Production code uses new patterns, but tests still check old patterns.</div>
|
|
1908
|
-
<div class="gap-example">
|
|
1909
|
-
<span class="bad">Production: AI_GATEWAY_API_KEY</span><br>
|
|
1910
|
-
<span class="bad">Tests: OPENAI_API_KEY (outdated!)</span>
|
|
2377
|
+
<span class="gap-icon">💨</span>
|
|
2378
|
+
<div class="gap-content">
|
|
2379
|
+
<span class="gap-number">Gap 03</span>
|
|
2380
|
+
<div class="gap-title">Context Dilution</div>
|
|
2381
|
+
<div class="gap-desc">After many turns, the AI forgets project structure, documentation locations, and your decisions.</div>
|
|
2382
|
+
<div class="gap-example">
|
|
2383
|
+
Turn 50: "What API key should I use?" (you already told it 40 turns ago)<br>
|
|
2384
|
+
<span class="good">Solution: Re-grounding every 7 turns via hooks</span>
|
|
2385
|
+
</div>
|
|
1911
2386
|
</div>
|
|
1912
2387
|
</li>
|
|
1913
2388
|
</ul>
|
|
@@ -1936,7 +2411,7 @@
|
|
|
1936
2411
|
|
|
1937
2412
|
<div class="solution-grid">
|
|
1938
2413
|
<div class="solution-card">
|
|
1939
|
-
<span class="solution-icon"
|
|
2414
|
+
<span class="solution-icon">📚</span>
|
|
1940
2415
|
<div class="solution-title">Research First</div>
|
|
1941
2416
|
<div class="solution-desc">
|
|
1942
2417
|
AI must search for live documentation before writing any code.
|
|
@@ -1944,7 +2419,7 @@
|
|
|
1944
2419
|
</div>
|
|
1945
2420
|
</div>
|
|
1946
2421
|
<div class="solution-card">
|
|
1947
|
-
<span class="solution-icon"
|
|
2422
|
+
<span class="solution-icon">💬</span>
|
|
1948
2423
|
<div class="solution-title">Interview Required</div>
|
|
1949
2424
|
<div class="solution-desc">
|
|
1950
2425
|
AI must ask YOU questions and wait for answers.
|
|
@@ -1952,7 +2427,7 @@
|
|
|
1952
2427
|
</div>
|
|
1953
2428
|
</div>
|
|
1954
2429
|
<div class="solution-card">
|
|
1955
|
-
<span class="solution-icon"
|
|
2430
|
+
<span class="solution-icon">✅</span>
|
|
1956
2431
|
<div class="solution-title">Verification Built-In</div>
|
|
1957
2432
|
<div class="solution-desc">
|
|
1958
2433
|
System checks implementation matches interview.
|
|
@@ -2038,17 +2513,24 @@
|
|
|
2038
2513
|
<section id="phases">
|
|
2039
2514
|
<div class="ascii-border">
|
|
2040
2515
|
<h2>THE WORKFLOW</h2>
|
|
2041
|
-
<h3>
|
|
2516
|
+
<h3>12 Enforced Phases (v3.0)</h3>
|
|
2042
2517
|
|
|
2043
2518
|
<div class="explanation">
|
|
2044
2519
|
<div class="explanation-title">The Complete Process</div>
|
|
2045
2520
|
<p>
|
|
2046
|
-
Every API goes through these
|
|
2047
|
-
the AI skip ahead.
|
|
2521
|
+
Every API goes through these 12 phases. The system tracks progress and won't let
|
|
2522
|
+
the AI skip ahead. <strong>Phase 0 (Disambiguation)</strong> and <strong>Phase 9 (Verify)</strong> are new in v3.0!
|
|
2048
2523
|
</p>
|
|
2049
2524
|
</div>
|
|
2050
2525
|
|
|
2051
2526
|
<div class="phase-grid">
|
|
2527
|
+
<div class="phase-box glow-border" data-phase="0">
|
|
2528
|
+
<div class="phase-status"></div>
|
|
2529
|
+
<div class="phase-number">00</div>
|
|
2530
|
+
<div class="phase-name">Disambiguate</div>
|
|
2531
|
+
<div class="phase-desc">Clarify ambiguous terms</div>
|
|
2532
|
+
<span class="phase-arrow">→</span>
|
|
2533
|
+
</div>
|
|
2052
2534
|
<div class="phase-box glow-border" data-phase="1">
|
|
2053
2535
|
<div class="phase-status"></div>
|
|
2054
2536
|
<div class="phase-number">01</div>
|
|
@@ -2067,14 +2549,14 @@
|
|
|
2067
2549
|
<div class="phase-status"></div>
|
|
2068
2550
|
<div class="phase-number">03</div>
|
|
2069
2551
|
<div class="phase-name">Interview</div>
|
|
2070
|
-
<div class="phase-desc">
|
|
2552
|
+
<div class="phase-desc">Questions FROM research</div>
|
|
2071
2553
|
<span class="phase-arrow">→</span>
|
|
2072
2554
|
</div>
|
|
2073
2555
|
<div class="phase-box glow-border" data-phase="4">
|
|
2074
2556
|
<div class="phase-status"></div>
|
|
2075
2557
|
<div class="phase-number">04</div>
|
|
2076
2558
|
<div class="phase-name">Deep Research</div>
|
|
2077
|
-
<div class="phase-desc">
|
|
2559
|
+
<div class="phase-desc">Adaptive, not shotgun</div>
|
|
2078
2560
|
<span class="phase-arrow">→</span>
|
|
2079
2561
|
</div>
|
|
2080
2562
|
<div class="phase-box glow-border" data-phase="5">
|
|
@@ -2107,275 +2589,740 @@
|
|
|
2107
2589
|
<div class="phase-desc">Make tests pass</div>
|
|
2108
2590
|
<span class="phase-arrow">→</span>
|
|
2109
2591
|
</div>
|
|
2110
|
-
<div class="phase-box glow-border" data-phase="9">
|
|
2592
|
+
<div class="phase-box glow-border" data-phase="9" style="border-color: var(--claude-orange);">
|
|
2111
2593
|
<div class="phase-status"></div>
|
|
2112
2594
|
<div class="phase-number">09</div>
|
|
2113
|
-
<div class="phase-name">
|
|
2114
|
-
<div class="phase-desc">
|
|
2595
|
+
<div class="phase-name">Verify</div>
|
|
2596
|
+
<div class="phase-desc">Re-research, find gaps</div>
|
|
2115
2597
|
<span class="phase-arrow">→</span>
|
|
2116
2598
|
</div>
|
|
2117
2599
|
<div class="phase-box glow-border" data-phase="10">
|
|
2118
2600
|
<div class="phase-status"></div>
|
|
2119
2601
|
<div class="phase-number">10</div>
|
|
2602
|
+
<div class="phase-name">Refactor</div>
|
|
2603
|
+
<div class="phase-desc">Clean up the code</div>
|
|
2604
|
+
<span class="phase-arrow">→</span>
|
|
2605
|
+
</div>
|
|
2606
|
+
<div class="phase-box glow-border" data-phase="11">
|
|
2607
|
+
<div class="phase-status"></div>
|
|
2608
|
+
<div class="phase-number">11</div>
|
|
2120
2609
|
<div class="phase-name">Documentation</div>
|
|
2121
2610
|
<div class="phase-desc">Update all docs</div>
|
|
2611
|
+
<span class="phase-arrow">→</span>
|
|
2122
2612
|
</div>
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
SECTION 6: REAL EXAMPLE WALKTHROUGH
|
|
2129
|
-
============================================ -->
|
|
2130
|
-
<section id="walkthrough">
|
|
2131
|
-
<div class="ascii-border">
|
|
2132
|
-
<h2>REAL EXAMPLE</h2>
|
|
2133
|
-
<h3>Creating a Brandfetch API</h3>
|
|
2134
|
-
|
|
2135
|
-
<div class="explanation">
|
|
2136
|
-
<div class="explanation-title">The Complete Flow</div>
|
|
2137
|
-
<p>
|
|
2138
|
-
Let's walk through what happens when you run <code>/api-create brandfetch</code>.
|
|
2139
|
-
This shows the full interview-driven workflow, from research to implementation,
|
|
2140
|
-
with <strong>structured questions based on real documentation</strong>.
|
|
2141
|
-
</p>
|
|
2142
|
-
</div>
|
|
2143
|
-
|
|
2144
|
-
<div class="walkthrough-step">
|
|
2145
|
-
<div class="walkthrough-header">
|
|
2146
|
-
<div class="walkthrough-num">1</div>
|
|
2147
|
-
<div class="walkthrough-title">You Run the Command</div>
|
|
2148
|
-
</div>
|
|
2149
|
-
<div class="walkthrough-content">
|
|
2150
|
-
<div class="walkthrough-desc">
|
|
2151
|
-
You type the command to create a new Brandfetch API endpoint.
|
|
2152
|
-
The workflow immediately begins.
|
|
2153
|
-
</div>
|
|
2154
|
-
<div class="walkthrough-example">
|
|
2155
|
-
<div class="label">Your Command:</div>
|
|
2156
|
-
/api-create brandfetch
|
|
2157
|
-
</div>
|
|
2158
|
-
</div>
|
|
2159
|
-
</div>
|
|
2160
|
-
|
|
2161
|
-
<div class="walkthrough-step">
|
|
2162
|
-
<div class="walkthrough-header">
|
|
2163
|
-
<div class="walkthrough-num">2</div>
|
|
2164
|
-
<div class="walkthrough-title">Research Phase (Automatic)</div>
|
|
2165
|
-
</div>
|
|
2166
|
-
<div class="walkthrough-content">
|
|
2167
|
-
<div class="walkthrough-desc">
|
|
2168
|
-
Before asking any questions, the AI is <strong>required</strong> to research.
|
|
2169
|
-
It fetches live documentation from Context7 and searches the web.
|
|
2170
|
-
</div>
|
|
2171
|
-
<div class="walkthrough-example">
|
|
2172
|
-
<div class="label">Research Logged to State File:</div>
|
|
2173
|
-
- Context7: Brandfetch SDK docs → found logos, colors, fonts endpoints<br>
|
|
2174
|
-
- WebSearch: "Brandfetch API rate limits 2025" → 5 req/second<br>
|
|
2175
|
-
- WebSearch: "Brandfetch API response format" → JSON with asset URLs<br>
|
|
2176
|
-
- Context7: Authentication → Bearer token required
|
|
2177
|
-
</div>
|
|
2178
|
-
</div>
|
|
2179
|
-
</div>
|
|
2180
|
-
|
|
2181
|
-
<div class="walkthrough-step">
|
|
2182
|
-
<div class="walkthrough-header">
|
|
2183
|
-
<div class="walkthrough-num">3</div>
|
|
2184
|
-
<div class="walkthrough-title">Structured Interview (Based on Research)</div>
|
|
2185
|
-
</div>
|
|
2186
|
-
<div class="walkthrough-content">
|
|
2187
|
-
<div class="walkthrough-desc">
|
|
2188
|
-
Now the AI asks YOU questions - but with <strong>multiple-choice options</strong>
|
|
2189
|
-
derived from what it actually found in the documentation. No guessing!
|
|
2190
|
-
</div>
|
|
2191
|
-
<div class="walkthrough-example">
|
|
2192
|
-
<div class="label">Question 1 (with options from research):</div>
|
|
2193
|
-
"What's the primary purpose of this endpoint?"<br><br>
|
|
2194
|
-
<strong>1.</strong> Brand lookup (get brand by domain)<br>
|
|
2195
|
-
<strong>2.</strong> Logo extraction (get logo assets)<br>
|
|
2196
|
-
<strong>3.</strong> Color palette extraction<br>
|
|
2197
|
-
<strong>4.</strong> Full brand kit (all assets)<br>
|
|
2198
|
-
<strong>5.</strong> Type something else...<br><br>
|
|
2199
|
-
<em>You select: "4. Full brand kit (all assets)"</em>
|
|
2200
|
-
</div>
|
|
2201
|
-
</div>
|
|
2202
|
-
</div>
|
|
2203
|
-
|
|
2204
|
-
<div class="walkthrough-step">
|
|
2205
|
-
<div class="walkthrough-header">
|
|
2206
|
-
<div class="walkthrough-num">4</div>
|
|
2207
|
-
<div class="walkthrough-title">More Questions, All Tracked</div>
|
|
2208
|
-
</div>
|
|
2209
|
-
<div class="walkthrough-content">
|
|
2210
|
-
<div class="walkthrough-desc">
|
|
2211
|
-
Each question is tracked with your answer. These decisions are stored
|
|
2212
|
-
in the state file and <strong>injected during implementation</strong> to ensure consistency.
|
|
2213
|
-
</div>
|
|
2214
|
-
<div class="walkthrough-example">
|
|
2215
|
-
<div class="label">Decisions Captured:</div>
|
|
2216
|
-
• Purpose: full_brand_kit<br>
|
|
2217
|
-
• Response Format: JSON with asset URLs<br>
|
|
2218
|
-
• API Key Handling: server environment variables only<br>
|
|
2219
|
-
• Error Handling: detailed (error, code, details)<br>
|
|
2220
|
-
• Required Params: domain (string)<br>
|
|
2221
|
-
• Optional Params: include_colors, include_fonts
|
|
2222
|
-
</div>
|
|
2223
|
-
</div>
|
|
2224
|
-
</div>
|
|
2225
|
-
|
|
2226
|
-
<div class="walkthrough-step">
|
|
2227
|
-
<div class="walkthrough-header">
|
|
2228
|
-
<div class="walkthrough-num">5</div>
|
|
2229
|
-
<div class="walkthrough-title">Implementation (With Decision Reminders)</div>
|
|
2230
|
-
</div>
|
|
2231
|
-
<div class="walkthrough-content">
|
|
2232
|
-
<div class="walkthrough-desc">
|
|
2233
|
-
When the AI writes code, the hook <strong>injects your decisions</strong> as a reminder.
|
|
2234
|
-
This ensures the implementation matches what you actually asked for.
|
|
2235
|
-
</div>
|
|
2236
|
-
<div class="walkthrough-example">
|
|
2237
|
-
<div class="label">Injected on Every Write:</div>
|
|
2238
|
-
✅ Interview complete. REMEMBER THE USER'S DECISIONS:<br><br>
|
|
2239
|
-
• Purpose: Full brand kit (all assets)<br>
|
|
2240
|
-
• Response Format: JSON with asset URLs<br>
|
|
2241
|
-
• API Key Handling: server environment variables only<br>
|
|
2242
|
-
• Error Handling: detailed (error, code, details)<br><br>
|
|
2243
|
-
<em>Your implementation MUST align with these choices.</em>
|
|
2244
|
-
</div>
|
|
2245
|
-
</div>
|
|
2246
|
-
</div>
|
|
2247
|
-
|
|
2248
|
-
<div class="walkthrough-step">
|
|
2249
|
-
<div class="walkthrough-header">
|
|
2250
|
-
<div class="walkthrough-num">6</div>
|
|
2251
|
-
<div class="walkthrough-title">TDD + Final Result</div>
|
|
2252
|
-
</div>
|
|
2253
|
-
<div class="walkthrough-content">
|
|
2254
|
-
<div class="walkthrough-desc">
|
|
2255
|
-
Tests are written first (TDD), then implementation, then docs.
|
|
2256
|
-
Everything is tracked and verified against your interview decisions.
|
|
2257
|
-
</div>
|
|
2258
|
-
<div class="walkthrough-example">
|
|
2259
|
-
<div class="label">Files Created:</div>
|
|
2260
|
-
- src/lib/schemas/brandfetch.ts (Zod validation)<br>
|
|
2261
|
-
- src/lib/__tests__/brandfetch.test.ts (tests first!)<br>
|
|
2262
|
-
- src/app/api/v2/brandfetch/route.ts<br>
|
|
2263
|
-
- Interview doc: src/v2/docs/endpoints/brandfetch.md<br>
|
|
2264
|
-
- All tests passing ✓
|
|
2265
|
-
</div>
|
|
2613
|
+
<div class="phase-box glow-border" data-phase="12">
|
|
2614
|
+
<div class="phase-status"></div>
|
|
2615
|
+
<div class="phase-number">12</div>
|
|
2616
|
+
<div class="phase-name">Complete</div>
|
|
2617
|
+
<div class="phase-desc">Final verification</div>
|
|
2266
2618
|
</div>
|
|
2267
2619
|
</div>
|
|
2268
2620
|
</div>
|
|
2269
2621
|
</section>
|
|
2270
2622
|
|
|
2271
2623
|
<!-- ============================================
|
|
2272
|
-
SECTION
|
|
2624
|
+
SECTION 6: LIVE DEMO - CLAUDE CODE TERMINAL
|
|
2625
|
+
Full 12-phase v3.0 workflow simulation
|
|
2273
2626
|
============================================ -->
|
|
2274
2627
|
<section id="demo">
|
|
2275
|
-
<div class="ascii-border">
|
|
2628
|
+
<div class="ascii-border" style="max-width: 1400px;">
|
|
2276
2629
|
<h2>LIVE SIMULATION</h2>
|
|
2277
|
-
<h3>
|
|
2630
|
+
<h3>12-Phase Workflow (v3.0)</h3>
|
|
2278
2631
|
|
|
2279
2632
|
<div class="explanation">
|
|
2280
|
-
<div class="explanation-title">
|
|
2633
|
+
<div class="explanation-title">The Complete v3.0 Flow</div>
|
|
2281
2634
|
<p>
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2635
|
+
Watch the full <strong>/api-create brandfetch</strong> command in action.
|
|
2636
|
+
The side panel explains each step as it happens. Notice the AI/User conversation format
|
|
2637
|
+
and how research findings drive the interview questions.
|
|
2285
2638
|
</p>
|
|
2286
2639
|
</div>
|
|
2287
2640
|
|
|
2288
|
-
<div class="
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
<div class="
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2641
|
+
<div class="claude-code-container">
|
|
2642
|
+
<!-- Claude Code Terminal (Left) -->
|
|
2643
|
+
<div class="claude-code-terminal" id="claudeTerminal">
|
|
2644
|
+
<div class="claude-code-header">
|
|
2645
|
+
<div class="claude-code-dots">
|
|
2646
|
+
<div class="claude-code-dot red"></div>
|
|
2647
|
+
<div class="claude-code-dot yellow"></div>
|
|
2648
|
+
<div class="claude-code-dot green"></div>
|
|
2649
|
+
</div>
|
|
2650
|
+
<div class="claude-code-title">~/my-project</div>
|
|
2651
|
+
<div class="claude-code-badge">CLAUDE CODE</div>
|
|
2297
2652
|
</div>
|
|
2298
|
-
</div>
|
|
2299
|
-
|
|
2300
|
-
<div class="terminal-comment" data-step="0">// Step 1: Research phase starts automatically</div>
|
|
2301
|
-
<div class="terminal-line" data-step="1">
|
|
2302
|
-
<span class="terminal-prompt">claude></span>
|
|
2303
|
-
<span class="terminal-command">mcp__context7__get-library-docs("brandfetch")</span>
|
|
2304
|
-
</div>
|
|
2305
|
-
<div class="terminal-line terminal-result" data-step="2">
|
|
2306
|
-
<span class="terminal-logged">[LOGGED] Context7 source: brandfetch SDK documentation</span>
|
|
2307
|
-
</div>
|
|
2308
|
-
|
|
2309
|
-
<div class="terminal-line" data-step="3">
|
|
2310
|
-
<span class="terminal-prompt">claude></span>
|
|
2311
|
-
<span class="terminal-command">WebSearch "Brandfetch API endpoints 2025"</span>
|
|
2312
|
-
</div>
|
|
2313
|
-
<div class="terminal-line terminal-result" data-step="4">
|
|
2314
|
-
<span class="terminal-logged">[LOGGED] WebSearch: found /v2/brands, /v2/search, /v2/logos</span>
|
|
2315
|
-
</div>
|
|
2316
|
-
|
|
2317
|
-
<div class="terminal-comment" data-step="5">// Step 2: Interview with structured options (from research)</div>
|
|
2318
|
-
<div class="terminal-line" data-step="6">
|
|
2319
|
-
<span class="terminal-prompt">claude></span>
|
|
2320
|
-
<span class="terminal-command">AskUserQuestion(<br>
|
|
2321
|
-
question: "What's the primary purpose?"<br>
|
|
2322
|
-
options: [<br>
|
|
2323
|
-
{value: "lookup", label: "Brand lookup by domain"},<br>
|
|
2324
|
-
{value: "logos", label: "Logo extraction only"},<br>
|
|
2325
|
-
{value: "full_kit", label: "Full brand kit"},<br>
|
|
2326
|
-
{value: "custom", label: "Type something..."}<br>
|
|
2327
|
-
]<br>
|
|
2328
|
-
)</span>
|
|
2329
|
-
</div>
|
|
2330
|
-
<div class="terminal-line terminal-result" data-step="7">
|
|
2331
|
-
<span class="terminal-allowed">[USER] Selected: "full_kit"<br>[TRACKED] decisions.purpose = "full_kit"</span>
|
|
2332
|
-
</div>
|
|
2333
|
-
|
|
2334
|
-
<div class="terminal-line" data-step="8">
|
|
2335
|
-
<span class="terminal-prompt">claude></span>
|
|
2336
|
-
<span class="terminal-command">AskUserQuestion(<br>
|
|
2337
|
-
question: "How should API keys be handled?"<br>
|
|
2338
|
-
options: [<br>
|
|
2339
|
-
{value: "server_only", label: "Server env vars only"},<br>
|
|
2340
|
-
{value: "header", label: "Custom header override"},<br>
|
|
2341
|
-
{value: "both", label: "Both methods"},<br>
|
|
2342
|
-
]<br>
|
|
2343
|
-
)</span>
|
|
2344
|
-
</div>
|
|
2345
|
-
<div class="terminal-line terminal-result" data-step="9">
|
|
2346
|
-
<span class="terminal-allowed">[USER] Selected: "server_only"<br>[TRACKED] decisions.api_key_handling = "server_only"</span>
|
|
2347
|
-
</div>
|
|
2348
2653
|
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
|
|
2352
|
-
|
|
2353
|
-
|
|
2354
|
-
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
|
|
2654
|
+
<!-- ASCII Art Startup Screen -->
|
|
2655
|
+
<pre class="ascii-startup" id="asciiStartup">
|
|
2656
|
+
<span style="color: var(--claude-orange);">╭─────────────────────────────────────────────────────────────────────────────╮</span>
|
|
2657
|
+
<span style="color: var(--claude-orange);">│</span> <span style="color: var(--claude-orange);">│</span> <span class="tips-text">Tips for getting started</span> <span style="color: var(--claude-orange);">│</span>
|
|
2658
|
+
<span style="color: var(--claude-orange);">│</span> <span class="welcome-text">Welcome back, Developer!</span> <span style="color: var(--claude-orange);">│</span> <span class="tips-text">Run /init to create a CLAUDE.md file...</span> <span style="color: var(--claude-orange);">│</span>
|
|
2659
|
+
<span style="color: var(--claude-orange);">│</span> <span style="color: var(--claude-orange);">│</span> <span class="tips-text">Try /api-create to start a new endpoint</span> <span style="color: var(--claude-orange);">│</span>
|
|
2660
|
+
<span style="color: var(--claude-orange);">│</span> <span style="color: var(--claude-orange);">▗ ▗ ▖ ▖</span> <span style="color: var(--claude-orange);">│</span> <span class="tips-text">────────────────────────────────────────</span> <span style="color: var(--claude-orange);">│</span>
|
|
2661
|
+
<span style="color: var(--claude-orange);">│</span> <span style="color: var(--claude-orange);">│</span> <span class="tips-text">Recent activity</span> <span style="color: var(--claude-orange);">│</span>
|
|
2662
|
+
<span style="color: var(--claude-orange);">│</span> <span style="color: var(--claude-orange);">▘▘ ▝▝</span> <span style="color: var(--claude-orange);">│</span> <span class="tips-text"> api/v2/search - completed</span> <span style="color: var(--claude-orange);">│</span>
|
|
2663
|
+
<span style="color: var(--claude-orange);">│</span> <span style="color: var(--claude-orange);">│</span> <span class="tips-text"> api/v2/analyze - 8 tests passing</span> <span style="color: var(--claude-orange);">│</span>
|
|
2664
|
+
<span style="color: var(--claude-orange);">│</span> <span class="model-text">Opus 4.5 · Claude Max</span> <span style="color: var(--claude-orange);">│</span> <span style="color: var(--claude-orange);">│</span>
|
|
2665
|
+
<span style="color: var(--claude-orange);">│</span> <span class="path-text">~/my-project</span> <span style="color: var(--claude-orange);">│</span> <span style="color: var(--claude-orange);">│</span>
|
|
2666
|
+
<span style="color: var(--claude-orange);">╰─────────────────────────────────────────────────────────────────────────────╯</span>
|
|
2667
|
+
</pre>
|
|
2668
|
+
|
|
2669
|
+
<!-- Prompt Line (shows before messages) -->
|
|
2670
|
+
<div class="claude-prompt-line" id="promptLine">
|
|
2671
|
+
<span class="claude-prompt">❯</span>
|
|
2672
|
+
<span class="claude-input" id="promptInput"></span>
|
|
2673
|
+
<span class="claude-cursor"></span>
|
|
2674
|
+
</div>
|
|
2360
2675
|
|
|
2361
|
-
|
|
2362
|
-
|
|
2363
|
-
|
|
2364
|
-
|
|
2365
|
-
|
|
2366
|
-
|
|
2367
|
-
|
|
2368
|
-
|
|
2369
|
-
|
|
2370
|
-
|
|
2676
|
+
<div class="claude-code-body" id="claudeBody">
|
|
2677
|
+
<!-- Loading dots (shown between messages) -->
|
|
2678
|
+
<div class="loading-dots" id="loadingDots" style="display: none;">
|
|
2679
|
+
<span></span><span></span><span></span>
|
|
2680
|
+
</div>
|
|
2681
|
+
|
|
2682
|
+
<!-- Phase 0: User Command -->
|
|
2683
|
+
<div class="claude-msg" data-phase="0" data-step="0">
|
|
2684
|
+
<div class="claude-msg-role user">
|
|
2685
|
+
<span class="claude-msg-icon">👤</span>
|
|
2686
|
+
<span class="claude-msg-name">USER</span>
|
|
2687
|
+
</div>
|
|
2688
|
+
<div class="claude-msg-content">
|
|
2689
|
+
<code>/api-create brandfetch</code>
|
|
2690
|
+
</div>
|
|
2691
|
+
</div>
|
|
2692
|
+
|
|
2693
|
+
<!-- Phase 1: Scope Confirmation -->
|
|
2694
|
+
<div class="claude-msg" data-phase="1" data-step="1">
|
|
2695
|
+
<div class="claude-msg-role ai">
|
|
2696
|
+
<span class="claude-msg-icon">🤖</span>
|
|
2697
|
+
<span class="claude-msg-name">CLAUDE</span>
|
|
2698
|
+
</div>
|
|
2699
|
+
<div class="claude-msg-content">
|
|
2700
|
+
I understand you want to create an API endpoint for <strong>Brandfetch</strong> - a service for fetching brand assets (logos, colors, fonts) by domain.
|
|
2701
|
+
<br><br>Is this correct? <span style="color: #22c55e;">✓ Yes</span>
|
|
2702
|
+
</div>
|
|
2703
|
+
</div>
|
|
2704
|
+
|
|
2705
|
+
<!-- Phase 2: Initial Research -->
|
|
2706
|
+
<div class="claude-msg" data-phase="2" data-step="2">
|
|
2707
|
+
<div class="claude-msg-role ai">
|
|
2708
|
+
<span class="claude-msg-icon">🤖</span>
|
|
2709
|
+
<span class="claude-msg-name">CLAUDE</span>
|
|
2710
|
+
</div>
|
|
2711
|
+
<div class="claude-msg-content">
|
|
2712
|
+
Starting research... I need to find the real documentation before asking questions.
|
|
2713
|
+
<div class="claude-tool-call">
|
|
2714
|
+
<div class="claude-tool-name">mcp__context7__get-library-docs</div>
|
|
2715
|
+
<div class="claude-tool-result">"brandfetch" → Found SDK docs, /v2/brands endpoint, auth method</div>
|
|
2716
|
+
</div>
|
|
2717
|
+
<div class="claude-tool-call">
|
|
2718
|
+
<div class="claude-tool-name">WebSearch</div>
|
|
2719
|
+
<div class="claude-tool-result">"Brandfetch API rate limits 2025" → 5 req/second</div>
|
|
2720
|
+
</div>
|
|
2721
|
+
</div>
|
|
2722
|
+
</div>
|
|
2723
|
+
|
|
2724
|
+
<!-- User Loop-back: Request more research -->
|
|
2725
|
+
<div class="claude-msg loop-back" data-phase="2" data-step="3">
|
|
2726
|
+
<div class="claude-msg-role user">
|
|
2727
|
+
<span class="claude-msg-icon">👤</span>
|
|
2728
|
+
<span class="claude-msg-name">USER</span>
|
|
2729
|
+
</div>
|
|
2730
|
+
<div class="claude-msg-content">
|
|
2731
|
+
<span class="loop-back-badge">↩ LOOP BACK</span>
|
|
2732
|
+
Can you also check what error responses look like?
|
|
2733
|
+
</div>
|
|
2734
|
+
</div>
|
|
2735
|
+
|
|
2736
|
+
<div class="claude-msg" data-phase="2" data-step="4">
|
|
2737
|
+
<div class="claude-msg-role ai">
|
|
2738
|
+
<span class="claude-msg-icon">🤖</span>
|
|
2739
|
+
<span class="claude-msg-name">CLAUDE</span>
|
|
2740
|
+
</div>
|
|
2741
|
+
<div class="claude-msg-content">
|
|
2742
|
+
Good catch! Researching error handling...
|
|
2743
|
+
<div class="claude-tool-call">
|
|
2744
|
+
<div class="claude-tool-name">WebSearch</div>
|
|
2745
|
+
<div class="claude-tool-result">"Brandfetch API error codes" → 401, 404, 429 with JSON error format</div>
|
|
2746
|
+
</div>
|
|
2747
|
+
</div>
|
|
2748
|
+
</div>
|
|
2749
|
+
|
|
2750
|
+
<!-- Phase 3: Interview (Extensive - 5+ questions) -->
|
|
2751
|
+
<div class="claude-msg" data-phase="3" data-step="5">
|
|
2752
|
+
<div class="claude-msg-role ai">
|
|
2753
|
+
<span class="claude-msg-icon">🤖</span>
|
|
2754
|
+
<span class="claude-msg-name">CLAUDE</span>
|
|
2755
|
+
</div>
|
|
2756
|
+
<div class="claude-msg-content">
|
|
2757
|
+
Based on my research, I found these capabilities. <strong>Question 1/5:</strong> What's the primary purpose?
|
|
2758
|
+
<div class="claude-user-choice">
|
|
2759
|
+
<div class="claude-choice-option">
|
|
2760
|
+
<div class="claude-choice-marker"></div>
|
|
2761
|
+
<span>Brand lookup by domain</span>
|
|
2762
|
+
</div>
|
|
2763
|
+
<div class="claude-choice-option">
|
|
2764
|
+
<div class="claude-choice-marker"></div>
|
|
2765
|
+
<span>Logo extraction only</span>
|
|
2766
|
+
</div>
|
|
2767
|
+
<div class="claude-choice-option selected">
|
|
2768
|
+
<div class="claude-choice-marker"></div>
|
|
2769
|
+
<span>Full brand kit (logos, colors, fonts)</span>
|
|
2770
|
+
</div>
|
|
2771
|
+
</div>
|
|
2772
|
+
</div>
|
|
2773
|
+
</div>
|
|
2774
|
+
|
|
2775
|
+
<div class="claude-msg" data-phase="3" data-step="6">
|
|
2776
|
+
<div class="claude-msg-role user">
|
|
2777
|
+
<span class="claude-msg-icon">👤</span>
|
|
2778
|
+
<span class="claude-msg-name">USER</span>
|
|
2779
|
+
</div>
|
|
2780
|
+
<div class="claude-msg-content">
|
|
2781
|
+
<span style="color: #3b82f6;">Selected: Full brand kit (logos, colors, fonts)</span>
|
|
2782
|
+
</div>
|
|
2783
|
+
</div>
|
|
2784
|
+
|
|
2785
|
+
<div class="claude-msg" data-phase="3" data-step="7">
|
|
2786
|
+
<div class="claude-msg-role ai">
|
|
2787
|
+
<span class="claude-msg-icon">🤖</span>
|
|
2788
|
+
<span class="claude-msg-name">CLAUDE</span>
|
|
2789
|
+
</div>
|
|
2790
|
+
<div class="claude-msg-content">
|
|
2791
|
+
<strong>Question 2/5:</strong> How should <strong>API keys</strong> be handled?
|
|
2792
|
+
<div class="claude-user-choice">
|
|
2793
|
+
<div class="claude-choice-option selected">
|
|
2794
|
+
<div class="claude-choice-marker"></div>
|
|
2795
|
+
<span>Server environment variables only</span>
|
|
2796
|
+
</div>
|
|
2797
|
+
<div class="claude-choice-option">
|
|
2798
|
+
<div class="claude-choice-marker"></div>
|
|
2799
|
+
<span>Custom header override (X-Brandfetch-Key)</span>
|
|
2800
|
+
</div>
|
|
2801
|
+
<div class="claude-choice-option">
|
|
2802
|
+
<div class="claude-choice-marker"></div>
|
|
2803
|
+
<span>Both methods</span>
|
|
2804
|
+
</div>
|
|
2805
|
+
</div>
|
|
2806
|
+
</div>
|
|
2807
|
+
</div>
|
|
2808
|
+
|
|
2809
|
+
<div class="claude-msg" data-phase="3" data-step="8">
|
|
2810
|
+
<div class="claude-msg-role user">
|
|
2811
|
+
<span class="claude-msg-icon">👤</span>
|
|
2812
|
+
<span class="claude-msg-name">USER</span>
|
|
2813
|
+
</div>
|
|
2814
|
+
<div class="claude-msg-content">
|
|
2815
|
+
<span style="color: #3b82f6;">Selected: Server environment variables only</span>
|
|
2816
|
+
</div>
|
|
2817
|
+
</div>
|
|
2818
|
+
|
|
2819
|
+
<div class="claude-msg" data-phase="3" data-step="9">
|
|
2820
|
+
<div class="claude-msg-role ai">
|
|
2821
|
+
<span class="claude-msg-icon">🤖</span>
|
|
2822
|
+
<span class="claude-msg-name">CLAUDE</span>
|
|
2823
|
+
</div>
|
|
2824
|
+
<div class="claude-msg-content">
|
|
2825
|
+
<strong>Question 3/5:</strong> What <strong>caching strategy</strong> should we use?
|
|
2826
|
+
<div class="claude-user-choice">
|
|
2827
|
+
<div class="claude-choice-option">
|
|
2828
|
+
<div class="claude-choice-marker"></div>
|
|
2829
|
+
<span>No caching</span>
|
|
2830
|
+
</div>
|
|
2831
|
+
<div class="claude-choice-option">
|
|
2832
|
+
<div class="claude-choice-marker"></div>
|
|
2833
|
+
<span>Short cache (5 minutes)</span>
|
|
2834
|
+
</div>
|
|
2835
|
+
<div class="claude-choice-option selected">
|
|
2836
|
+
<div class="claude-choice-marker"></div>
|
|
2837
|
+
<span>Long cache (24 hours) - brands rarely change</span>
|
|
2838
|
+
</div>
|
|
2839
|
+
</div>
|
|
2840
|
+
</div>
|
|
2841
|
+
</div>
|
|
2842
|
+
|
|
2843
|
+
<div class="claude-msg" data-phase="3" data-step="10">
|
|
2844
|
+
<div class="claude-msg-role user">
|
|
2845
|
+
<span class="claude-msg-icon">👤</span>
|
|
2846
|
+
<span class="claude-msg-name">USER</span>
|
|
2847
|
+
</div>
|
|
2848
|
+
<div class="claude-msg-content">
|
|
2849
|
+
<span style="color: #3b82f6;">Selected: Long cache (24 hours)</span>
|
|
2850
|
+
</div>
|
|
2851
|
+
</div>
|
|
2852
|
+
|
|
2853
|
+
<div class="claude-msg" data-phase="3" data-step="11">
|
|
2854
|
+
<div class="claude-msg-role ai">
|
|
2855
|
+
<span class="claude-msg-icon">🤖</span>
|
|
2856
|
+
<span class="claude-msg-name">CLAUDE</span>
|
|
2857
|
+
</div>
|
|
2858
|
+
<div class="claude-msg-content">
|
|
2859
|
+
<strong>Question 4/5:</strong> How should we handle <strong>errors</strong>?
|
|
2860
|
+
<div class="claude-user-choice">
|
|
2861
|
+
<div class="claude-choice-option">
|
|
2862
|
+
<div class="claude-choice-marker"></div>
|
|
2863
|
+
<span>Throw exceptions (let caller handle)</span>
|
|
2864
|
+
</div>
|
|
2865
|
+
<div class="claude-choice-option selected">
|
|
2866
|
+
<div class="claude-choice-marker"></div>
|
|
2867
|
+
<span>Return error objects with status codes</span>
|
|
2868
|
+
</div>
|
|
2869
|
+
<div class="claude-choice-option">
|
|
2870
|
+
<div class="claude-choice-marker"></div>
|
|
2871
|
+
<span>Fallback to empty brand object</span>
|
|
2872
|
+
</div>
|
|
2873
|
+
</div>
|
|
2874
|
+
</div>
|
|
2875
|
+
</div>
|
|
2876
|
+
|
|
2877
|
+
<div class="claude-msg" data-phase="3" data-step="12">
|
|
2878
|
+
<div class="claude-msg-role user">
|
|
2879
|
+
<span class="claude-msg-icon">👤</span>
|
|
2880
|
+
<span class="claude-msg-name">USER</span>
|
|
2881
|
+
</div>
|
|
2882
|
+
<div class="claude-msg-content">
|
|
2883
|
+
<span style="color: #3b82f6;">Selected: Return error objects with status codes</span>
|
|
2884
|
+
</div>
|
|
2885
|
+
</div>
|
|
2886
|
+
|
|
2887
|
+
<div class="claude-msg" data-phase="3" data-step="13">
|
|
2888
|
+
<div class="claude-msg-role ai">
|
|
2889
|
+
<span class="claude-msg-icon">🤖</span>
|
|
2890
|
+
<span class="claude-msg-name">CLAUDE</span>
|
|
2891
|
+
</div>
|
|
2892
|
+
<div class="claude-msg-content">
|
|
2893
|
+
<strong>Question 5/5:</strong> Should we expose <strong>rate limit headers</strong>?
|
|
2894
|
+
<div class="claude-user-choice">
|
|
2895
|
+
<div class="claude-choice-option">
|
|
2896
|
+
<div class="claude-choice-marker"></div>
|
|
2897
|
+
<span>No - handle internally</span>
|
|
2898
|
+
</div>
|
|
2899
|
+
<div class="claude-choice-option selected">
|
|
2900
|
+
<div class="claude-choice-marker"></div>
|
|
2901
|
+
<span>Yes - X-RateLimit-Remaining, X-RateLimit-Reset</span>
|
|
2902
|
+
</div>
|
|
2903
|
+
</div>
|
|
2904
|
+
</div>
|
|
2905
|
+
</div>
|
|
2906
|
+
|
|
2907
|
+
<div class="claude-msg" data-phase="3" data-step="14">
|
|
2908
|
+
<div class="claude-msg-role user">
|
|
2909
|
+
<span class="claude-msg-icon">👤</span>
|
|
2910
|
+
<span class="claude-msg-name">USER</span>
|
|
2911
|
+
</div>
|
|
2912
|
+
<div class="claude-msg-content">
|
|
2913
|
+
<span style="color: #3b82f6;">Selected: Yes - expose rate limit headers</span>
|
|
2914
|
+
</div>
|
|
2915
|
+
</div>
|
|
2916
|
+
|
|
2917
|
+
<!-- Phase 4: Deep Research -->
|
|
2918
|
+
<div class="claude-msg" data-phase="4" data-step="15">
|
|
2919
|
+
<div class="claude-msg-role ai">
|
|
2920
|
+
<span class="claude-msg-icon">🤖</span>
|
|
2921
|
+
<span class="claude-msg-name">CLAUDE</span>
|
|
2922
|
+
</div>
|
|
2923
|
+
<div class="claude-msg-content">
|
|
2924
|
+
Based on your selections, I'll research more specifically:
|
|
2925
|
+
<div class="claude-tool-call">
|
|
2926
|
+
<div class="claude-tool-name">WebSearch</div>
|
|
2927
|
+
<div class="claude-tool-result">"Brandfetch full brand response format" → JSON with logos[], colors[], fonts[]</div>
|
|
2928
|
+
</div>
|
|
2929
|
+
<div class="claude-tool-call">
|
|
2930
|
+
<div class="claude-tool-name">WebSearch</div>
|
|
2931
|
+
<div class="claude-tool-result">"Brandfetch rate limit headers" → X-RateLimit-Limit, X-RateLimit-Remaining</div>
|
|
2932
|
+
</div>
|
|
2933
|
+
</div>
|
|
2934
|
+
</div>
|
|
2935
|
+
|
|
2936
|
+
<!-- Phase 5: Schema -->
|
|
2937
|
+
<div class="claude-msg" data-phase="5" data-step="16">
|
|
2938
|
+
<div class="claude-msg-role ai">
|
|
2939
|
+
<span class="claude-msg-icon">🤖</span>
|
|
2940
|
+
<span class="claude-msg-name">CLAUDE</span>
|
|
2941
|
+
</div>
|
|
2942
|
+
<div class="claude-msg-content">
|
|
2943
|
+
Creating Zod schema based on research + interview decisions...
|
|
2944
|
+
<div class="claude-tool-call">
|
|
2945
|
+
<div class="claude-tool-name">Write</div>
|
|
2946
|
+
<div class="claude-tool-result">src/lib/schemas/brandfetch.ts → BrandRequestSchema, BrandResponseSchema, BrandErrorSchema</div>
|
|
2947
|
+
</div>
|
|
2948
|
+
</div>
|
|
2949
|
+
</div>
|
|
2950
|
+
|
|
2951
|
+
<!-- Phase 6: Environment -->
|
|
2952
|
+
<div class="claude-msg" data-phase="6" data-step="17">
|
|
2953
|
+
<div class="claude-msg-role system">
|
|
2954
|
+
<span class="claude-msg-icon">⚙️</span>
|
|
2955
|
+
<span class="claude-msg-name">HOOK</span>
|
|
2956
|
+
</div>
|
|
2957
|
+
<div class="claude-msg-content">
|
|
2958
|
+
<strong style="color: var(--claude-orange);">check-env.py:</strong> Checking required environment variables...<br>
|
|
2959
|
+
<span style="color: #22c55e;">✓ BRANDFETCH_API_KEY found in .env.local</span>
|
|
2960
|
+
</div>
|
|
2961
|
+
</div>
|
|
2962
|
+
|
|
2963
|
+
<!-- Phase 7: TDD Red -->
|
|
2964
|
+
<div class="claude-msg" data-phase="7" data-step="18">
|
|
2965
|
+
<div class="claude-msg-role ai">
|
|
2966
|
+
<span class="claude-msg-icon">🤖</span>
|
|
2967
|
+
<span class="claude-msg-name">CLAUDE</span>
|
|
2968
|
+
</div>
|
|
2969
|
+
<div class="claude-msg-content">
|
|
2970
|
+
Writing failing tests first (TDD Red)...
|
|
2971
|
+
<div class="claude-tool-call">
|
|
2972
|
+
<div class="claude-tool-name">Write</div>
|
|
2973
|
+
<div class="claude-tool-result">src/lib/__tests__/brandfetch.test.ts (15 test cases)</div>
|
|
2974
|
+
</div>
|
|
2975
|
+
<div style="margin-top: 8px; color: #888; font-size: 0.85rem;">
|
|
2976
|
+
Tests cover: full brand kit, caching, error objects, rate limit headers
|
|
2977
|
+
</div>
|
|
2978
|
+
</div>
|
|
2979
|
+
</div>
|
|
2980
|
+
|
|
2981
|
+
<!-- Phase 8: TDD Green -->
|
|
2982
|
+
<div class="claude-msg" data-phase="8" data-step="19">
|
|
2983
|
+
<div class="claude-msg-role ai">
|
|
2984
|
+
<span class="claude-msg-icon">🤖</span>
|
|
2985
|
+
<span class="claude-msg-name">CLAUDE</span>
|
|
2986
|
+
</div>
|
|
2987
|
+
<div class="claude-msg-content">
|
|
2988
|
+
Implementing to pass tests...
|
|
2989
|
+
<div class="claude-tool-call">
|
|
2990
|
+
<div class="claude-tool-name">Write</div>
|
|
2991
|
+
<div class="claude-tool-result">src/app/api/v2/brandfetch/route.ts</div>
|
|
2992
|
+
</div>
|
|
2993
|
+
</div>
|
|
2994
|
+
</div>
|
|
2995
|
+
|
|
2996
|
+
<div class="claude-msg" data-phase="8" data-step="20">
|
|
2997
|
+
<div class="claude-msg-role system">
|
|
2998
|
+
<span class="claude-msg-icon">⚙️</span>
|
|
2999
|
+
<span class="claude-msg-name">HOOK</span>
|
|
3000
|
+
</div>
|
|
3001
|
+
<div class="claude-msg-content">
|
|
3002
|
+
<strong style="color: var(--claude-orange);">enforce-interview.py:</strong> REMEMBER USER DECISIONS:<br>
|
|
3003
|
+
• Purpose: full_brand_kit<br>
|
|
3004
|
+
• API Key Handling: server_only<br>
|
|
3005
|
+
• Caching: 24_hours<br>
|
|
3006
|
+
• Error Handling: return_error_objects<br>
|
|
3007
|
+
• Rate Limits: expose_headers
|
|
3008
|
+
</div>
|
|
3009
|
+
</div>
|
|
3010
|
+
|
|
3011
|
+
<div class="claude-msg" data-phase="8" data-step="21">
|
|
3012
|
+
<div class="claude-msg-role ai">
|
|
3013
|
+
<span class="claude-msg-icon">🤖</span>
|
|
3014
|
+
<span class="claude-msg-name">CLAUDE</span>
|
|
3015
|
+
</div>
|
|
3016
|
+
<div class="claude-msg-content">
|
|
3017
|
+
<span style="color: #22c55e;">✓ All 15 tests passing!</span>
|
|
3018
|
+
</div>
|
|
3019
|
+
</div>
|
|
3020
|
+
|
|
3021
|
+
<!-- Phase 9: Verify - GAP FOUND! -->
|
|
3022
|
+
<div class="claude-msg" data-phase="9" data-step="22">
|
|
3023
|
+
<div class="claude-msg-role ai">
|
|
3024
|
+
<span class="claude-msg-icon">🤖</span>
|
|
3025
|
+
<span class="claude-msg-name">CLAUDE</span>
|
|
3026
|
+
</div>
|
|
3027
|
+
<div class="claude-msg-content">
|
|
3028
|
+
Re-reading docs to verify implementation matches...
|
|
3029
|
+
<div class="claude-tool-call">
|
|
3030
|
+
<div class="claude-tool-name">mcp__context7__get-library-docs</div>
|
|
3031
|
+
<div class="claude-tool-result">"brandfetch" → Comparing implementation to docs...</div>
|
|
3032
|
+
</div>
|
|
3033
|
+
<div class="gap-found">
|
|
3034
|
+
<div class="gap-found-title">⚠️ GAP DETECTED</div>
|
|
3035
|
+
Missing <code>include_fonts</code> query parameter documented in v2 API
|
|
3036
|
+
</div>
|
|
3037
|
+
</div>
|
|
3038
|
+
</div>
|
|
3039
|
+
|
|
3040
|
+
<!-- Loop back to fix gap -->
|
|
3041
|
+
<div class="claude-msg loop-back" data-phase="9" data-step="23">
|
|
3042
|
+
<div class="claude-msg-role system">
|
|
3043
|
+
<span class="claude-msg-icon">🔄</span>
|
|
3044
|
+
<span class="claude-msg-name">HOOK</span>
|
|
3045
|
+
</div>
|
|
3046
|
+
<div class="claude-msg-content">
|
|
3047
|
+
<span class="loop-back-badge">↩ LOOP BACK TO PHASE 7</span>
|
|
3048
|
+
<strong style="color: var(--claude-orange);">verify-implementation.py:</strong> Gap found! Returning to TDD Red phase to add missing test...
|
|
3049
|
+
</div>
|
|
3050
|
+
</div>
|
|
3051
|
+
|
|
3052
|
+
<div class="claude-msg" data-phase="7" data-step="24">
|
|
3053
|
+
<div class="claude-msg-role ai">
|
|
3054
|
+
<span class="claude-msg-icon">🤖</span>
|
|
3055
|
+
<span class="claude-msg-name">CLAUDE</span>
|
|
3056
|
+
</div>
|
|
3057
|
+
<div class="claude-msg-content">
|
|
3058
|
+
Adding test for include_fonts parameter...
|
|
3059
|
+
<div class="claude-tool-call">
|
|
3060
|
+
<div class="claude-tool-name">Edit</div>
|
|
3061
|
+
<div class="claude-tool-result">src/lib/__tests__/brandfetch.test.ts → Added test case #16</div>
|
|
3062
|
+
</div>
|
|
3063
|
+
</div>
|
|
3064
|
+
</div>
|
|
3065
|
+
|
|
3066
|
+
<div class="claude-msg" data-phase="8" data-step="25">
|
|
3067
|
+
<div class="claude-msg-role ai">
|
|
3068
|
+
<span class="claude-msg-icon">🤖</span>
|
|
3069
|
+
<span class="claude-msg-name">CLAUDE</span>
|
|
3070
|
+
</div>
|
|
3071
|
+
<div class="claude-msg-content">
|
|
3072
|
+
Updating implementation for include_fonts...
|
|
3073
|
+
<div class="claude-tool-call">
|
|
3074
|
+
<div class="claude-tool-name">Edit</div>
|
|
3075
|
+
<div class="claude-tool-result">src/app/api/v2/brandfetch/route.ts → Added include_fonts query param</div>
|
|
3076
|
+
</div>
|
|
3077
|
+
<span style="color: #22c55e;">✓ All 16 tests passing!</span>
|
|
3078
|
+
</div>
|
|
3079
|
+
</div>
|
|
3080
|
+
|
|
3081
|
+
<div class="claude-msg" data-phase="9" data-step="26">
|
|
3082
|
+
<div class="claude-msg-role ai">
|
|
3083
|
+
<span class="claude-msg-icon">🤖</span>
|
|
3084
|
+
<span class="claude-msg-name">CLAUDE</span>
|
|
3085
|
+
</div>
|
|
3086
|
+
<div class="claude-msg-content">
|
|
3087
|
+
Re-verifying implementation...
|
|
3088
|
+
<div class="claude-tool-call">
|
|
3089
|
+
<div class="claude-tool-name">mcp__context7__get-library-docs</div>
|
|
3090
|
+
<div class="claude-tool-result">"brandfetch" → All documented features now implemented</div>
|
|
3091
|
+
</div>
|
|
3092
|
+
<span style="color: #22c55e;">✓ Verification complete - no gaps remaining</span>
|
|
3093
|
+
</div>
|
|
3094
|
+
</div>
|
|
3095
|
+
|
|
3096
|
+
<!-- Phase 10-12: Refactor, Docs, Complete -->
|
|
3097
|
+
<div class="claude-msg" data-phase="10" data-step="27">
|
|
3098
|
+
<div class="claude-msg-role ai">
|
|
3099
|
+
<span class="claude-msg-icon">🤖</span>
|
|
3100
|
+
<span class="claude-msg-name">CLAUDE</span>
|
|
3101
|
+
</div>
|
|
3102
|
+
<div class="claude-msg-content">
|
|
3103
|
+
Refactoring code (tests still pass)...
|
|
3104
|
+
<div class="claude-tool-call">
|
|
3105
|
+
<div class="claude-tool-name">Edit</div>
|
|
3106
|
+
<div class="claude-tool-result">Extracted caching logic to utils, improved type safety</div>
|
|
3107
|
+
</div>
|
|
3108
|
+
<span style="color: #22c55e;">✓ 16/16 tests passing</span>
|
|
3109
|
+
</div>
|
|
3110
|
+
</div>
|
|
3111
|
+
|
|
3112
|
+
<div class="claude-msg" data-phase="11" data-step="28">
|
|
3113
|
+
<div class="claude-msg-role ai">
|
|
3114
|
+
<span class="claude-msg-icon">🤖</span>
|
|
3115
|
+
<span class="claude-msg-name">CLAUDE</span>
|
|
3116
|
+
</div>
|
|
3117
|
+
<div class="claude-msg-content">
|
|
3118
|
+
Updating documentation...
|
|
3119
|
+
<div class="claude-tool-call">
|
|
3120
|
+
<div class="claude-tool-name">Write</div>
|
|
3121
|
+
<div class="claude-tool-result">api-tests-manifest.json → Added /api/v2/brandfetch entry</div>
|
|
3122
|
+
</div>
|
|
3123
|
+
<div class="claude-tool-call">
|
|
3124
|
+
<div class="claude-tool-name">Edit</div>
|
|
3125
|
+
<div class="claude-tool-result">openapi.yaml → Added brandfetch endpoint schema</div>
|
|
3126
|
+
</div>
|
|
3127
|
+
<div class="claude-tool-call">
|
|
3128
|
+
<div class="claude-tool-name">Write</div>
|
|
3129
|
+
<div class="claude-tool-result">.claude/research/brandfetch/ → Cached research for future sessions</div>
|
|
3130
|
+
</div>
|
|
3131
|
+
</div>
|
|
3132
|
+
</div>
|
|
3133
|
+
|
|
3134
|
+
<div class="claude-msg" data-phase="12" data-step="29">
|
|
3135
|
+
<div class="claude-msg-role system">
|
|
3136
|
+
<span class="claude-msg-icon">✅</span>
|
|
3137
|
+
<span class="claude-msg-name">COMPLETE</span>
|
|
3138
|
+
</div>
|
|
3139
|
+
<div class="claude-msg-content">
|
|
3140
|
+
<span style="color: #22c55e; font-weight: 600;">All 12 phases complete! Brandfetch API ready.</span><br><br>
|
|
3141
|
+
<div style="display: grid; grid-template-columns: repeat(2, 1fr); gap: 8px; font-size: 0.85rem;">
|
|
3142
|
+
<div>📁 Files created: <strong>5</strong></div>
|
|
3143
|
+
<div>✅ Tests passing: <strong>16/16</strong></div>
|
|
3144
|
+
<div>🔄 Loop-backs: <strong>2</strong></div>
|
|
3145
|
+
<div>📋 Interview decisions: <strong>5</strong></div>
|
|
3146
|
+
</div>
|
|
3147
|
+
</div>
|
|
3148
|
+
</div>
|
|
3149
|
+
</div>
|
|
2371
3150
|
</div>
|
|
2372
3151
|
|
|
2373
|
-
|
|
2374
|
-
|
|
2375
|
-
<div class="
|
|
2376
|
-
|
|
2377
|
-
|
|
2378
|
-
|
|
3152
|
+
<!-- Explanation Panel (Right) -->
|
|
3153
|
+
<div class="explanation-panel" id="explanationPanel">
|
|
3154
|
+
<div class="explanation-panel-header">
|
|
3155
|
+
Phase Explanation
|
|
3156
|
+
</div>
|
|
3157
|
+
<div class="explanation-panel-body">
|
|
3158
|
+
<div class="explanation-step active" data-phase="0">
|
|
3159
|
+
<div class="explanation-step-phase">
|
|
3160
|
+
<div class="explanation-step-num">0</div>
|
|
3161
|
+
<div class="explanation-step-name">User Command</div>
|
|
3162
|
+
</div>
|
|
3163
|
+
<div class="explanation-step-desc">
|
|
3164
|
+
The user triggers the full 12-phase workflow with a single command.
|
|
3165
|
+
</div>
|
|
3166
|
+
<div class="explanation-step-why">
|
|
3167
|
+
This starts the entire interview-driven development process.
|
|
3168
|
+
</div>
|
|
3169
|
+
</div>
|
|
3170
|
+
|
|
3171
|
+
<div class="explanation-step" data-phase="1">
|
|
3172
|
+
<div class="explanation-step-phase">
|
|
3173
|
+
<div class="explanation-step-num">1</div>
|
|
3174
|
+
<div class="explanation-step-name">Scope Confirmation</div>
|
|
3175
|
+
</div>
|
|
3176
|
+
<div class="explanation-step-desc">
|
|
3177
|
+
Claude confirms understanding of what we're building before doing anything.
|
|
3178
|
+
</div>
|
|
3179
|
+
<div class="explanation-step-why">
|
|
3180
|
+
Prevents building the wrong thing. Loop back if unclear.
|
|
3181
|
+
</div>
|
|
3182
|
+
</div>
|
|
3183
|
+
|
|
3184
|
+
<div class="explanation-step" data-phase="2">
|
|
3185
|
+
<div class="explanation-step-phase">
|
|
3186
|
+
<div class="explanation-step-num">2</div>
|
|
3187
|
+
<div class="explanation-step-name">Initial Research</div>
|
|
3188
|
+
</div>
|
|
3189
|
+
<div class="explanation-step-desc">
|
|
3190
|
+
Claude researches REAL documentation using Context7 and WebSearch. No training data assumptions!
|
|
3191
|
+
</div>
|
|
3192
|
+
<div class="explanation-step-why">
|
|
3193
|
+
Questions will be generated FROM these findings - not generic templates.
|
|
3194
|
+
</div>
|
|
3195
|
+
</div>
|
|
3196
|
+
|
|
3197
|
+
<div class="explanation-step" data-phase="3">
|
|
3198
|
+
<div class="explanation-step-phase">
|
|
3199
|
+
<div class="explanation-step-num">3</div>
|
|
3200
|
+
<div class="explanation-step-name">Interview</div>
|
|
3201
|
+
</div>
|
|
3202
|
+
<div class="explanation-step-desc">
|
|
3203
|
+
Claude asks structured questions with options derived from research. User selects, answers tracked.
|
|
3204
|
+
</div>
|
|
3205
|
+
<div class="explanation-step-why">
|
|
3206
|
+
Every decision is recorded and injected during implementation.
|
|
3207
|
+
</div>
|
|
3208
|
+
</div>
|
|
3209
|
+
|
|
3210
|
+
<div class="explanation-step" data-phase="4">
|
|
3211
|
+
<div class="explanation-step-phase">
|
|
3212
|
+
<div class="explanation-step-num">4</div>
|
|
3213
|
+
<div class="explanation-step-name">Deep Research</div>
|
|
3214
|
+
</div>
|
|
3215
|
+
<div class="explanation-step-desc">
|
|
3216
|
+
Based on interview answers, Claude proposes targeted follow-up searches.
|
|
3217
|
+
</div>
|
|
3218
|
+
<div class="explanation-step-why">
|
|
3219
|
+
Adaptive research - not shotgun. Only what's relevant to YOUR choices.
|
|
3220
|
+
</div>
|
|
3221
|
+
</div>
|
|
3222
|
+
|
|
3223
|
+
<div class="explanation-step" data-phase="5">
|
|
3224
|
+
<div class="explanation-step-phase">
|
|
3225
|
+
<div class="explanation-step-num">5</div>
|
|
3226
|
+
<div class="explanation-step-name">Schema Design</div>
|
|
3227
|
+
</div>
|
|
3228
|
+
<div class="explanation-step-desc">
|
|
3229
|
+
Zod schemas created based on research + interview decisions.
|
|
3230
|
+
</div>
|
|
3231
|
+
<div class="explanation-step-why">
|
|
3232
|
+
Types before code. Schema drives tests and implementation.
|
|
3233
|
+
</div>
|
|
3234
|
+
</div>
|
|
3235
|
+
|
|
3236
|
+
<div class="explanation-step" data-phase="6">
|
|
3237
|
+
<div class="explanation-step-phase">
|
|
3238
|
+
<div class="explanation-step-num">6</div>
|
|
3239
|
+
<div class="explanation-step-name">Environment</div>
|
|
3240
|
+
</div>
|
|
3241
|
+
<div class="explanation-step-desc">
|
|
3242
|
+
Verify API keys exist and are configured correctly.
|
|
3243
|
+
</div>
|
|
3244
|
+
<div class="explanation-step-why">
|
|
3245
|
+
Catches config issues BEFORE writing code.
|
|
3246
|
+
</div>
|
|
3247
|
+
</div>
|
|
3248
|
+
|
|
3249
|
+
<div class="explanation-step" data-phase="7">
|
|
3250
|
+
<div class="explanation-step-phase">
|
|
3251
|
+
<div class="explanation-step-num">7</div>
|
|
3252
|
+
<div class="explanation-step-name">TDD Red</div>
|
|
3253
|
+
</div>
|
|
3254
|
+
<div class="explanation-step-desc">
|
|
3255
|
+
Write failing tests first. Define success BEFORE implementation.
|
|
3256
|
+
</div>
|
|
3257
|
+
<div class="explanation-step-why">
|
|
3258
|
+
No implementation until tests exist. Enforced by hooks.
|
|
3259
|
+
</div>
|
|
3260
|
+
</div>
|
|
3261
|
+
|
|
3262
|
+
<div class="explanation-step" data-phase="8">
|
|
3263
|
+
<div class="explanation-step-phase">
|
|
3264
|
+
<div class="explanation-step-num">8</div>
|
|
3265
|
+
<div class="explanation-step-name">TDD Green</div>
|
|
3266
|
+
</div>
|
|
3267
|
+
<div class="explanation-step-desc">
|
|
3268
|
+
Write minimal code to pass tests. Interview decisions injected by hook!
|
|
3269
|
+
</div>
|
|
3270
|
+
<div class="explanation-step-why">
|
|
3271
|
+
Hook reminds Claude of YOUR decisions on every write.
|
|
3272
|
+
</div>
|
|
3273
|
+
</div>
|
|
3274
|
+
|
|
3275
|
+
<div class="explanation-step" data-phase="9">
|
|
3276
|
+
<div class="explanation-step-phase">
|
|
3277
|
+
<div class="explanation-step-num">9</div>
|
|
3278
|
+
<div class="explanation-step-name">Verify</div>
|
|
3279
|
+
</div>
|
|
3280
|
+
<div class="explanation-step-desc">
|
|
3281
|
+
Re-read original docs, compare to implementation. Find gaps!
|
|
3282
|
+
</div>
|
|
3283
|
+
<div class="explanation-step-why">
|
|
3284
|
+
Catches memory-based errors. Loops back if gaps found.
|
|
3285
|
+
</div>
|
|
3286
|
+
</div>
|
|
3287
|
+
|
|
3288
|
+
<div class="explanation-step" data-phase="10">
|
|
3289
|
+
<div class="explanation-step-phase">
|
|
3290
|
+
<div class="explanation-step-num">10</div>
|
|
3291
|
+
<div class="explanation-step-name">Refactor</div>
|
|
3292
|
+
</div>
|
|
3293
|
+
<div class="explanation-step-desc">
|
|
3294
|
+
Clean up code while tests stay green.
|
|
3295
|
+
</div>
|
|
3296
|
+
<div class="explanation-step-why">
|
|
3297
|
+
Safe improvements - tests prove nothing broke.
|
|
3298
|
+
</div>
|
|
3299
|
+
</div>
|
|
3300
|
+
|
|
3301
|
+
<div class="explanation-step" data-phase="11">
|
|
3302
|
+
<div class="explanation-step-phase">
|
|
3303
|
+
<div class="explanation-step-num">11</div>
|
|
3304
|
+
<div class="explanation-step-name">Documentation</div>
|
|
3305
|
+
</div>
|
|
3306
|
+
<div class="explanation-step-desc">
|
|
3307
|
+
Update OpenAPI spec, test manifest, research cache.
|
|
3308
|
+
</div>
|
|
3309
|
+
<div class="explanation-step-why">
|
|
3310
|
+
No "complete" without docs. Stop hook enforces this.
|
|
3311
|
+
</div>
|
|
3312
|
+
</div>
|
|
3313
|
+
|
|
3314
|
+
<div class="explanation-step" data-phase="12">
|
|
3315
|
+
<div class="explanation-step-phase">
|
|
3316
|
+
<div class="explanation-step-num">12</div>
|
|
3317
|
+
<div class="explanation-step-name">Completion</div>
|
|
3318
|
+
</div>
|
|
3319
|
+
<div class="explanation-step-desc">
|
|
3320
|
+
All phases verified. API is ready for use!
|
|
3321
|
+
</div>
|
|
3322
|
+
<div class="explanation-step-why">
|
|
3323
|
+
api-workflow-check.py blocks completion if anything incomplete.
|
|
3324
|
+
</div>
|
|
3325
|
+
</div>
|
|
2379
3326
|
</div>
|
|
2380
3327
|
</div>
|
|
2381
3328
|
</div>
|
|
@@ -2391,12 +3338,34 @@
|
|
|
2391
3338
|
<h3>The State File</h3>
|
|
2392
3339
|
|
|
2393
3340
|
<div class="explanation">
|
|
2394
|
-
<div class="explanation-title">
|
|
3341
|
+
<div class="explanation-title">Why This Matters</div>
|
|
2395
3342
|
<p>
|
|
2396
3343
|
All progress is saved to <code>.claude/api-dev-state.json</code>.
|
|
2397
|
-
This
|
|
2398
|
-
during implementation to ensure consistency.
|
|
3344
|
+
This solves three critical problems:
|
|
2399
3345
|
</p>
|
|
3346
|
+
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 16px; margin-top: 16px;">
|
|
3347
|
+
<div style="background: rgba(249, 115, 22, 0.1); border-left: 3px solid var(--claude-orange); padding: 12px; border-radius: 4px;">
|
|
3348
|
+
<div style="display: flex; align-items: center; gap: 8px;">
|
|
3349
|
+
<span style="font-size: 1.5rem;">🎯</span>
|
|
3350
|
+
<strong style="color: var(--claude-orange);">Re-Grounding</strong>
|
|
3351
|
+
</div>
|
|
3352
|
+
<p style="margin: 8px 0 0; font-size: 0.85rem; color: #aaa;">Hooks inject your decisions into every file write, preventing the AI from "forgetting" what you asked for.</p>
|
|
3353
|
+
</div>
|
|
3354
|
+
<div style="background: rgba(249, 115, 22, 0.1); border-left: 3px solid var(--claude-orange); padding: 12px; border-radius: 4px;">
|
|
3355
|
+
<div style="display: flex; align-items: center; gap: 8px;">
|
|
3356
|
+
<span style="font-size: 1.5rem;">💾</span>
|
|
3357
|
+
<strong style="color: var(--claude-orange);">Session Persistence</strong>
|
|
3358
|
+
</div>
|
|
3359
|
+
<p style="margin: 8px 0 0; font-size: 0.85rem; color: #aaa;">Come back tomorrow and pick up where you left off. The state file remembers research, interview answers, and progress.</p>
|
|
3360
|
+
</div>
|
|
3361
|
+
<div style="background: rgba(249, 115, 22, 0.1); border-left: 3px solid var(--claude-orange); padding: 12px; border-radius: 4px;">
|
|
3362
|
+
<div style="display: flex; align-items: center; gap: 8px;">
|
|
3363
|
+
<span style="font-size: 1.5rem;">🔄</span>
|
|
3364
|
+
<strong style="color: var(--claude-orange);">Loop-Back Tracking</strong>
|
|
3365
|
+
</div>
|
|
3366
|
+
<p style="margin: 8px 0 0; font-size: 0.85rem; color: #aaa;">When verification finds gaps, we know exactly which phase to return to. No lost context.</p>
|
|
3367
|
+
</div>
|
|
3368
|
+
</div>
|
|
2400
3369
|
</div>
|
|
2401
3370
|
|
|
2402
3371
|
<div class="json-viewer">
|
|
@@ -2458,39 +3427,39 @@
|
|
|
2458
3427
|
|
|
2459
3428
|
<div class="install-flow">
|
|
2460
3429
|
<div class="install-step">
|
|
2461
|
-
<div class="install-icon"
|
|
3430
|
+
<div class="install-icon">📝</div>
|
|
2462
3431
|
<div class="install-content">
|
|
2463
|
-
<div class="install-from">Slash Commands</div>
|
|
3432
|
+
<div class="install-from">21 Slash Commands</div>
|
|
2464
3433
|
<div class="install-note">/api-create, /api-interview, /red, /green, /refactor...</div>
|
|
2465
3434
|
</div>
|
|
2466
|
-
<div class="install-arrow"
|
|
3435
|
+
<div class="install-arrow">→</div>
|
|
2467
3436
|
<div class="install-to">.claude/commands/</div>
|
|
2468
3437
|
</div>
|
|
2469
3438
|
<div class="install-step">
|
|
2470
|
-
<div class="install-icon"
|
|
3439
|
+
<div class="install-icon">🐍</div>
|
|
2471
3440
|
<div class="install-content">
|
|
2472
|
-
<div class="install-from">Python Hooks</div>
|
|
3441
|
+
<div class="install-from">5 Python Hooks</div>
|
|
2473
3442
|
<div class="install-note">enforce-research, enforce-interview, verify-implementation...</div>
|
|
2474
3443
|
</div>
|
|
2475
|
-
<div class="install-arrow"
|
|
3444
|
+
<div class="install-arrow">→</div>
|
|
2476
3445
|
<div class="install-to">.claude/hooks/</div>
|
|
2477
3446
|
</div>
|
|
2478
3447
|
<div class="install-step">
|
|
2479
|
-
<div class="install-icon"
|
|
3448
|
+
<div class="install-icon">⚙️</div>
|
|
2480
3449
|
<div class="install-content">
|
|
2481
3450
|
<div class="install-from">Settings Configuration</div>
|
|
2482
3451
|
<div class="install-note">Hook registration, permissions, matchers</div>
|
|
2483
3452
|
</div>
|
|
2484
|
-
<div class="install-arrow"
|
|
3453
|
+
<div class="install-arrow">→</div>
|
|
2485
3454
|
<div class="install-to">.claude/settings.json</div>
|
|
2486
3455
|
</div>
|
|
2487
3456
|
<div class="install-step">
|
|
2488
|
-
<div class="install-icon"
|
|
3457
|
+
<div class="install-icon">🔌</div>
|
|
2489
3458
|
<div class="install-content">
|
|
2490
3459
|
<div class="install-from">MCP Servers</div>
|
|
2491
3460
|
<div class="install-note">Context7 (live docs), GitHub (issues/PRs)</div>
|
|
2492
3461
|
</div>
|
|
2493
|
-
<div class="install-arrow"
|
|
3462
|
+
<div class="install-arrow">→</div>
|
|
2494
3463
|
<div class="install-to">claude mcp add</div>
|
|
2495
3464
|
</div>
|
|
2496
3465
|
</div>
|
|
@@ -2531,14 +3500,41 @@
|
|
|
2531
3500
|
</div>
|
|
2532
3501
|
|
|
2533
3502
|
<div class="credit-links">
|
|
2534
|
-
<a href="https://github.com/hustle-together/api-dev-tools" class="credit-link" target="_blank">
|
|
2535
|
-
|
|
3503
|
+
<a href="https://github.com/hustle-together/api-dev-tools" class="credit-link" target="_blank">
|
|
3504
|
+
<svg width="24" height="24" viewBox="0 0 24 24" fill="currentColor" style="margin-right: 8px;">
|
|
3505
|
+
<path d="M12 0C5.37 0 0 5.37 0 12c0 5.31 3.435 9.795 8.205 11.385.6.105.825-.255.825-.57 0-.285-.015-1.23-.015-2.235-3.015.555-3.795-.735-4.035-1.41-.135-.345-.72-1.41-1.23-1.695-.42-.225-1.02-.78-.015-.795.945-.015 1.62.87 1.845 1.23 1.08 1.815 2.805 1.305 3.495.99.105-.78.42-1.305.765-1.605-2.67-.3-5.46-1.335-5.46-5.925 0-1.305.465-2.385 1.23-3.225-.12-.3-.54-1.53.12-3.18 0 0 1.005-.315 3.3 1.23.96-.27 1.98-.405 3-.405s2.04.135 3 .405c2.295-1.56 3.3-1.23 3.3-1.23.66 1.65.24 2.88.12 3.18.765.84 1.23 1.905 1.23 3.225 0 4.605-2.805 5.625-5.475 5.925.435.375.81 1.095.81 2.22 0 1.605-.015 2.895-.015 3.3 0 .315.225.69.825.57A12.02 12.02 0 0024 12c0-6.63-5.37-12-12-12z"/>
|
|
3506
|
+
</svg>
|
|
3507
|
+
VIEW ON GITHUB
|
|
3508
|
+
</a>
|
|
3509
|
+
<a href="https://www.npmjs.com/package/@hustle-together/api-dev-tools" class="credit-link" target="_blank">
|
|
3510
|
+
<svg width="24" height="24" viewBox="0 0 24 24" fill="currentColor" style="margin-right: 8px;">
|
|
3511
|
+
<path d="M0 7.334v8h6.666v1.332H12v-1.332h12v-8H0zm6.666 6.664H5.334v-4H3.999v4H1.335V8.667h5.331v5.331zm4 0v1.336H8.001V8.667h5.334v5.332h-2.669v-.001zm12.001 0h-1.33v-4h-1.336v4h-1.335v-4h-1.33v4h-2.671V8.667h8.002v5.331zM10.665 10H12v2.667h-1.335V10z"/>
|
|
3512
|
+
</svg>
|
|
3513
|
+
INSTALL FROM NPM
|
|
3514
|
+
</a>
|
|
3515
|
+
</div>
|
|
3516
|
+
|
|
3517
|
+
<!-- Attribution -->
|
|
3518
|
+
<div style="margin-top: 32px; padding: 20px; background: rgba(0,0,0,0.2); border-radius: 8px; text-align: center;">
|
|
3519
|
+
<p style="color: #888; font-size: 0.85rem; margin-bottom: 16px;">Built on the shoulders of giants:</p>
|
|
3520
|
+
<div style="display: flex; justify-content: center; align-items: center; gap: 32px; flex-wrap: wrap;">
|
|
3521
|
+
<a href="https://github.com/wbern/claude-instructions" target="_blank" style="display: flex; align-items: center; gap: 8px; color: var(--claude-orange); text-decoration: none;">
|
|
3522
|
+
<svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor">
|
|
3523
|
+
<path d="M12 0C5.37 0 0 5.37 0 12c0 5.31 3.435 9.795 8.205 11.385.6.105.825-.255.825-.57 0-.285-.015-1.23-.015-2.235-3.015.555-3.795-.735-4.035-1.41-.135-.345-.72-1.41-1.23-1.695-.42-.225-1.02-.78-.015-.795.945-.015 1.62.87 1.845 1.23 1.08 1.815 2.805 1.305 3.495.99.105-.78.42-1.305.765-1.605-2.67-.3-5.46-1.335-5.46-5.925 0-1.305.465-2.385 1.23-3.225-.12-.3-.54-1.53.12-3.18 0 0 1.005-.315 3.3 1.23.96-.27 1.98-.405 3-.405s2.04.135 3 .405c2.295-1.56 3.3-1.23 3.3-1.23.66 1.65.24 2.88.12 3.18.765.84 1.23 1.905 1.23 3.225 0 4.605-2.805 5.625-5.475 5.925.435.375.81 1.095.81 2.22 0 1.605-.015 2.895-.015 3.3 0 .315.225.69.825.57A12.02 12.02 0 0024 12c0-6.63-5.37-12-12-12z"/>
|
|
3524
|
+
</svg>
|
|
3525
|
+
<span>@wbern/claude-instructions</span>
|
|
3526
|
+
</a>
|
|
3527
|
+
<a href="https://context7.com" target="_blank" style="display: flex; align-items: center; gap: 8px; color: var(--claude-orange); text-decoration: none;">
|
|
3528
|
+
<span style="font-weight: bold; font-size: 1.1rem;">C7</span>
|
|
3529
|
+
<span>Context7</span>
|
|
3530
|
+
</a>
|
|
3531
|
+
</div>
|
|
2536
3532
|
</div>
|
|
2537
3533
|
|
|
2538
3534
|
<div class="made-with">
|
|
2539
3535
|
<p>Made for developers who want AI assistants<br>that actually follow instructions.</p>
|
|
2540
3536
|
<p style="margin-top: 20px; color: var(--dark-grey);">
|
|
2541
|
-
|
|
3537
|
+
v3.0.0 | MIT License<br>
|
|
2542
3538
|
"Interview first, test first, document always"
|
|
2543
3539
|
</p>
|
|
2544
3540
|
</div>
|
|
@@ -2552,7 +3548,7 @@
|
|
|
2552
3548
|
// ============================================
|
|
2553
3549
|
// CONFIGURATION
|
|
2554
3550
|
// ============================================
|
|
2555
|
-
const sections = ['intro', 'problems', 'solution', 'hooks', 'phases', '
|
|
3551
|
+
const sections = ['intro', 'problems', 'solution', 'hooks', 'phases', 'demo', 'state', 'install', 'credits'];
|
|
2556
3552
|
let isPlaying = false;
|
|
2557
3553
|
|
|
2558
3554
|
// ============================================
|
|
@@ -2754,51 +3750,162 @@
|
|
|
2754
3750
|
phasesTL.to('.phase-connector', { opacity: 1, duration: 0.3 }, '-=0.8');
|
|
2755
3751
|
|
|
2756
3752
|
// ============================================
|
|
2757
|
-
// SECTION 6:
|
|
3753
|
+
// SECTION 6: CLAUDE CODE TERMINAL ANIMATION
|
|
3754
|
+
// Animates both terminal messages and explanation panel
|
|
2758
3755
|
// ============================================
|
|
2759
|
-
const
|
|
3756
|
+
const demoTL = gsap.timeline({
|
|
2760
3757
|
scrollTrigger: {
|
|
2761
|
-
trigger: '#
|
|
3758
|
+
trigger: '#demo',
|
|
2762
3759
|
start: 'top 60%',
|
|
2763
3760
|
toggleActions: 'play none none reverse'
|
|
2764
3761
|
}
|
|
2765
3762
|
});
|
|
2766
3763
|
|
|
2767
|
-
|
|
3764
|
+
demoTL.to('#demo .explanation', { opacity: 1, duration: 0.5 });
|
|
2768
3765
|
|
|
2769
|
-
|
|
2770
|
-
|
|
2771
|
-
|
|
2772
|
-
|
|
2773
|
-
|
|
2774
|
-
|
|
2775
|
-
|
|
2776
|
-
|
|
3766
|
+
// Get all Claude Code messages and explanation steps
|
|
3767
|
+
const claudeMessages = document.querySelectorAll('#claudeBody .claude-msg');
|
|
3768
|
+
const explanationSteps = document.querySelectorAll('#explanationPanel .explanation-step');
|
|
3769
|
+
const asciiStartup = document.getElementById('asciiStartup');
|
|
3770
|
+
const promptLine = document.getElementById('promptLine');
|
|
3771
|
+
const promptInput = document.getElementById('promptInput');
|
|
3772
|
+
const loadingDots = document.getElementById('loadingDots');
|
|
3773
|
+
|
|
3774
|
+
// Track current phase for syncing explanation panel
|
|
3775
|
+
let currentDemoPhase = 0;
|
|
3776
|
+
|
|
3777
|
+
// Function to update explanation panel
|
|
3778
|
+
function updateExplanationPanel(phase) {
|
|
3779
|
+
explanationSteps.forEach(step => {
|
|
3780
|
+
const stepPhase = parseInt(step.dataset.phase);
|
|
3781
|
+
if (stepPhase === phase) {
|
|
3782
|
+
step.classList.add('active');
|
|
3783
|
+
// Scroll the explanation panel to show the active step
|
|
3784
|
+
step.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
|
|
3785
|
+
} else if (stepPhase < phase) {
|
|
3786
|
+
// Keep previous phases visible but not active
|
|
3787
|
+
step.classList.remove('active');
|
|
3788
|
+
step.style.opacity = '0.7';
|
|
3789
|
+
} else {
|
|
3790
|
+
step.classList.remove('active');
|
|
3791
|
+
step.style.opacity = '0.5';
|
|
3792
|
+
}
|
|
3793
|
+
});
|
|
3794
|
+
}
|
|
2777
3795
|
|
|
2778
|
-
//
|
|
2779
|
-
|
|
2780
|
-
|
|
2781
|
-
|
|
2782
|
-
|
|
2783
|
-
|
|
2784
|
-
|
|
2785
|
-
|
|
3796
|
+
// Typing effect for prompt
|
|
3797
|
+
function typeText(element, text, speed = 50) {
|
|
3798
|
+
return new Promise(resolve => {
|
|
3799
|
+
let i = 0;
|
|
3800
|
+
element.textContent = '';
|
|
3801
|
+
const interval = setInterval(() => {
|
|
3802
|
+
if (i < text.length) {
|
|
3803
|
+
element.textContent += text.charAt(i);
|
|
3804
|
+
i++;
|
|
3805
|
+
} else {
|
|
3806
|
+
clearInterval(interval);
|
|
3807
|
+
resolve();
|
|
3808
|
+
}
|
|
3809
|
+
}, speed);
|
|
3810
|
+
});
|
|
3811
|
+
}
|
|
3812
|
+
|
|
3813
|
+
// Show loading dots animation
|
|
3814
|
+
function showLoadingDots(show = true) {
|
|
3815
|
+
loadingDots.style.display = show ? 'inline-flex' : 'none';
|
|
3816
|
+
}
|
|
3817
|
+
|
|
3818
|
+
// Step 1: Show ASCII startup screen (2 seconds)
|
|
3819
|
+
demoTL.to(asciiStartup, {
|
|
3820
|
+
opacity: 1,
|
|
3821
|
+
duration: 0.5,
|
|
3822
|
+
onStart: () => {
|
|
3823
|
+
asciiStartup.style.display = 'block';
|
|
3824
|
+
asciiStartup.classList.add('visible');
|
|
2786
3825
|
}
|
|
2787
|
-
});
|
|
3826
|
+
}, 0.5);
|
|
3827
|
+
|
|
3828
|
+
// Step 2: Show prompt line and type command (after ASCII)
|
|
3829
|
+
demoTL.to(promptLine, {
|
|
3830
|
+
opacity: 1,
|
|
3831
|
+
duration: 0.3,
|
|
3832
|
+
onStart: () => {
|
|
3833
|
+
promptLine.classList.add('visible');
|
|
3834
|
+
},
|
|
3835
|
+
onComplete: () => {
|
|
3836
|
+
// Type the command
|
|
3837
|
+
typeText(promptInput, '/api-create brandfetch', 60);
|
|
3838
|
+
}
|
|
3839
|
+
}, 2.5);
|
|
3840
|
+
|
|
3841
|
+
// Step 3: Hide ASCII and prompt, show messages (after typing)
|
|
3842
|
+
demoTL.to([asciiStartup, promptLine], {
|
|
3843
|
+
opacity: 0,
|
|
3844
|
+
duration: 0.3,
|
|
3845
|
+
onComplete: () => {
|
|
3846
|
+
asciiStartup.style.display = 'none';
|
|
3847
|
+
promptLine.style.display = 'none';
|
|
3848
|
+
}
|
|
3849
|
+
}, 5.5);
|
|
2788
3850
|
|
|
2789
|
-
|
|
3851
|
+
// Get terminal body for scrolling
|
|
3852
|
+
const claudeBody = document.getElementById('claudeBody');
|
|
3853
|
+
|
|
3854
|
+
// Animate each message SEQUENTIALLY using relative positioning
|
|
3855
|
+
// Each message waits 1.5s after the PREVIOUS one completes
|
|
3856
|
+
claudeMessages.forEach((msg, i) => {
|
|
3857
|
+
const phase = parseInt(msg.dataset.phase);
|
|
3858
|
+
|
|
3859
|
+
// First message starts after ASCII animation (at 6s mark)
|
|
3860
|
+
// Subsequent messages use +=1.5 (1.5s after previous completes)
|
|
3861
|
+
const position = i === 0 ? 6.0 : '+=1.0'; // 1 second gap between messages
|
|
3862
|
+
|
|
3863
|
+
// Show loading dots before each message (except first)
|
|
3864
|
+
if (i > 0) {
|
|
3865
|
+
// Add loading dots that appear for 0.8s before message
|
|
3866
|
+
demoTL.call(() => {
|
|
3867
|
+
showLoadingDots(true);
|
|
3868
|
+
}, null, '+=0.2'); // Small gap after previous message
|
|
2790
3869
|
|
|
2791
|
-
|
|
2792
|
-
|
|
2793
|
-
|
|
2794
|
-
|
|
2795
|
-
|
|
3870
|
+
demoTL.to({}, { duration: 0.8 }); // Hold for loading dots
|
|
3871
|
+
|
|
3872
|
+
demoTL.call(() => {
|
|
3873
|
+
showLoadingDots(false);
|
|
3874
|
+
});
|
|
3875
|
+
}
|
|
3876
|
+
|
|
3877
|
+
// Add message to timeline
|
|
3878
|
+
demoTL.to(msg, {
|
|
2796
3879
|
opacity: 1,
|
|
2797
|
-
|
|
2798
|
-
|
|
2799
|
-
|
|
3880
|
+
y: 0,
|
|
3881
|
+
duration: 0.5,
|
|
3882
|
+
ease: 'power2.out',
|
|
3883
|
+
onStart: () => {
|
|
3884
|
+
msg.classList.add('visible');
|
|
3885
|
+
// Update explanation panel when phase changes
|
|
3886
|
+
if (phase !== currentDemoPhase) {
|
|
3887
|
+
currentDemoPhase = phase;
|
|
3888
|
+
updateExplanationPanel(phase);
|
|
3889
|
+
}
|
|
3890
|
+
},
|
|
3891
|
+
onComplete: () => {
|
|
3892
|
+
// Scroll terminal to show new message after it appears
|
|
3893
|
+
if (claudeBody) {
|
|
3894
|
+
const msgTop = msg.offsetTop;
|
|
3895
|
+
const bodyHeight = claudeBody.clientHeight;
|
|
3896
|
+
const scrollTarget = Math.max(0, msgTop - bodyHeight + msg.offsetHeight + 40);
|
|
3897
|
+
claudeBody.scrollTo({
|
|
3898
|
+
top: scrollTarget,
|
|
3899
|
+
behavior: 'smooth'
|
|
3900
|
+
});
|
|
3901
|
+
}
|
|
3902
|
+
}
|
|
3903
|
+
}, i === 0 ? position : '<'); // '<' means at same time as loading dots hide
|
|
2800
3904
|
});
|
|
2801
3905
|
|
|
3906
|
+
// Initialize explanation panel (show first step as active)
|
|
3907
|
+
updateExplanationPanel(0);
|
|
3908
|
+
|
|
2802
3909
|
// ============================================
|
|
2803
3910
|
// SECTION 8: STATE FILE ANIMATION
|
|
2804
3911
|
// ============================================
|
|
@@ -3131,67 +4238,45 @@
|
|
|
3131
4238
|
}
|
|
3132
4239
|
|
|
3133
4240
|
// Handle seek on progress bar click
|
|
3134
|
-
|
|
4241
|
+
function onProgressBarClick(e) {
|
|
3135
4242
|
e.stopPropagation(); // Prevent event bubbling
|
|
4243
|
+
e.preventDefault();
|
|
3136
4244
|
|
|
3137
|
-
//
|
|
4245
|
+
// Must have timing data loaded to seek
|
|
4246
|
+
if (!timingData || !timingData.duration) {
|
|
4247
|
+
console.warn('Cannot seek: timing data not loaded');
|
|
4248
|
+
return;
|
|
4249
|
+
}
|
|
4250
|
+
|
|
4251
|
+
// Calculate seek position from click location
|
|
3138
4252
|
const rect = audioProgressBar.getBoundingClientRect();
|
|
3139
4253
|
const clickX = e.clientX - rect.left;
|
|
3140
4254
|
const percentage = Math.max(0, Math.min(1, clickX / rect.width));
|
|
4255
|
+
const seekTime = percentage * timingData.duration;
|
|
3141
4256
|
|
|
3142
|
-
|
|
3143
|
-
// Only fall back to narrationAudio.duration if timing data unavailable
|
|
3144
|
-
let duration = (timingData && timingData.duration > 0) ? timingData.duration : narrationAudio.duration;
|
|
3145
|
-
|
|
3146
|
-
if (!duration || duration === 0 || isNaN(duration)) {
|
|
3147
|
-
console.warn('No duration available, waiting for audio to load...');
|
|
3148
|
-
// Wait for audio to load
|
|
3149
|
-
await new Promise((resolve) => {
|
|
3150
|
-
let resolved = false;
|
|
3151
|
-
const tryResolve = () => {
|
|
3152
|
-
if (!resolved && narrationAudio.duration > 0) {
|
|
3153
|
-
resolved = true;
|
|
3154
|
-
resolve();
|
|
3155
|
-
}
|
|
3156
|
-
};
|
|
3157
|
-
narrationAudio.addEventListener('loadedmetadata', tryResolve, { once: true });
|
|
3158
|
-
narrationAudio.addEventListener('canplay', tryResolve, { once: true });
|
|
3159
|
-
narrationAudio.load();
|
|
3160
|
-
setTimeout(() => { if (!resolved) { resolved = true; resolve(); } }, 2000);
|
|
3161
|
-
});
|
|
3162
|
-
duration = narrationAudio.duration;
|
|
3163
|
-
if (!duration || duration === 0 || isNaN(duration)) {
|
|
3164
|
-
console.error('Still no duration available after waiting');
|
|
3165
|
-
return;
|
|
3166
|
-
}
|
|
3167
|
-
}
|
|
3168
|
-
|
|
3169
|
-
const seekTime = percentage * duration;
|
|
3170
|
-
console.log(`Progress bar click: seeking to ${seekTime.toFixed(1)}s (${(percentage * 100).toFixed(1)}%) using duration ${duration.toFixed(1)}s`);
|
|
4257
|
+
console.log(`Progress bar click: seeking to ${seekTime.toFixed(1)}s (${(percentage * 100).toFixed(1)}%)`);
|
|
3171
4258
|
|
|
3172
|
-
//
|
|
4259
|
+
// Remember if we were playing
|
|
3173
4260
|
const wasPlaying = !narrationAudio.paused;
|
|
3174
|
-
narrationAudio.pause();
|
|
3175
4261
|
|
|
3176
|
-
//
|
|
3177
|
-
|
|
3178
|
-
|
|
3179
|
-
|
|
3180
|
-
|
|
3181
|
-
|
|
3182
|
-
|
|
4262
|
+
// Directly set currentTime - DON'T call load() or pause() first
|
|
4263
|
+
// The browser handles seeking while playing
|
|
4264
|
+
try {
|
|
4265
|
+
narrationAudio.currentTime = seekTime;
|
|
4266
|
+
console.log(`Set currentTime to: ${narrationAudio.currentTime.toFixed(1)}s`);
|
|
4267
|
+
} catch (err) {
|
|
4268
|
+
console.error('Failed to set currentTime:', err);
|
|
4269
|
+
return;
|
|
3183
4270
|
}
|
|
3184
4271
|
|
|
3185
|
-
|
|
3186
|
-
|
|
3187
|
-
|
|
3188
|
-
if (wasPlaying) {
|
|
4272
|
+
// If we weren't playing but user clicked progress bar, start playing
|
|
4273
|
+
if (wasPlaying || isPlaying) {
|
|
3189
4274
|
narrationAudio.play().catch(err => console.error('Playback failed:', err));
|
|
3190
4275
|
}
|
|
3191
4276
|
|
|
3192
|
-
//
|
|
4277
|
+
// Update highlight tracking for the new position
|
|
3193
4278
|
highlightIndex = 0;
|
|
3194
|
-
if (timingData
|
|
4279
|
+
if (timingData.highlights) {
|
|
3195
4280
|
for (let i = 0; i < timingData.highlights.length; i++) {
|
|
3196
4281
|
if (timingData.highlights[i].timestamp <= seekTime) {
|
|
3197
4282
|
highlightIndex = i;
|
|
@@ -3199,6 +4284,36 @@
|
|
|
3199
4284
|
break;
|
|
3200
4285
|
}
|
|
3201
4286
|
}
|
|
4287
|
+
// Apply highlight immediately
|
|
4288
|
+
if (highlightIndex >= 0 && highlightIndex < timingData.highlights.length) {
|
|
4289
|
+
applyHighlight(timingData.highlights[highlightIndex].selector);
|
|
4290
|
+
}
|
|
4291
|
+
}
|
|
4292
|
+
|
|
4293
|
+
// Scroll to correct section
|
|
4294
|
+
if (timingData.sections) {
|
|
4295
|
+
let sectionIdx = 0;
|
|
4296
|
+
for (let i = 0; i < timingData.sections.length; i++) {
|
|
4297
|
+
if (seekTime >= timingData.sections[i].timestamp) {
|
|
4298
|
+
sectionIdx = i;
|
|
4299
|
+
} else {
|
|
4300
|
+
break;
|
|
4301
|
+
}
|
|
4302
|
+
}
|
|
4303
|
+
currentSectionIdx = sectionIdx;
|
|
4304
|
+
updateActiveChapter(sectionIdx);
|
|
4305
|
+
const sectionEl = document.getElementById(timingData.sections[sectionIdx].id);
|
|
4306
|
+
if (sectionEl) {
|
|
4307
|
+
sectionEl.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
|
4308
|
+
}
|
|
4309
|
+
}
|
|
4310
|
+
|
|
4311
|
+
// Update UI immediately
|
|
4312
|
+
if (audioProgressFill) {
|
|
4313
|
+
audioProgressFill.style.width = `${percentage * 100}%`;
|
|
4314
|
+
}
|
|
4315
|
+
if (audioCurrentTime) {
|
|
4316
|
+
audioCurrentTime.textContent = formatTime(seekTime);
|
|
3202
4317
|
}
|
|
3203
4318
|
}
|
|
3204
4319
|
|
|
@@ -3241,6 +4356,7 @@
|
|
|
3241
4356
|
if (audioEnabled && timingData) {
|
|
3242
4357
|
// Try to play audio
|
|
3243
4358
|
audioProgressContainer.style.display = 'block';
|
|
4359
|
+
document.body.classList.add('audio-playing'); // Adjust section heights
|
|
3244
4360
|
|
|
3245
4361
|
try {
|
|
3246
4362
|
await narrationAudio.play();
|
|
@@ -3252,6 +4368,7 @@
|
|
|
3252
4368
|
audioToggleBtn.textContent = '🔇 NO AUDIO';
|
|
3253
4369
|
audioToggleBtn.classList.add('disabled');
|
|
3254
4370
|
audioProgressContainer.style.display = 'none';
|
|
4371
|
+
document.body.classList.remove('audio-playing');
|
|
3255
4372
|
startSilentAutoPlay();
|
|
3256
4373
|
}
|
|
3257
4374
|
} else {
|
|
@@ -3274,6 +4391,7 @@
|
|
|
3274
4391
|
narrationAudio.pause();
|
|
3275
4392
|
narrationAudio.currentTime = 0;
|
|
3276
4393
|
audioProgressContainer.style.display = 'none';
|
|
4394
|
+
document.body.classList.remove('audio-playing'); // Reset section heights
|
|
3277
4395
|
removeHighlight();
|
|
3278
4396
|
highlightIndex = 0;
|
|
3279
4397
|
currentSectionIdx = 0;
|
|
@@ -3386,7 +4504,6 @@
|
|
|
3386
4504
|
gsap.set('.flow-box, .flow-arrow, .hook-group, .hook-file', { opacity: 0 });
|
|
3387
4505
|
gsap.set('.result-allowed, .result-blocked', { opacity: 0 });
|
|
3388
4506
|
gsap.set('.phase-box', { opacity: 0, scale: 0.9 });
|
|
3389
|
-
gsap.set('.walkthrough-step', { opacity: 0, y: 20 });
|
|
3390
4507
|
gsap.set('.terminal-line, .terminal-comment', { opacity: 0 });
|
|
3391
4508
|
gsap.set('.json-line', { opacity: 0 });
|
|
3392
4509
|
gsap.set('.install-step', { opacity: 0, y: 20 });
|