@invisibleloop/pulse 0.14.1 → 0.15.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/.claude/commands/build-page.md +5 -1
- package/.claude/commands/verify.md +23 -13
- package/docs/.claude/pulse-checklist.md +5 -3
- package/docs/public/.pulse-ui-version +1 -1
- package/docs/public/docs.css +236 -0
- package/docs/public/home-brut.css +998 -0
- package/docs/public/menu.js +237 -6
- package/docs/public/pulse-ui.css +44 -0
- package/docs/public/theme.css +8 -0
- package/docs/server.js +24 -0
- package/docs/src/lib/layout.js +51 -3
- package/docs/src/pages/getting-started.js +1 -1
- package/docs/src/pages/home.js +231 -312
- package/docs/src/pages/how-it-works.js +67 -12
- package/examples/.claude/commands/pulse-build.md +7 -0
- package/examples/.claude/commands/pulse-dev.md +7 -0
- package/examples/.claude/commands/pulse-start.md +9 -0
- package/examples/.claude/commands/pulse-stop.md +5 -0
- package/examples/.claude/commands/verify.md +84 -0
- package/examples/.claude/coverage-check.js +127 -0
- package/examples/.claude/pulse-checklist.md +177 -0
- package/examples/public/.pulse-ui-version +1 -0
- package/examples/public/pulse-ui.css +4031 -0
- package/examples/public/pulse-ui.js +257 -0
- package/package.json +1 -1
- package/public/.pulse-ui-version +1 -1
- package/public/pulse-ui.css +44 -0
- package/scripts/build.js +127 -21
- package/src/agent/checklist.md +5 -3
- package/src/agent/guide-components.md +2 -2
- package/src/agent/guide-examples.md +310 -32
- package/src/agent/guide-styles.md +15 -0
- package/src/agent/guide-templates.md +3 -0
- package/src/agent/identity.md +2 -1
- package/src/agent/skills/verify/SKILL.md +64 -28
- package/src/agent/workflow.md +53 -17
- package/src/cli/dev.js +49 -13
- package/src/cli/index.js +4 -10
- package/src/cli/logger.js +145 -0
- package/src/cli/scaffold.js +55 -1
- package/src/mcp/server.js +174 -26
- package/src/mcp/validate-worker.js +21 -6
- package/src/server/index.js +20 -16
- package/src/spec/schema.js +19 -3
- package/src/spec/schema.test.js +28 -0
- package/src/ui/button.js +1 -1
|
@@ -41,7 +41,7 @@ Use `pulse_validate` on the spec. Fix any errors before continuing.
|
|
|
41
41
|
|
|
42
42
|
Check the project's server entry file (e.g. `src/server.js` or `pulse.config.js`) and add the new spec if needed.
|
|
43
43
|
|
|
44
|
-
### 6. Screenshot
|
|
44
|
+
### 6. Screenshot and design approval
|
|
45
45
|
|
|
46
46
|
Use `mcp__chrome-devtools__navigate_page` to load the page, then `mcp__chrome-devtools__take_screenshot`.
|
|
47
47
|
|
|
@@ -50,6 +50,10 @@ Check for:
|
|
|
50
50
|
- Layout looks correct
|
|
51
51
|
- No console errors via `mcp__chrome-devtools__list_console_messages`
|
|
52
52
|
|
|
53
|
+
Then use `ask_user` to ask: "Happy with the design and layout, or would you like any changes before I run tests and Lighthouse?" with choices: `["Yes, looks good — run tests and Lighthouse", "I'd like some changes first"]`
|
|
54
|
+
|
|
55
|
+
**Do not proceed to step 7 until the user explicitly confirms.** If they want changes, make them and return to step 6.
|
|
56
|
+
|
|
53
57
|
### 7. Run the checklist
|
|
54
58
|
|
|
55
59
|
Go through `src/agent/checklist.md` and confirm every applicable point passes. Fix anything that fails.
|
|
@@ -8,51 +8,61 @@ Run the full verification loop on the current page or the page specified in $ARG
|
|
|
8
8
|
|
|
9
9
|
If $ARGUMENTS is provided, use it as the file path or route. Otherwise, identify the most recently edited spec file from context.
|
|
10
10
|
|
|
11
|
-
### 2.
|
|
11
|
+
### 2. Design approval (new builds only)
|
|
12
|
+
|
|
13
|
+
**Skip this step for edits, bug fixes, or "add X to existing Y" tasks.**
|
|
14
|
+
|
|
15
|
+
If this is a new page build (came through `pulse_intake` or `build-page`):
|
|
16
|
+
|
|
17
|
+
1. Take a screenshot and describe what you see to the user.
|
|
18
|
+
2. Use `ask_user` to ask: "Happy with the design and layout, or would you like any changes before I run Lighthouse?" — provide choices: `["Yes, looks good — proceed", "I'd like some changes first"]`
|
|
19
|
+
3. **Do not proceed to step 3 until the user explicitly confirms.** If they want changes, stop here, make the changes, then restart from step 2. Lighthouse takes ~90 seconds — do not waste it on a design the user hasn't approved.
|
|
20
|
+
|
|
21
|
+
### 3. Validate the spec
|
|
12
22
|
|
|
13
23
|
Use `pulse_validate` with the spec file content. If validation fails, report every error clearly and stop — do not proceed to screenshot until the spec is valid.
|
|
14
24
|
|
|
15
|
-
###
|
|
25
|
+
### 4. Check the dev server
|
|
16
26
|
|
|
17
27
|
Use `pulse_fetch_page` to confirm the server is responding for the route. If it errors, use `pulse_restart_server` and retry once.
|
|
18
28
|
|
|
19
|
-
###
|
|
29
|
+
### 5. Screenshot
|
|
20
30
|
|
|
21
31
|
Use `mcp__chrome-devtools__navigate_page` to load the page route, then `mcp__chrome-devtools__take_screenshot` to capture the result. Describe what you see — layout, content, any obvious rendering issues.
|
|
22
32
|
|
|
23
|
-
###
|
|
33
|
+
### 6. Lighthouse — desktop
|
|
24
34
|
|
|
25
35
|
Run `mcp__chrome-devtools__lighthouse_audit` on the route with `{ "strategy": "desktop" }`.
|
|
26
36
|
|
|
27
|
-
**Pass bar: Performance, Accessibility, Best Practices, and SEO must all be 100.** Report the actual scores. If any score is below 100, identify the failing audit(s), fix the issue, and restart from step
|
|
37
|
+
**Pass bar: Performance, Accessibility, Best Practices, and SEO must all be 100.** Report the actual scores. If any score is below 100, identify the failing audit(s), fix the issue, and restart from step 3.
|
|
28
38
|
|
|
29
|
-
###
|
|
39
|
+
### 7. Lighthouse — mobile
|
|
30
40
|
|
|
31
41
|
Run `mcp__chrome-devtools__lighthouse_audit` on the same route with `{ "strategy": "mobile" }`.
|
|
32
42
|
|
|
33
|
-
**Same pass bar: all four categories must be 100.** Report the actual scores. If any score is below 100, fix and restart from step
|
|
43
|
+
**Same pass bar: all four categories must be 100.** Report the actual scores. If any score is below 100, fix and restart from step 3.
|
|
34
44
|
|
|
35
|
-
###
|
|
45
|
+
### 8. Performance
|
|
36
46
|
|
|
37
47
|
Navigate to the page route, then run `mcp__chrome-devtools__performance_start_trace` with `reload: true` and `autoStop: true`. Report LCP and CLS. Flag any LCP insight that suggests a fixable problem (render-blocking resources, large image load delay, etc.).
|
|
38
48
|
|
|
39
|
-
###
|
|
49
|
+
### 9. Console errors
|
|
40
50
|
|
|
41
51
|
Use `mcp__chrome-devtools__list_console_messages` — report any errors or unexpected warnings.
|
|
42
52
|
|
|
43
|
-
###
|
|
53
|
+
### 10. Code review
|
|
44
54
|
|
|
45
55
|
Call `pulse_review` with the spec file path. This runs a full code review AND atomically writes the `.pulse-verified` stamp server-side, eliminating any race condition with the stop hook.
|
|
46
56
|
|
|
47
57
|
Work through every item the review returns. Fix anything that fails before proceeding.
|
|
48
58
|
|
|
49
|
-
###
|
|
59
|
+
### 11. Close extra browser tabs
|
|
50
60
|
|
|
51
61
|
Use `mcp__chrome-devtools__list_pages` to get all open pages. Close every page **except the last one** — `close_page` refuses to close the final tab. `pageId` must be a number, not a string.
|
|
52
62
|
|
|
53
63
|
If there is only one page open, skip this step — there is nothing to close.
|
|
54
64
|
|
|
55
|
-
###
|
|
65
|
+
### 12. Write verification stamp
|
|
56
66
|
|
|
57
67
|
`pulse_review` writes the stamp automatically. As a belt-and-suspenders backup, also run:
|
|
58
68
|
|
|
@@ -62,7 +72,7 @@ date +%s > .pulse-verified
|
|
|
62
72
|
|
|
63
73
|
This ensures the stamp is present even if `pulse_review` was not called with a file path.
|
|
64
74
|
|
|
65
|
-
###
|
|
75
|
+
### 13. Report
|
|
66
76
|
|
|
67
77
|
Summarise:
|
|
68
78
|
- Validation: pass or fail (with errors if any)
|
|
@@ -36,13 +36,15 @@ Before finishing any spec, verify every point below. Fix anything that fails.
|
|
|
36
36
|
- Navigation → `nav({ logo, links, actions })`
|
|
37
37
|
- Footers → `footer({ logo, links, columns, legal, ... })`
|
|
38
38
|
|
|
39
|
-
- **Creative override — raw HTML throughout is permitted** when the design intent genuinely calls for it: a highly custom visual identity, an asymmetric or typographically-driven layout, a brutalist/editorial/retro/neon/paper vibe where components would constrain the expression. This is a deliberate design decision, not a shortcut. When taking this path:
|
|
40
|
-
-
|
|
39
|
+
- **Creative override — raw HTML throughout is permitted** when the design intent genuinely calls for it: a highly custom visual identity, an asymmetric or typographically-driven layout, a brutalist/editorial/retro/neon/paper vibe where components would constrain the expression, or a layout that requires features a component simply doesn't support (e.g. full-viewport height, custom gradient glows, clamp-scaled display type). This is a deliberate design decision, not a shortcut. When taking this path:
|
|
40
|
+
- **Declare it in a comment at the top of the spec** so the reviewer recognises it: `// component-free — creative override: <reason>`. This is the signal the review tool reads.
|
|
41
41
|
- Functional atoms (`button`, `input`, `badge`, `modal`) should still come from components unless there is a specific design reason not to.
|
|
42
42
|
- `/pulse-ui.css` is always required — it provides the token system your custom CSS will use.
|
|
43
43
|
- The quality gate replaces the component checklist: **100/100/100/100 Lighthouse on both desktop and mobile is the pass bar.** A component-free page that passes every audit is correct. A component-heavy page that fails accessibility is not.
|
|
44
44
|
|
|
45
|
-
- When reviewing a
|
|
45
|
+
- **When reviewing**: before flagging a class name like `.hero` as a violation, first ask whether the `hero()` component could actually reproduce the layout. If the answer is no, it is a creative override — check Lighthouse instead of refactoring. Do not flatten a good custom layout into a generic component just to clear a pattern-match.
|
|
46
|
+
|
|
47
|
+
- **The review tool auto-detects creative override** from the spec comment. When detected, component pattern checks are shown as advisory (`⚡`) not as failures, and the Lighthouse gate is the stated pass bar.
|
|
46
48
|
|
|
47
49
|
- **Never write App Store or Google Play download buttons by hand.** Always use `appBadge({ store: 'apple', href })` and `appBadge({ store: 'google', href })`. Raw `<a>` tags with badge images are incorrect — `appBadge` renders the correct accessible, styled badge for each store.
|
|
48
50
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
0.
|
|
1
|
+
0.14.2
|
package/docs/public/docs.css
CHANGED
|
@@ -1406,6 +1406,242 @@ a:hover {
|
|
|
1406
1406
|
flex-shrink: 0;
|
|
1407
1407
|
}
|
|
1408
1408
|
|
|
1409
|
+
/* ─── Sidebar search ─────────────────────────────────────────────────────────── */
|
|
1410
|
+
.sidebar-search-wrap {
|
|
1411
|
+
display: flex;
|
|
1412
|
+
align-items: center;
|
|
1413
|
+
gap: 0.4rem;
|
|
1414
|
+
padding: 0.6rem 0.75rem;
|
|
1415
|
+
border-bottom: 1px solid var(--border-subtle);
|
|
1416
|
+
flex-shrink: 0;
|
|
1417
|
+
position: relative;
|
|
1418
|
+
}
|
|
1419
|
+
|
|
1420
|
+
.sidebar-search-icon {
|
|
1421
|
+
color: var(--muted-2);
|
|
1422
|
+
flex-shrink: 0;
|
|
1423
|
+
pointer-events: none;
|
|
1424
|
+
}
|
|
1425
|
+
|
|
1426
|
+
.sidebar-search {
|
|
1427
|
+
flex: 1;
|
|
1428
|
+
min-width: 0;
|
|
1429
|
+
background: transparent;
|
|
1430
|
+
border: none;
|
|
1431
|
+
outline: none;
|
|
1432
|
+
font-family: var(--font);
|
|
1433
|
+
font-size: 0.82rem;
|
|
1434
|
+
color: var(--text);
|
|
1435
|
+
padding: 0;
|
|
1436
|
+
line-height: 1.4;
|
|
1437
|
+
}
|
|
1438
|
+
|
|
1439
|
+
.sidebar-search::placeholder {
|
|
1440
|
+
color: var(--muted-2);
|
|
1441
|
+
}
|
|
1442
|
+
|
|
1443
|
+
.sidebar-search::-webkit-search-cancel-button {
|
|
1444
|
+
-webkit-appearance: none;
|
|
1445
|
+
}
|
|
1446
|
+
|
|
1447
|
+
.sidebar-search-full {
|
|
1448
|
+
display: flex;
|
|
1449
|
+
align-items: center;
|
|
1450
|
+
justify-content: center;
|
|
1451
|
+
width: 22px;
|
|
1452
|
+
height: 22px;
|
|
1453
|
+
flex-shrink: 0;
|
|
1454
|
+
background: var(--surface-2);
|
|
1455
|
+
border: 1px solid var(--border);
|
|
1456
|
+
border-radius: 4px;
|
|
1457
|
+
color: var(--muted-2);
|
|
1458
|
+
cursor: pointer;
|
|
1459
|
+
transition: color 0.1s, background 0.1s;
|
|
1460
|
+
}
|
|
1461
|
+
|
|
1462
|
+
.sidebar-search-full:hover {
|
|
1463
|
+
color: var(--text);
|
|
1464
|
+
background: var(--border);
|
|
1465
|
+
}
|
|
1466
|
+
|
|
1467
|
+
.sidebar-no-results {
|
|
1468
|
+
padding: 0.75rem 1.25rem;
|
|
1469
|
+
font-size: 0.8rem;
|
|
1470
|
+
color: var(--muted-2);
|
|
1471
|
+
}
|
|
1472
|
+
|
|
1473
|
+
/* ─── Search overlay ─────────────────────────────────────────────────────────── */
|
|
1474
|
+
.search-overlay {
|
|
1475
|
+
position: fixed;
|
|
1476
|
+
inset: 0;
|
|
1477
|
+
z-index: 500;
|
|
1478
|
+
display: flex;
|
|
1479
|
+
align-items: flex-start;
|
|
1480
|
+
justify-content: center;
|
|
1481
|
+
padding-top: 10vh;
|
|
1482
|
+
}
|
|
1483
|
+
|
|
1484
|
+
.search-overlay[hidden] {
|
|
1485
|
+
display: none;
|
|
1486
|
+
}
|
|
1487
|
+
|
|
1488
|
+
.search-overlay-backdrop {
|
|
1489
|
+
position: absolute;
|
|
1490
|
+
inset: 0;
|
|
1491
|
+
background: rgba(0, 0, 0, 0.6);
|
|
1492
|
+
backdrop-filter: blur(3px);
|
|
1493
|
+
}
|
|
1494
|
+
|
|
1495
|
+
.search-overlay-panel {
|
|
1496
|
+
position: relative;
|
|
1497
|
+
width: min(640px, calc(100vw - 2rem));
|
|
1498
|
+
background: var(--surface);
|
|
1499
|
+
border: 1px solid var(--border);
|
|
1500
|
+
border-radius: 12px;
|
|
1501
|
+
box-shadow: 0 24px 64px rgba(0, 0, 0, 0.5);
|
|
1502
|
+
display: flex;
|
|
1503
|
+
flex-direction: column;
|
|
1504
|
+
overflow: hidden;
|
|
1505
|
+
max-height: 70vh;
|
|
1506
|
+
}
|
|
1507
|
+
|
|
1508
|
+
.search-overlay-header {
|
|
1509
|
+
display: flex;
|
|
1510
|
+
align-items: center;
|
|
1511
|
+
gap: 0.75rem;
|
|
1512
|
+
padding: 0.875rem 1rem;
|
|
1513
|
+
border-bottom: 1px solid var(--border-subtle);
|
|
1514
|
+
flex-shrink: 0;
|
|
1515
|
+
}
|
|
1516
|
+
|
|
1517
|
+
.search-overlay-input-wrap {
|
|
1518
|
+
display: flex;
|
|
1519
|
+
align-items: center;
|
|
1520
|
+
gap: 0.6rem;
|
|
1521
|
+
flex: 1;
|
|
1522
|
+
color: var(--muted-2);
|
|
1523
|
+
}
|
|
1524
|
+
|
|
1525
|
+
.search-overlay-input {
|
|
1526
|
+
flex: 1;
|
|
1527
|
+
background: transparent;
|
|
1528
|
+
border: none;
|
|
1529
|
+
outline: none;
|
|
1530
|
+
font-family: var(--font);
|
|
1531
|
+
font-size: 1rem;
|
|
1532
|
+
color: var(--text);
|
|
1533
|
+
padding: 0;
|
|
1534
|
+
line-height: 1.4;
|
|
1535
|
+
}
|
|
1536
|
+
|
|
1537
|
+
.search-overlay-input::placeholder {
|
|
1538
|
+
color: var(--muted-2);
|
|
1539
|
+
}
|
|
1540
|
+
|
|
1541
|
+
.search-overlay-input::-webkit-search-cancel-button {
|
|
1542
|
+
-webkit-appearance: none;
|
|
1543
|
+
}
|
|
1544
|
+
|
|
1545
|
+
.search-overlay-close {
|
|
1546
|
+
font-family: var(--mono);
|
|
1547
|
+
font-size: 0.7rem;
|
|
1548
|
+
color: var(--muted-2);
|
|
1549
|
+
background: var(--surface-2);
|
|
1550
|
+
border: 1px solid var(--border);
|
|
1551
|
+
border-radius: 4px;
|
|
1552
|
+
padding: 0.2rem 0.5rem;
|
|
1553
|
+
cursor: pointer;
|
|
1554
|
+
flex-shrink: 0;
|
|
1555
|
+
}
|
|
1556
|
+
|
|
1557
|
+
.search-overlay-results {
|
|
1558
|
+
overflow-y: auto;
|
|
1559
|
+
flex: 1;
|
|
1560
|
+
padding: 0.5rem;
|
|
1561
|
+
}
|
|
1562
|
+
|
|
1563
|
+
.search-result {
|
|
1564
|
+
display: block;
|
|
1565
|
+
padding: 0.65rem 0.75rem;
|
|
1566
|
+
border-radius: 6px;
|
|
1567
|
+
text-decoration: none;
|
|
1568
|
+
color: var(--text);
|
|
1569
|
+
transition: background 0.1s;
|
|
1570
|
+
}
|
|
1571
|
+
|
|
1572
|
+
.search-result:hover,
|
|
1573
|
+
.search-result--selected {
|
|
1574
|
+
background: var(--surface-2);
|
|
1575
|
+
}
|
|
1576
|
+
|
|
1577
|
+
.search-result-meta {
|
|
1578
|
+
margin-bottom: 0.15rem;
|
|
1579
|
+
}
|
|
1580
|
+
|
|
1581
|
+
.search-result-section {
|
|
1582
|
+
font-size: 0.68rem;
|
|
1583
|
+
font-weight: 600;
|
|
1584
|
+
text-transform: uppercase;
|
|
1585
|
+
letter-spacing: 0.08em;
|
|
1586
|
+
color: var(--accent);
|
|
1587
|
+
}
|
|
1588
|
+
|
|
1589
|
+
.search-result-title {
|
|
1590
|
+
font-size: 0.9rem;
|
|
1591
|
+
font-weight: 500;
|
|
1592
|
+
color: var(--text);
|
|
1593
|
+
line-height: 1.4;
|
|
1594
|
+
}
|
|
1595
|
+
|
|
1596
|
+
.search-result-title mark,
|
|
1597
|
+
.search-result-snip mark {
|
|
1598
|
+
background: rgba(201, 184, 0, 0.3);
|
|
1599
|
+
color: inherit;
|
|
1600
|
+
border-radius: 2px;
|
|
1601
|
+
}
|
|
1602
|
+
|
|
1603
|
+
.search-result-snip {
|
|
1604
|
+
font-size: 0.78rem;
|
|
1605
|
+
color: var(--muted-2);
|
|
1606
|
+
margin-top: 0.25rem;
|
|
1607
|
+
line-height: 1.5;
|
|
1608
|
+
display: -webkit-box;
|
|
1609
|
+
-webkit-line-clamp: 2;
|
|
1610
|
+
-webkit-box-orient: vertical;
|
|
1611
|
+
overflow: hidden;
|
|
1612
|
+
}
|
|
1613
|
+
|
|
1614
|
+
.search-overlay-empty {
|
|
1615
|
+
padding: 2rem 1rem;
|
|
1616
|
+
text-align: center;
|
|
1617
|
+
color: var(--muted-2);
|
|
1618
|
+
font-size: 0.9rem;
|
|
1619
|
+
}
|
|
1620
|
+
|
|
1621
|
+
.search-overlay-footer {
|
|
1622
|
+
display: flex;
|
|
1623
|
+
gap: 1.25rem;
|
|
1624
|
+
padding: 0.6rem 1rem;
|
|
1625
|
+
border-top: 1px solid var(--border-subtle);
|
|
1626
|
+
flex-shrink: 0;
|
|
1627
|
+
font-size: 0.72rem;
|
|
1628
|
+
color: var(--muted-2);
|
|
1629
|
+
}
|
|
1630
|
+
|
|
1631
|
+
.search-overlay-footer kbd {
|
|
1632
|
+
display: inline-flex;
|
|
1633
|
+
align-items: center;
|
|
1634
|
+
justify-content: center;
|
|
1635
|
+
font-family: var(--mono);
|
|
1636
|
+
font-size: 0.68rem;
|
|
1637
|
+
background: var(--surface-2);
|
|
1638
|
+
border: 1px solid var(--border);
|
|
1639
|
+
border-radius: 3px;
|
|
1640
|
+
padding: 0.1rem 0.35rem;
|
|
1641
|
+
color: var(--muted-2);
|
|
1642
|
+
margin-right: 0.2rem;
|
|
1643
|
+
}
|
|
1644
|
+
|
|
1409
1645
|
.logo-link {
|
|
1410
1646
|
display: flex;
|
|
1411
1647
|
align-items: center;
|