comprehende 0.4.0 → 0.5.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 +20 -13
- package/dist/api/live.js +28 -26
- package/dist/cli/args.js +3 -3
- package/dist/cli/main.js +4 -3
- package/dist/git/repo.js +7 -0
- package/dist/git/show.js +3 -3
- package/dist/review/coverage.js +4 -2
- package/dist/server/http.js +5 -3
- package/dist/ui/assets/index-CNz9KqcH.js +1713 -0
- package/dist/ui/assets/index-DJMUAjCi.css +1 -0
- package/dist/ui/index.html +2 -2
- package/package.json +2 -1
- package/skills/comprehende/SKILL.md +43 -78
- package/skills/comprehende/references/example.md +27 -24
- package/skills/comprehende/references/review.schema.json +121 -37
- package/dist/ui/assets/index-jNrhIkrB.css +0 -1
- package/dist/ui/assets/index-wHrmWxbz.js +0 -1598
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@font-face{font-family:IBM Plex Sans;font-style:normal;font-display:swap;font-weight:400;src:url(./ibm-plex-sans-cyrillic-ext-400-normal-g30qAdWV.woff2) format("woff2"),url(./ibm-plex-sans-cyrillic-ext-400-normal-Dsrv2Tcn.woff) format("woff");unicode-range:U+0460-052F,U+1C80-1C8A,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:IBM Plex Sans;font-style:normal;font-display:swap;font-weight:400;src:url(./ibm-plex-sans-cyrillic-400-normal-DZqxrq2p.woff2) format("woff2"),url(./ibm-plex-sans-cyrillic-400-normal-BTotfTJu.woff) format("woff");unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}@font-face{font-family:IBM Plex Sans;font-style:normal;font-display:swap;font-weight:400;src:url(./ibm-plex-sans-greek-400-normal-_efipK4i.woff2) format("woff2"),url(./ibm-plex-sans-greek-400-normal-D9ESIMu3.woff) format("woff");unicode-range:U+0370-0377,U+037A-037F,U+0384-038A,U+038C,U+038E-03A1,U+03A3-03FF}@font-face{font-family:IBM Plex Sans;font-style:normal;font-display:swap;font-weight:400;src:url(./ibm-plex-sans-vietnamese-400-normal-DG4YqDda.woff2) format("woff2"),url(./ibm-plex-sans-vietnamese-400-normal-fK1oJ5dG.woff) format("woff");unicode-range:U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+0300-0301,U+0303-0304,U+0308-0309,U+0323,U+0329,U+1EA0-1EF9,U+20AB}@font-face{font-family:IBM Plex Sans;font-style:normal;font-display:swap;font-weight:400;src:url(./ibm-plex-sans-latin-ext-400-normal-C5H60-Va.woff2) format("woff2"),url(./ibm-plex-sans-latin-ext-400-normal-RBey6euL.woff) format("woff");unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:IBM Plex Sans;font-style:normal;font-display:swap;font-weight:400;src:url(./ibm-plex-sans-latin-400-normal-CDDApCn2.woff2) format("woff2"),url(./ibm-plex-sans-latin-400-normal-CYLoc0-x.woff) format("woff");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:IBM Plex Sans;font-style:normal;font-display:swap;font-weight:500;src:url(./ibm-plex-sans-cyrillic-ext-500-normal-Cs5J6C77.woff2) format("woff2"),url(./ibm-plex-sans-cyrillic-ext-500-normal-DB5PtV2g.woff) format("woff");unicode-range:U+0460-052F,U+1C80-1C8A,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:IBM Plex Sans;font-style:normal;font-display:swap;font-weight:500;src:url(./ibm-plex-sans-cyrillic-500-normal-CocWQlwt.woff2) format("woff2"),url(./ibm-plex-sans-cyrillic-500-normal-ByOcLdNv.woff) format("woff");unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}@font-face{font-family:IBM Plex Sans;font-style:normal;font-display:swap;font-weight:500;src:url(./ibm-plex-sans-greek-500-normal-JMMifIXV.woff2) format("woff2"),url(./ibm-plex-sans-greek-500-normal-CuWXN6rf.woff) format("woff");unicode-range:U+0370-0377,U+037A-037F,U+0384-038A,U+038C,U+038E-03A1,U+03A3-03FF}@font-face{font-family:IBM Plex Sans;font-style:normal;font-display:swap;font-weight:500;src:url(./ibm-plex-sans-vietnamese-500-normal-e4dixQRQ.woff2) format("woff2"),url(./ibm-plex-sans-vietnamese-500-normal-BEb3_waV.woff) format("woff");unicode-range:U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+0300-0301,U+0303-0304,U+0308-0309,U+0323,U+0329,U+1EA0-1EF9,U+20AB}@font-face{font-family:IBM Plex Sans;font-style:normal;font-display:swap;font-weight:500;src:url(./ibm-plex-sans-latin-ext-500-normal-DakdToA3.woff2) format("woff2"),url(./ibm-plex-sans-latin-ext-500-normal-D0aIdm-b.woff) format("woff");unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:IBM Plex Sans;font-style:normal;font-display:swap;font-weight:500;src:url(./ibm-plex-sans-latin-500-normal-6ng42L7E.woff2) format("woff2"),url(./ibm-plex-sans-latin-500-normal-BgVn5rGT.woff) format("woff");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:IBM Plex Sans;font-style:normal;font-display:swap;font-weight:600;src:url(./ibm-plex-sans-cyrillic-ext-600-normal-DUMzJB7m.woff2) format("woff2"),url(./ibm-plex-sans-cyrillic-ext-600-normal-Bz0x94Yp.woff) format("woff");unicode-range:U+0460-052F,U+1C80-1C8A,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:IBM Plex Sans;font-style:normal;font-display:swap;font-weight:600;src:url(./ibm-plex-sans-cyrillic-600-normal-71GNu3SW.woff2) format("woff2"),url(./ibm-plex-sans-cyrillic-600-normal-BGq0mW3O.woff) format("woff");unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}@font-face{font-family:IBM Plex Sans;font-style:normal;font-display:swap;font-weight:600;src:url(./ibm-plex-sans-greek-600-normal-DzTrcv_p.woff2) format("woff2"),url(./ibm-plex-sans-greek-600-normal-D-CqTdkO.woff) format("woff");unicode-range:U+0370-0377,U+037A-037F,U+0384-038A,U+038C,U+038E-03A1,U+03A3-03FF}@font-face{font-family:IBM Plex Sans;font-style:normal;font-display:swap;font-weight:600;src:url(./ibm-plex-sans-vietnamese-600-normal-DpPYBSTl.woff2) format("woff2"),url(./ibm-plex-sans-vietnamese-600-normal-DgdngZtN.woff) format("woff");unicode-range:U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+0300-0301,U+0303-0304,U+0308-0309,U+0323,U+0329,U+1EA0-1EF9,U+20AB}@font-face{font-family:IBM Plex Sans;font-style:normal;font-display:swap;font-weight:600;src:url(./ibm-plex-sans-latin-ext-600-normal-DOrvGEcy.woff2) format("woff2"),url(./ibm-plex-sans-latin-ext-600-normal-DIrixKbi.woff) format("woff");unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:IBM Plex Sans;font-style:normal;font-display:swap;font-weight:600;src:url(./ibm-plex-sans-latin-600-normal-CuJfVYMP.woff2) format("woff2"),url(./ibm-plex-sans-latin-600-normal-Cu4Hd6ag.woff) format("woff");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:IBM Plex Mono;font-style:normal;font-display:swap;font-weight:400;src:url(./ibm-plex-mono-cyrillic-ext-400-normal-xuaO2J-f.woff2) format("woff2"),url(./ibm-plex-mono-cyrillic-ext-400-normal-DMdlQ8Kv.woff) format("woff");unicode-range:U+0460-052F,U+1C80-1C8A,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:IBM Plex Mono;font-style:normal;font-display:swap;font-weight:400;src:url(./ibm-plex-mono-cyrillic-400-normal-BSMlKf0J.woff2) format("woff2"),url(./ibm-plex-mono-cyrillic-400-normal-CEL4l2ZJ.woff) format("woff");unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}@font-face{font-family:IBM Plex Mono;font-style:normal;font-display:swap;font-weight:400;src:url(./ibm-plex-mono-vietnamese-400-normal-BulugwFq.woff2) format("woff2"),url(./ibm-plex-mono-vietnamese-400-normal-DDuiU_S-.woff) format("woff");unicode-range:U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+0300-0301,U+0303-0304,U+0308-0309,U+0323,U+0329,U+1EA0-1EF9,U+20AB}@font-face{font-family:IBM Plex Mono;font-style:normal;font-display:swap;font-weight:400;src:url(./ibm-plex-mono-latin-ext-400-normal-BmRBH3aV.woff2) format("woff2"),url(./ibm-plex-mono-latin-ext-400-normal-D3D2R8hC.woff) format("woff");unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:IBM Plex Mono;font-style:normal;font-display:swap;font-weight:400;src:url(./ibm-plex-mono-latin-400-normal-DMJ8VG8y.woff2) format("woff2"),url(./ibm-plex-mono-latin-400-normal-CvHOgSBP.woff) format("woff");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:IBM Plex Mono;font-style:normal;font-display:swap;font-weight:500;src:url(./ibm-plex-mono-cyrillic-ext-500-normal-BqneJy0T.woff2) format("woff2"),url(./ibm-plex-mono-cyrillic-ext-500-normal-BIfNGwUT.woff) format("woff");unicode-range:U+0460-052F,U+1C80-1C8A,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:IBM Plex Mono;font-style:normal;font-display:swap;font-weight:500;src:url(./ibm-plex-mono-cyrillic-500-normal-Bq9vWWag.woff2) format("woff2"),url(./ibm-plex-mono-cyrillic-500-normal-Ael50iVv.woff) format("woff");unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}@font-face{font-family:IBM Plex Mono;font-style:normal;font-display:swap;font-weight:500;src:url(./ibm-plex-mono-vietnamese-500-normal-DZ4AoWbu.woff2) format("woff2"),url(./ibm-plex-mono-vietnamese-500-normal-C8zxqsMH.woff) format("woff");unicode-range:U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+0300-0301,U+0303-0304,U+0308-0309,U+0323,U+0329,U+1EA0-1EF9,U+20AB}@font-face{font-family:IBM Plex Mono;font-style:normal;font-display:swap;font-weight:500;src:url(./ibm-plex-mono-latin-ext-500-normal-CAhNIIs5.woff2) format("woff2"),url(./ibm-plex-mono-latin-ext-500-normal-CZ70TYgx.woff) format("woff");unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:IBM Plex Mono;font-style:normal;font-display:swap;font-weight:500;src:url(./ibm-plex-mono-latin-500-normal-DSY6xOcd.woff2) format("woff2"),url(./ibm-plex-mono-latin-500-normal-CB9ihrfo.woff) format("woff");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:"Source Serif 4";font-style:normal;font-display:swap;font-weight:400;src:url(./source-serif-4-cyrillic-ext-400-normal-CWV284fw.woff2) format("woff2"),url(./source-serif-4-cyrillic-ext-400-normal-DLkyKLvH.woff) format("woff");unicode-range:U+0460-052F,U+1C80-1C8A,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:"Source Serif 4";font-style:normal;font-display:swap;font-weight:400;src:url(./source-serif-4-cyrillic-400-normal-C44pakCn.woff2) format("woff2"),url(./source-serif-4-cyrillic-400-normal-B8Z6Jvzv.woff) format("woff");unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}@font-face{font-family:"Source Serif 4";font-style:normal;font-display:swap;font-weight:400;src:url(./source-serif-4-greek-400-normal-Cw5-AHNN.woff2) format("woff2"),url(./source-serif-4-greek-400-normal-BccYJ-vZ.woff) format("woff");unicode-range:U+0370-0377,U+037A-037F,U+0384-038A,U+038C,U+038E-03A1,U+03A3-03FF}@font-face{font-family:"Source Serif 4";font-style:normal;font-display:swap;font-weight:400;src:url(./source-serif-4-vietnamese-400-normal-BbG3LG1A.woff2) format("woff2"),url(./source-serif-4-vietnamese-400-normal-DR1UuFon.woff) format("woff");unicode-range:U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+0300-0301,U+0303-0304,U+0308-0309,U+0323,U+0329,U+1EA0-1EF9,U+20AB}@font-face{font-family:"Source Serif 4";font-style:normal;font-display:swap;font-weight:400;src:url(./source-serif-4-latin-ext-400-normal-Cp7z-ARB.woff2) format("woff2"),url(./source-serif-4-latin-ext-400-normal-CEpydyUl.woff) format("woff");unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:"Source Serif 4";font-style:normal;font-display:swap;font-weight:400;src:url(./source-serif-4-latin-400-normal-DJ5YJwmz.woff2) format("woff2"),url(./source-serif-4-latin-400-normal-Dn3IlU-Z.woff) format("woff");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:"Source Serif 4";font-style:normal;font-display:swap;font-weight:600;src:url(./source-serif-4-cyrillic-ext-600-normal-D_E8FDgP.woff2) format("woff2"),url(./source-serif-4-cyrillic-ext-600-normal-DiT2IGQm.woff) format("woff");unicode-range:U+0460-052F,U+1C80-1C8A,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:"Source Serif 4";font-style:normal;font-display:swap;font-weight:600;src:url(./source-serif-4-cyrillic-600-normal-BDP5YDHD.woff2) format("woff2"),url(./source-serif-4-cyrillic-600-normal-DFnC3vAY.woff) format("woff");unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}@font-face{font-family:"Source Serif 4";font-style:normal;font-display:swap;font-weight:600;src:url(./source-serif-4-greek-600-normal-DdRkKr-1.woff2) format("woff2"),url(./source-serif-4-greek-600-normal-DhXQw1Kl.woff) format("woff");unicode-range:U+0370-0377,U+037A-037F,U+0384-038A,U+038C,U+038E-03A1,U+03A3-03FF}@font-face{font-family:"Source Serif 4";font-style:normal;font-display:swap;font-weight:600;src:url(./source-serif-4-vietnamese-600-normal-CznyfUKR.woff2) format("woff2"),url(./source-serif-4-vietnamese-600-normal-B0WJbuqT.woff) format("woff");unicode-range:U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+0300-0301,U+0303-0304,U+0308-0309,U+0323,U+0329,U+1EA0-1EF9,U+20AB}@font-face{font-family:"Source Serif 4";font-style:normal;font-display:swap;font-weight:600;src:url(./source-serif-4-latin-ext-600-normal-0sIUyHMO.woff2) format("woff2"),url(./source-serif-4-latin-ext-600-normal-C6NNqpJh.woff) format("woff");unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:"Source Serif 4";font-style:normal;font-display:swap;font-weight:600;src:url(./source-serif-4-latin-600-normal-DouSKlru.woff2) format("woff2"),url(./source-serif-4-latin-600-normal-DMD1h6_f.woff) format("woff");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}._stage_2307v_2{background-color:var(--diff-canvas);background-image:repeating-conic-gradient(var(--muted) 0% 25%,var(--diff-canvas) 0% 50%);background-size:12px 12px;box-shadow:inset 0 0 0 1px var(--border)}@keyframes _wait-walk_1s58a_1{0%{top:-40%}to{top:100%}}@media(prefers-reduced-motion:no-preference){._walker_1s58a_11{animation:_wait-walk_1s58a_1 1.7s var(--motion-ease) infinite}}._itemActive_xc7sz_1{background-color:var(--accent)}._selection_xc7sz_5{display:none}@supports (anchor-name: --stack-active){._itemActive_xc7sz_1{background-color:transparent;anchor-name:--stack-active}._selection_xc7sz_5{display:block;pointer-events:none;position:absolute;z-index:0;position-anchor:--stack-active;top:anchor(top);left:anchor(left);width:anchor-size(width);height:anchor-size(height);border-radius:var(--radius);background-color:var(--accent)}}@media(prefers-reduced-motion:no-preference){._selection_xc7sz_5{transition-property:top,left,width,height;transition-duration:var(--motion);transition-timing-function:var(--motion-ease)}}@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-space-y-reverse:0;--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-ordinal:initial;--tw-slashed-zero:initial;--tw-numeric-figure:initial;--tw-numeric-spacing:initial;--tw-numeric-fraction:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid;--tw-duration:initial;--tw-ease:initial;--tw-content:"";--tw-animation-delay:0s;--tw-animation-direction:normal;--tw-animation-duration:initial;--tw-animation-fill-mode:none;--tw-animation-iteration-count:1;--tw-enter-blur:0;--tw-enter-opacity:1;--tw-enter-rotate:0;--tw-enter-scale:1;--tw-enter-translate-x:0;--tw-enter-translate-y:0;--tw-exit-blur:0;--tw-exit-opacity:1;--tw-exit-rotate:0;--tw-exit-scale:1;--tw-exit-translate-x:0;--tw-exit-translate-y:0}}}@layer theme{:root,:host{--font-sans:"IBM Plex Sans", ui-sans-serif, system-ui, sans-serif;--font-mono:"IBM Plex Mono", ui-monospace, "SF Mono", Menlo, monospace;--color-white:#fff;--spacing:.25rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--text-lg:1.125rem;--text-lg--line-height:calc(1.75 / 1.125);--font-weight-normal:400;--font-weight-medium:500;--font-weight-semibold:600;--tracking-wide:.025em;--leading-snug:1.375;--leading-relaxed:1.625;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:"IBM Plex Sans", ui-sans-serif, system-ui, sans-serif;--default-mono-font-family:"IBM Plex Mono", ui-monospace, "SF Mono", Menlo, monospace}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring:where(:not(iframe)){outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab,red,red)){::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}*{border-color:var(--border)}html,body,#root{height:100%}html{view-transition-name:none}body{background-color:var(--background);color:var(--foreground);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-family:IBM Plex Sans,ui-sans-serif,system-ui,sans-serif;font-size:14px;line-height:1.55}code,pre,kbd{font-family:var(--font-mono)}}@layer components;@layer utilities{.pointer-events-none{pointer-events:none}.visible{visibility:visible}.sr-only{clip-path:inset(50%);white-space:nowrap;border-width:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.absolute{position:absolute}.relative{position:relative}.sticky{position:sticky}.inset-x-0{inset-inline:0}.inset-y-0{inset-block:0}.inset-y-1\.5{inset-block:calc(var(--spacing) * 1.5)}.top-0{top:0}.top-1\/2{top:50%}.top-\[28\%\]{top:28%}.left-0{left:0}.z-1{z-index:1}.z-10{z-index:10}.z-50{z-index:50}.m-0{margin:0}.mx-1{margin-inline:var(--spacing)}.mx-3{margin-inline:calc(var(--spacing) * 3)}.mx-\[0\.08em\]{margin-inline:.08em}.mx-auto{margin-inline:auto}.mt-0\.5{margin-top:calc(var(--spacing) * .5)}.mt-1{margin-top:var(--spacing)}.mt-4{margin-top:calc(var(--spacing) * 4)}.mt-8{margin-top:calc(var(--spacing) * 8)}.mt-px{margin-top:1px}.mb-1{margin-bottom:var(--spacing)}.mb-2{margin-bottom:calc(var(--spacing) * 2)}.mb-3{margin-bottom:calc(var(--spacing) * 3)}.mb-4{margin-bottom:calc(var(--spacing) * 4)}.mb-5{margin-bottom:calc(var(--spacing) * 5)}.mb-6{margin-bottom:calc(var(--spacing) * 6)}.mb-8{margin-bottom:calc(var(--spacing) * 8)}.mb-12{margin-bottom:calc(var(--spacing) * 12)}.ml-auto{margin-left:auto}.block{display:block}.contents{display:contents}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline{display:inline}.inline-flex{display:inline-flex}.size-2{width:calc(var(--spacing) * 2);height:calc(var(--spacing) * 2)}.size-2\.5{width:calc(var(--spacing) * 2.5);height:calc(var(--spacing) * 2.5)}.size-3\.5{width:calc(var(--spacing) * 3.5);height:calc(var(--spacing) * 3.5)}.size-4{width:calc(var(--spacing) * 4);height:calc(var(--spacing) * 4)}.size-6{width:calc(var(--spacing) * 6);height:calc(var(--spacing) * 6)}.size-8{width:calc(var(--spacing) * 8);height:calc(var(--spacing) * 8)}.size-9{width:calc(var(--spacing) * 9);height:calc(var(--spacing) * 9)}.size-full{width:100%;height:100%}.h-6{height:calc(var(--spacing) * 6)}.h-7{height:calc(var(--spacing) * 7)}.h-8{height:calc(var(--spacing) * 8)}.h-9{height:calc(var(--spacing) * 9)}.h-10{height:calc(var(--spacing) * 10)}.h-\[1\.1rem\]{height:1.1rem}.h-\[44\%\]{height:44%}.h-auto{height:auto}.h-full{height:100%}.min-h-0{min-height:0}.w-0\.5{width:calc(var(--spacing) * .5)}.w-2{width:calc(var(--spacing) * 2)}.w-3{width:calc(var(--spacing) * 3)}.w-5{width:calc(var(--spacing) * 5)}.w-\[3px\]{width:3px}.w-\[calc\(100\%-24px\)\]{width:calc(100% - 24px)}.w-fit{width:fit-content}.w-full{width:100%}.w-px{width:1px}.max-w-\[10rem\]{max-width:10rem}.max-w-\[68ch\]{max-width:68ch}.max-w-\[min\(24rem\,calc\(100vw-2rem\)\)\]{max-width:min(24rem,100vw - 2rem)}.max-w-full{max-width:100%}.max-w-none{max-width:none}.min-w-0{min-width:0}.min-w-8{min-width:calc(var(--spacing) * 8)}.min-w-9{min-width:calc(var(--spacing) * 9)}.min-w-10{min-width:calc(var(--spacing) * 10)}.flex-1{flex:1}.flex-none{flex:none}.flex-shrink{flex-shrink:1}.shrink-0{flex-shrink:0}.origin-\(--radix-tooltip-content-transform-origin\){transform-origin:var(--radix-tooltip-content-transform-origin)}.-translate-x-1\/2{--tw-translate-x: -50% ;translate:var(--tw-translate-x) var(--tw-translate-y)}.-translate-y-1\/2{--tw-translate-y: -50% ;translate:var(--tw-translate-x) var(--tw-translate-y)}.-rotate-90{rotate:-90deg}.cursor-col-resize{cursor:col-resize}.cursor-pointer{cursor:pointer}.touch-none{touch-action:none}.resize{resize:both}.list-disc{list-style-type:disc}.list-none{list-style-type:none}.auto-cols-\[minmax\(16rem\,1fr\)\]{grid-auto-columns:minmax(16rem,1fr)}.grid-flow-col{grid-auto-flow:column}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-baseline{align-items:baseline}.items-center{align-items:center}.items-start{align-items:flex-start}.items-stretch{align-items:stretch}.justify-center{justify-content:center}.justify-start{justify-content:flex-start}.gap-0{gap:0}.gap-1{gap:var(--spacing)}.gap-1\.5{gap:calc(var(--spacing) * 1.5)}.gap-2{gap:calc(var(--spacing) * 2)}.gap-2\.5{gap:calc(var(--spacing) * 2.5)}.gap-3{gap:calc(var(--spacing) * 3)}.gap-4{gap:calc(var(--spacing) * 4)}.gap-\[0\.28rem\]{gap:.28rem}:where(.space-y-1>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(var(--spacing) * var(--tw-space-y-reverse));margin-block-end:calc(var(--spacing) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-2>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 2) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 2) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-8>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 8) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 8) * calc(1 - var(--tw-space-y-reverse)))}.gap-x-3{column-gap:calc(var(--spacing) * 3)}.gap-y-1{row-gap:var(--spacing)}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.scroll-smooth{scroll-behavior:smooth}.rounded-\[0\.22em\]{border-radius:.22em}.rounded-\[1px\]{border-radius:1px}.rounded-\[inherit\]{border-radius:inherit}.rounded-full{border-radius:3.40282e38px}.rounded-lg{border-radius:calc(var(--radius) * 1.3)}.rounded-md{border-radius:var(--radius)}.rounded-none{border-radius:0}.rounded-sm{border-radius:calc(var(--radius) * .7)}.border{border-style:var(--tw-border-style);border-width:1px}.border-0{border-style:var(--tw-border-style);border-width:0}.border-r{border-right-style:var(--tw-border-style);border-right-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-border{border-color:var(--border)}.border-input{border-color:var(--input)}.border-primary{border-color:var(--primary)}.border-transparent{border-color:#0000}.bg-\[color-mix\(in_srgb\,var\(--foreground\)_8\%\,transparent\)\]{background-color:var(--foreground)}@supports (color:color-mix(in lab,red,red)){.bg-\[color-mix\(in_srgb\,var\(--foreground\)_8\%\,transparent\)\]{background-color:color-mix(in srgb,var(--foreground) 8%,transparent)}}.bg-\[var\(--diff-canvas\)\]{background-color:var(--diff-canvas)}.bg-\[var\(--strand\,var\(--primary\)\)\]{background-color:var(--strand,var(--primary))}.bg-add,.bg-add\/38{background-color:var(--add)}@supports (color:color-mix(in lab,red,red)){.bg-add\/38{background-color:color-mix(in oklab,var(--add) 38%,transparent)}}.bg-background{background-color:var(--background)}.bg-border{background-color:var(--border)}.bg-card{background-color:var(--card)}.bg-del,.bg-del\/38{background-color:var(--del)}@supports (color:color-mix(in lab,red,red)){.bg-del\/38{background-color:color-mix(in oklab,var(--del) 38%,transparent)}}.bg-destructive,.bg-destructive\/20{background-color:var(--destructive)}@supports (color:color-mix(in lab,red,red)){.bg-destructive\/20{background-color:color-mix(in oklab,var(--destructive) 20%,transparent)}}.bg-foreground{background-color:var(--foreground)}.bg-muted-foreground{background-color:var(--muted-foreground)}.bg-primary{background-color:var(--primary)}.bg-secondary{background-color:var(--secondary)}.bg-transparent{background-color:#0000}.box-decoration-clone{-webkit-box-decoration-break:clone;box-decoration-break:clone}.p-0{padding:0}.px-0\.5{padding-inline:calc(var(--spacing) * .5)}.px-2{padding-inline:calc(var(--spacing) * 2)}.px-2\.5{padding-inline:calc(var(--spacing) * 2.5)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-4{padding-inline:calc(var(--spacing) * 4)}.px-5{padding-inline:calc(var(--spacing) * 5)}.px-6{padding-inline:calc(var(--spacing) * 6)}.px-8{padding-inline:calc(var(--spacing) * 8)}.px-10{padding-inline:calc(var(--spacing) * 10)}.px-\[0\.32em\]{padding-inline:.32em}.py-0\.5{padding-block:calc(var(--spacing) * .5)}.py-1{padding-block:var(--spacing)}.py-1\.5{padding-block:calc(var(--spacing) * 1.5)}.py-2{padding-block:calc(var(--spacing) * 2)}.py-3{padding-block:calc(var(--spacing) * 3)}.py-4{padding-block:calc(var(--spacing) * 4)}.py-5{padding-block:calc(var(--spacing) * 5)}.py-6{padding-block:calc(var(--spacing) * 6)}.py-8{padding-block:calc(var(--spacing) * 8)}.py-\[0\.12em\]{padding-block:.12em}.pt-2{padding-top:calc(var(--spacing) * 2)}.pt-6{padding-top:calc(var(--spacing) * 6)}.pb-1{padding-bottom:var(--spacing)}.pb-4{padding-bottom:calc(var(--spacing) * 4)}.pb-8{padding-bottom:calc(var(--spacing) * 8)}.pl-5{padding-left:calc(var(--spacing) * 5)}.text-left{text-align:left}.font-mono{font-family:IBM Plex Mono,ui-monospace,SF Mono,Menlo,monospace}.font-sans{font-family:IBM Plex Sans,ui-sans-serif,system-ui,sans-serif}.font-serif{font-family:"Source Serif 4",Iowan Old Style,Georgia,serif}.text-lg{font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.text-\[0\.86em\]{font-size:.86em}.text-\[1\.75rem\]{font-size:1.75rem}.text-\[10px\]{font-size:10px}.text-\[11px\]{font-size:11px}.leading-none{--tw-leading:1;line-height:1}.leading-relaxed{--tw-leading:var(--leading-relaxed);line-height:var(--leading-relaxed)}.leading-snug{--tw-leading:var(--leading-snug);line-height:var(--leading-snug)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-normal{--tw-font-weight:var(--font-weight-normal);font-weight:var(--font-weight-normal)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-wide{--tw-tracking:var(--tracking-wide);letter-spacing:var(--tracking-wide)}.whitespace-normal{white-space:normal}.whitespace-nowrap{white-space:nowrap}.text-add{color:var(--add)}.text-background{color:var(--background)}.text-del{color:var(--del)}.text-destructive{color:var(--destructive)}.text-foreground{color:var(--foreground)}.text-muted-foreground{color:var(--muted-foreground)}.text-primary{color:var(--primary)}.text-primary-foreground{color:var(--primary-foreground)}.text-secondary-foreground{color:var(--secondary-foreground)}.text-warn{color:var(--warn)}.text-white{color:var(--color-white)}.not-italic{font-style:normal}.tabular-nums{--tw-numeric-spacing:tabular-nums;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,)}.underline-offset-4{text-underline-offset:4px}.accent-primary{accent-color:var(--primary)}.opacity-45{opacity:.45}.shadow{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-xs{--tw-shadow:0 1px 2px 0 var(--tw-shadow-color,#0000000d);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.transition-\[border-color\]{transition-property:border-color;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-\[color\,background-color\,border-color\,box-shadow\,opacity\]{transition-property:color,background-color,border-color,box-shadow,opacity;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-opacity{transition-property:opacity;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-150{--tw-duration:.15s;transition-duration:.15s}.duration-\[var\(--motion\)\]{--tw-duration:var(--motion);transition-duration:var(--motion)}.ease-\[var\(--motion-ease\)\]{--tw-ease:var(--motion-ease);transition-timing-function:var(--motion-ease)}.outline-none{--tw-outline-style:none;outline-style:none}.select-none{-webkit-user-select:none;user-select:none}.after\:absolute:after{content:var(--tw-content);position:absolute}.after\:inset-y-0:after{content:var(--tw-content);inset-block:0}.after\:left-1\/2:after{content:var(--tw-content);left:50%}.after\:w-px:after{content:var(--tw-content);width:1px}.after\:-translate-x-1\/2:after{content:var(--tw-content);--tw-translate-x: -50% ;translate:var(--tw-translate-x) var(--tw-translate-y)}.after\:bg-border:after{content:var(--tw-content);background-color:var(--border)}.after\:transition-\[background-color\]:after{content:var(--tw-content);transition-property:background-color;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.after\:duration-\[var\(--motion\)\]:after{content:var(--tw-content);--tw-duration:var(--motion);transition-duration:var(--motion)}.after\:ease-\[var\(--motion-ease\)\]:after{content:var(--tw-content);--tw-ease:var(--motion-ease);transition-timing-function:var(--motion-ease)}.last\:mb-0:last-child{margin-bottom:0}@media(hover:hover){.hover\:bg-accent:hover{background-color:var(--accent)}.hover\:bg-destructive\/90:hover{background-color:var(--destructive)}@supports (color:color-mix(in lab,red,red)){.hover\:bg-destructive\/90:hover{background-color:color-mix(in oklab,var(--destructive) 90%,transparent)}}.hover\:bg-muted:hover{background-color:var(--muted)}.hover\:bg-primary\/90:hover{background-color:var(--primary)}@supports (color:color-mix(in lab,red,red)){.hover\:bg-primary\/90:hover{background-color:color-mix(in oklab,var(--primary) 90%,transparent)}}.hover\:bg-secondary\/80:hover{background-color:var(--secondary)}@supports (color:color-mix(in lab,red,red)){.hover\:bg-secondary\/80:hover{background-color:color-mix(in oklab,var(--secondary) 80%,transparent)}}.hover\:bg-transparent:hover{background-color:#0000}.hover\:text-accent-foreground:hover{color:var(--accent-foreground)}.hover\:text-muted-foreground:hover{color:var(--muted-foreground)}.hover\:text-warn:hover{color:var(--warn)}.hover\:underline:hover{text-decoration-line:underline}.hover\:after\:bg-primary\/60:hover:after{content:var(--tw-content);background-color:var(--primary)}@supports (color:color-mix(in lab,red,red)){.hover\:after\:bg-primary\/60:hover:after{background-color:color-mix(in oklab,var(--primary) 60%,transparent)}}.hover\:after\:bg-primary\/70:hover:after{content:var(--tw-content);background-color:var(--primary)}@supports (color:color-mix(in lab,red,red)){.hover\:after\:bg-primary\/70:hover:after{background-color:color-mix(in oklab,var(--primary) 70%,transparent)}}}.focus-visible\:border-ring:focus-visible{border-color:var(--ring)}.focus-visible\:ring-1:focus-visible{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus-visible\:ring-2:focus-visible{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus-visible\:ring-ring:focus-visible,.focus-visible\:ring-ring\/50:focus-visible{--tw-ring-color:var(--ring)}@supports (color:color-mix(in lab,red,red)){.focus-visible\:ring-ring\/50:focus-visible{--tw-ring-color:color-mix(in oklab, var(--ring) 50%, transparent)}}.focus-visible\:outline-hidden:focus-visible{--tw-outline-style:none;outline-style:none}@media(forced-colors:active){.focus-visible\:outline-hidden:focus-visible{outline-offset:2px;outline:2px solid #0000}}.focus-visible\:outline-none:focus-visible{--tw-outline-style:none;outline-style:none}.disabled\:pointer-events-none:disabled{pointer-events:none}.disabled\:opacity-50:disabled{opacity:.5}.has-\[\>svg\]\:px-2\.5:has(>svg){padding-inline:calc(var(--spacing) * 2.5)}.has-\[\>svg\]\:px-3:has(>svg){padding-inline:calc(var(--spacing) * 3)}.has-\[\>svg\]\:px-4:has(>svg){padding-inline:calc(var(--spacing) * 4)}.aria-\[orientation\=horizontal\]\:h-2[aria-orientation=horizontal]{height:calc(var(--spacing) * 2)}.aria-\[orientation\=horizontal\]\:w-full[aria-orientation=horizontal]{width:100%}.aria-\[orientation\=horizontal\]\:after\:left-0[aria-orientation=horizontal]:after{content:var(--tw-content);left:0}.aria-\[orientation\=horizontal\]\:after\:h-px[aria-orientation=horizontal]:after{content:var(--tw-content);height:1px}.aria-\[orientation\=horizontal\]\:after\:w-full[aria-orientation=horizontal]:after{content:var(--tw-content);width:100%}.aria-\[orientation\=horizontal\]\:after\:translate-x-0[aria-orientation=horizontal]:after{content:var(--tw-content);--tw-translate-x:0px;translate:var(--tw-translate-x) var(--tw-translate-y)}.aria-\[orientation\=horizontal\]\:after\:-translate-y-1\/2[aria-orientation=horizontal]:after{content:var(--tw-content);--tw-translate-y: -50% ;translate:var(--tw-translate-x) var(--tw-translate-y)}.aria-\[orientation\=vertical\]\:flex-col[aria-orientation=vertical]{flex-direction:column}.data-\[orientation\=horizontal\]\:h-px[data-orientation=horizontal]{height:1px}.data-\[orientation\=horizontal\]\:w-full[data-orientation=horizontal]{width:100%}.data-\[orientation\=vertical\]\:h-full[data-orientation=vertical]{height:100%}.data-\[orientation\=vertical\]\:w-px[data-orientation=vertical]{width:1px}.data-\[state\=closed\]\:animate-out[data-state=closed]{animation:exit var(--tw-animation-duration,var(--tw-duration,.15s))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)}.data-\[state\=closed\]\:fade-out-0[data-state=closed]{--tw-exit-opacity:0}.data-\[state\=delayed-open\]\:animate-in[data-state=delayed-open]{animation:enter var(--tw-animation-duration,var(--tw-duration,.15s))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)}.data-\[state\=delayed-open\]\:fade-in-0[data-state=delayed-open]{--tw-enter-opacity:0}.data-\[state\=instant-open\]\:animate-in[data-state=instant-open]{animation:enter var(--tw-animation-duration,var(--tw-duration,.15s))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)}.data-\[state\=instant-open\]\:fade-in-0[data-state=instant-open]{--tw-enter-opacity:0}.data-\[state\=on\]\:bg-accent[data-state=on]{background-color:var(--accent)}.data-\[state\=on\]\:text-accent-foreground[data-state=on]{color:var(--accent-foreground)}@media(prefers-reduced-motion:no-preference){.motion-safe\:after\:transition-colors:after{content:var(--tw-content);transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}}@media not all and (min-width:40rem){.max-sm\:hidden{display:none}}@media(min-width:800px){.min-\[800px\]\:flex-row{flex-direction:row}.min-\[800px\]\:flex-wrap{flex-wrap:wrap}.min-\[800px\]\:items-center{align-items:center}.min-\[800px\]\:justify-between{justify-content:space-between}.min-\[800px\]\:justify-end{justify-content:flex-end}}.\[\&_svg\]\:pointer-events-none svg{pointer-events:none}.\[\&_svg\]\:shrink-0 svg{flex-shrink:0}.\[\&_svg\:not\(\[class\*\=\'size-\'\]\)\]\:size-4 svg:not([class*=size-]){width:calc(var(--spacing) * 4);height:calc(var(--spacing) * 4)}.\[\&\>svg\]\:pointer-events-none>svg{pointer-events:none}.\[\&\>svg\]\:size-3>svg{width:calc(var(--spacing) * 3);height:calc(var(--spacing) * 3)}[data-motion=group] .\[\[data-motion\=group\]_\&\]\:\[view-transition-name\:review-copy\]{view-transition-name:review-copy}[data-motion=group] .\[\[data-motion\=group\]_\&\]\:\[view-transition-name\:review-overview\]{view-transition-name:review-overview}[data-motion=group] .\[\[data-motion\=group\]_\&\]\:\[view-transition-name\:review-strand\]{view-transition-name:review-strand}[data-motion=scene] .\[\[data-motion\=scene\]_\&\]\:\[view-transition-name\:review-scene\]{view-transition-name:review-scene}}@property --tw-animation-delay{syntax:"*";inherits:false;initial-value:0s}@property --tw-animation-direction{syntax:"*";inherits:false;initial-value:normal}@property --tw-animation-duration{syntax:"*";inherits:false}@property --tw-animation-fill-mode{syntax:"*";inherits:false;initial-value:none}@property --tw-animation-iteration-count{syntax:"*";inherits:false;initial-value:1}@property --tw-enter-blur{syntax:"*";inherits:false;initial-value:0}@property --tw-enter-opacity{syntax:"*";inherits:false;initial-value:1}@property --tw-enter-rotate{syntax:"*";inherits:false;initial-value:0}@property --tw-enter-scale{syntax:"*";inherits:false;initial-value:1}@property --tw-enter-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-enter-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-exit-blur{syntax:"*";inherits:false;initial-value:0}@property --tw-exit-opacity{syntax:"*";inherits:false;initial-value:1}@property --tw-exit-rotate{syntax:"*";inherits:false;initial-value:0}@property --tw-exit-scale{syntax:"*";inherits:false;initial-value:1}@property --tw-exit-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-exit-translate-y{syntax:"*";inherits:false;initial-value:0}:root{color-scheme:light;--motion:.18s;--motion-brief:.5s;--motion-brief-gap:50ms;--motion-ease:cubic-bezier(.2, .8, .2, 1);--radius:.45rem;--background:#f4f6f8;--foreground:#171b22;--card:#fff;--card-foreground:#171b22;--popover:#fff;--popover-foreground:#171b22;--primary:#3d4fd8;--primary-foreground:#fff;--secondary:#e8ecf1;--secondary-foreground:#171b22;--muted:#e8ecf1;--muted-foreground:#5c6570;--accent:#e4e8f4;--accent-foreground:#171b22;--destructive:#cf222e;--border:#d5dbe3;--input:#d5dbe3;--ring:#3d4fd8;--add:#1a7f37;--del:#cf222e;--warn:#9a6700;--add-bg:#1a7f3729;--del-bg:#cf222e29;--diff-canvas:#fff;--diff-fg:#1f2328;--diff-add-line:#e6ffec;--diff-add-num:#ccffd8;--diff-add-word:#abf2bc;--diff-del-line:#ffebe9;--diff-del-num:#ffd7d5;--diff-del-word:#ff818266;--diff-hunk:#ddf4ff;--diff-hover:#f6f8fa;--strand-0:#2458b5;--strand-1:#9a5b00;--strand-2:#6b3d96;--strand-3:#0b6e78;--strand-4:#9a356e;--strand-5:#3a5366}.dark{color-scheme:dark;--background:#12151c;--foreground:#e6eaf0;--card:#1a1e27;--card-foreground:#e6eaf0;--popover:#1a1e27;--popover-foreground:#e6eaf0;--primary:#8b9cff;--primary-foreground:#12151c;--secondary:#252a33;--secondary-foreground:#e6eaf0;--muted:#252a33;--muted-foreground:#8b939e;--accent:#2a3148;--accent-foreground:#e6eaf0;--destructive:#f85149;--border:#2c3340;--input:#2c3340;--ring:#8b9cff;--add:#3fb950;--del:#f85149;--warn:#d4a017;--add-bg:#3fb95029;--del-bg:#f8514929;--diff-canvas:#0d1117;--diff-fg:#e6edf3;--diff-add-line:#2ea04326;--diff-add-num:#2ea04366;--diff-add-word:#2ea04366;--diff-del-line:#f8514926;--diff-del-num:#f8514966;--diff-del-word:#f8514966;--diff-hunk:#388bfd1a;--diff-hover:#161b22;--strand-0:#8fb4f0;--strand-1:#e0a64a;--strand-2:#c9a3e8;--strand-3:#6ed0d6;--strand-4:#e399c0;--strand-5:#9ab0c2}::view-transition-old(review-strand){mix-blend-mode:normal;animation-timing-function:var(--motion-ease);animation-fill-mode:both}::view-transition-new(review-strand){mix-blend-mode:normal;animation-timing-function:var(--motion-ease);animation-fill-mode:both}::view-transition-old(review-copy){mix-blend-mode:normal;animation-timing-function:var(--motion-ease);animation-fill-mode:both}::view-transition-new(review-copy){mix-blend-mode:normal;animation-timing-function:var(--motion-ease);animation-fill-mode:both}::view-transition-old(review-overview){mix-blend-mode:normal;animation-timing-function:var(--motion-ease);animation-fill-mode:both}::view-transition-new(review-overview){mix-blend-mode:normal;animation-timing-function:var(--motion-ease);animation-fill-mode:both}::view-transition-old(review-scene){mix-blend-mode:normal;animation-timing-function:var(--motion-ease);animation-fill-mode:both}::view-transition-new(review-scene){mix-blend-mode:normal;animation-timing-function:var(--motion-ease);animation-fill-mode:both}::view-transition-old(review-strand){height:100%;animation-duration:var(--motion-brief);overflow:clip}::view-transition-new(review-strand){height:100%;animation-duration:var(--motion-brief);overflow:clip}::view-transition-old(review-strand){animation-name:motion-fade-out}::view-transition-new(review-strand){animation-name:motion-fade-in}::view-transition-group(review-strand){animation-duration:var(--motion-brief);animation-timing-function:var(--motion-ease)}::view-transition-image-pair(review-strand){isolation:isolate}::view-transition-old(review-copy){animation-name:motion-slide-down-out;animation-duration:calc((var(--motion-brief) - var(--motion-brief-gap)) / 2)}::view-transition-new(review-copy){animation-name:motion-slide-up-in;animation-duration:calc((var(--motion-brief) - var(--motion-brief-gap)) / 2);animation-delay:calc((var(--motion-brief) + var(--motion-brief-gap)) / 2)}::view-transition-group(review-copy){animation:none}::view-transition-old(review-overview){animation-name:motion-fade-out;animation-duration:var(--motion-brief)}::view-transition-new(review-overview){animation-name:motion-fade-in;animation-duration:var(--motion-brief)}::view-transition-group(review-overview){animation:none}::view-transition-old(review-scene){animation-name:motion-fade-out;animation-duration:var(--motion)}::view-transition-new(review-scene){animation-name:motion-fade-in;animation-duration:var(--motion)}::view-transition-group(review-scene){animation-duration:var(--motion);animation-timing-function:var(--motion-ease)}::view-transition-image-pair(review-scene){isolation:isolate}@keyframes motion-fade-out{to{opacity:0}}@keyframes motion-fade-in{0%{opacity:0}}@keyframes motion-slide-down-out{to{opacity:0;translate:0 .75rem}}@keyframes motion-slide-up-in{0%{opacity:0;translate:0 .75rem}}@media(prefers-reduced-motion:reduce){*,:before,:after{scroll-behavior:auto!important;transition-duration:.01ms!important;animation-duration:.01ms!important;animation-iteration-count:1!important}::view-transition-group(*){animation:none!important}::view-transition-old(*){animation:none!important}::view-transition-new(*){animation:none!important}}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-ordinal{syntax:"*";inherits:false}@property --tw-slashed-zero{syntax:"*";inherits:false}@property --tw-numeric-figure{syntax:"*";inherits:false}@property --tw-numeric-spacing{syntax:"*";inherits:false}@property --tw-numeric-fraction{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-duration{syntax:"*";inherits:false}@property --tw-ease{syntax:"*";inherits:false}@property --tw-content{syntax:"*";inherits:false;initial-value:""}@keyframes enter{0%{opacity:var(--tw-enter-opacity,1);transform:translate3d(var(--tw-enter-translate-x,0),var(--tw-enter-translate-y,0),0)scale3d(var(--tw-enter-scale,1),var(--tw-enter-scale,1),var(--tw-enter-scale,1))rotate(var(--tw-enter-rotate,0));filter:blur(var(--tw-enter-blur,0))}}@keyframes exit{to{opacity:var(--tw-exit-opacity,1);transform:translate3d(var(--tw-exit-translate-x,0),var(--tw-exit-translate-y,0),0)scale3d(var(--tw-exit-scale,1),var(--tw-exit-scale,1),var(--tw-exit-scale,1))rotate(var(--tw-exit-rotate,0));filter:blur(var(--tw-exit-blur,0))}}
|
package/dist/ui/index.html
CHANGED
|
@@ -18,8 +18,8 @@
|
|
|
18
18
|
}
|
|
19
19
|
})();
|
|
20
20
|
</script>
|
|
21
|
-
<script type="module" crossorigin src="./assets/index-
|
|
22
|
-
<link rel="stylesheet" crossorigin href="./assets/index-
|
|
21
|
+
<script type="module" crossorigin src="./assets/index-CNz9KqcH.js"></script>
|
|
22
|
+
<link rel="stylesheet" crossorigin href="./assets/index-DJMUAjCi.css">
|
|
23
23
|
</head>
|
|
24
24
|
<body>
|
|
25
25
|
<div id="root"></div>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "comprehende",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "Local review assistant that groups git diffs so humans can comprehend AI code changes.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -68,6 +68,7 @@
|
|
|
68
68
|
"lucide-react": "^1.31.0",
|
|
69
69
|
"react": "^19.2.0",
|
|
70
70
|
"react-dom": "^19.2.0",
|
|
71
|
+
"react-markdown": "^10.1.0",
|
|
71
72
|
"react-resizable-panels": "^4.12.2",
|
|
72
73
|
"tailwind-merge": "^3.6.0",
|
|
73
74
|
"tailwindcss": "^4.3.3",
|
|
@@ -7,107 +7,72 @@ compatibility: Requires Node.js 24+, git, and a git work tree as the current wor
|
|
|
7
7
|
|
|
8
8
|
# Comprehende
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
Group a git diff into review concerns and serve a local UI. The point is cognitive offloading over cognitive surrender: the human gets a why and a what of their own to hold against the live diff, instead of adopting the change blind.
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
AI agents write a lot of code. That creates comprehension debt: the gap between what is in the repo and what humans actually understand. Unlike technical debt, nobody chooses it. It stays invisible until something breaks.
|
|
15
|
-
|
|
16
|
-
Cognitive offloading means handing off the *how* while keeping the *why* and the *what*. The human still has a view of the change. Cognitive surrender means adopting the agent's answer with no *why* or *what* of your own. That is how the debt grows.
|
|
17
|
-
|
|
18
|
-
This skill is for offloading. Group and summarize so a human can form their own view, then drill into the live git diff. Do not rubber-stamp. Do not hide risk behind file lists.
|
|
19
|
-
|
|
20
|
-
The review document is interpretation only: groups, summaries, hunk pointers. Never copy patch text, file bodies, or blame into `review.json`. Diffs are live `git` output at serve time. If git and the document disagree, git wins. Fix groups. Never invent a replacement hunk.
|
|
21
|
-
|
|
22
|
-
## Resolve the CLI
|
|
23
|
-
|
|
24
|
-
Run the published CLI at the pinned version, inside the repository under review.
|
|
12
|
+
Run every command inside the repository under review. Cwd is the repo; there is no `--repo` flag. Use the pinned CLI:
|
|
25
13
|
|
|
26
14
|
```sh
|
|
27
|
-
npx comprehende@0.
|
|
15
|
+
npx comprehende@0.5.0 <command>
|
|
28
16
|
```
|
|
29
17
|
|
|
30
|
-
Do not
|
|
18
|
+
The review document is interpretation only. It holds groups, summaries, and hunk pointers. Do not copy patch text into it. `serve` reads the diff from git.
|
|
31
19
|
|
|
32
20
|
## Workflow
|
|
33
21
|
|
|
34
|
-
1. Resolve
|
|
35
|
-
2. Run `npx comprehende@0.
|
|
36
|
-
3. Recover the why and write the what.
|
|
37
|
-
4.
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
- Windows: a unique folder under `%TEMP%` (cmd) or `[System.IO.Path]::GetTempPath()` (PowerShell)
|
|
42
|
-
- Node (any OS): `fs.mkdtempSync(path.join(os.tmpdir(), "comprehende-"))`
|
|
43
|
-
|
|
44
|
-
Unix example:
|
|
45
|
-
|
|
46
|
-
```sh
|
|
47
|
-
REVIEW_DIR=$(mktemp -d)
|
|
48
|
-
# write $REVIEW_DIR/review.json
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
5. Run `npx comprehende@0.4.0 validate --data "$REVIEW_DIR/review.json"`. On failure, fix groups or coverage. Never the diff.
|
|
52
|
-
6. Run `npx comprehende@0.4.0 serve --data "$REVIEW_DIR/review.json" --open` and give the user the localhost URL (`127.0.0.1` only).
|
|
53
|
-
|
|
54
|
-
Default `--head` is `HEAD`. Default `--base` is `origin/HEAD`, falling back to `main` or `master`.
|
|
22
|
+
1. Resolve base and head. Use the refs the user named; three-dot (`base...head`) is the merge request or branch diff. When the change is already on the default branch, use the request's recorded base and head SHAs; the moving default-branch `HEAD` includes later merges. When only the head SHA is known, base is the merge-base of that head with the named base branch. Fetch refs missing from the local clone. Done when both refs resolve in cwd; if one still does not resolve, stop and tell the user rather than guess a ref.
|
|
23
|
+
2. Run `npx comprehende@0.5.0 index [--base <ref>] [--head <ref>]` and keep the JSON outside the work tree (stdout or a temp file). Defaults: `--head` is `HEAD`; `--base` is `origin/HEAD`, falling back to `main` or `master`. The index lists hunk refs (path plus `@@` ranges), image files (`oldStart` and `newStart` 0), and `skipped` (lockfiles and non-image binaries). It carries no line content.
|
|
24
|
+
3. Recover the why and write the what. Read the sources listed under The why, read `git diff --stat <base>...<head>` and the diffs themselves, then write document `summary` (always) and document `why` (only when a source names the motive). Summaries come from the code, not the log.
|
|
25
|
+
4. Group the hunks by review concern, following the Grouping rules. Done when every hunk ref from the index appears in at least one group and every group has its `why`.
|
|
26
|
+
5. Write `review.json` in a fresh temp directory outside the repository (`mktemp -d` or the platform equivalent; the work tree stays untouched, with no new gitignore entries). Shape per [references/review.schema.json](./references/review.schema.json); worked example in [references/example.md](./references/example.md). Copy hunk objects verbatim from the index. Set document `size` from review burden, not `git diff --stat`.
|
|
27
|
+
6. Run `npx comprehende@0.5.0 validate --data "$REVIEW_DIR/review.json"` with the absolute path. On failure, fix groups or coverage; the diff is git's, leave it alone. Done when validate exits 0.
|
|
28
|
+
7. Run `npx comprehende@0.5.0 serve --data "$REVIEW_DIR/review.json" --open` and give the user the localhost URL (`127.0.0.1` only).
|
|
55
29
|
|
|
56
30
|
## The why
|
|
57
31
|
|
|
58
|
-
|
|
32
|
+
Document `why` names why the work exists, in one or two sentences. This should be inferred only from the sources below. If the sources don't tell us why the change exists, or they are missing, omit it, and let the summary be the main source for getting an idea of the changes. If sources are available and they tell the story, don't derive document `why` from the diff, from group structure, or from a motive you infer from the patch. A request naming two unrelated product stories with no unifying source also gets no document `why`; each story keeps its own group `why`s.
|
|
59
33
|
|
|
60
|
-
|
|
34
|
+
Sources are read, never copied: write your own prose from them, and keep ticket bodies, request descriptions, commit text, and transcript text out of `review.json`. Having references, quotes to them are fine.
|
|
61
35
|
|
|
62
|
-
|
|
36
|
+
- Tickets and issues. Copy `id` from the tracker the user named, plus `url`, `title`, and `part` when you have them. Read the ticket (host CLI, tools or MCP, whichever is available) when document `why` needs it. `part` goes on a ticket that belongs to one story, matching that story's group `part`; omit it only when the request or ticket title says the ticket covers the whole review. Commit count proves nothing about ticket scope.
|
|
37
|
+
- PR description and comments. When the user named a pull request or merge request, read its description and comments for context. PRs can also refer to tickets and issues in their description or branch names.
|
|
38
|
+
- Commit messages. `git log --format='%s%n%n%b' --end-of-options <base>...<head>`. They can clarify group `why`; document `why` needs one of the stronger sources above. These can also contain issues and tickets.
|
|
39
|
+
- Transcripts. A coding-agent (like Cursor, Claude Code, Codex, etc.) transcript you already have (this session, or a historical one) supplies the human's stated reason. The human's motive is the main driver, but the agent's plan and the whole conversation can matter here.
|
|
63
40
|
|
|
64
|
-
|
|
41
|
+
Every group has `why`: why this group exists. A source that names the concern is best. A foundation group with no source of its own says it enables the groups that depend on it; that is a complete `why`. Independent side work in its own part (docs-only, test-only) gets its own group `why` and leaves document `why` to the named motive.
|
|
65
42
|
|
|
66
|
-
|
|
43
|
+
## The what
|
|
67
44
|
|
|
68
|
-
Document `
|
|
45
|
+
Document `summary` is one or two sentences naming what the change is, including each independent story when the PR is mixed. Every review has one, even when `why` is absent. It is a what, not a motive.
|
|
69
46
|
|
|
70
|
-
|
|
47
|
+
Group `summary` is one sentence saying what the group is, describing how its hunks are related: "Calling the new validator from `core.ts` by the route in `routes.ts`", not a file-by-file recap or a path list.
|
|
71
48
|
|
|
72
|
-
|
|
49
|
+
## Grouping rules
|
|
73
50
|
|
|
74
|
-
|
|
51
|
+
- Group by review concern: why these hunks are read together. A directory qualifies only when that directory is the concern. Grouping needs the diffs; the index and the log alone are not enough.
|
|
52
|
+
- A hunk may appear in several groups when it matters in more than one story.
|
|
53
|
+
- `dependsOn` marks a real dependency inside one story: the reader needs the earlier group to understand this one. Reading order inside a story: contracts and foundations, then call sites, then tests, then mechanical work. Independent work stands alone with its own `part`, empty `dependsOn`, and nothing depending on it; a second feature or standalone documentation that could have been its own PR is independent work. When unsure whether two concerns depend on each other, keep them separate under different parts: a false split is easy to see, a false chain hides a mixed PR.
|
|
54
|
+
- `part` is a short name (a few words) for one independent story, the same on every group in that story; the UI colors shared parts together.
|
|
55
|
+
- Mechanical work (import reordering, identifier-only renames, generated code, formatting, type re-exports) is its own group that keeps every hunk as refs, risk visible rather than folded into a file list. When it exists only because of a story, it is that part's last group with nothing depending on it. When it could have been its own PR, it is its own part.
|
|
56
|
+
- `suggestedOrder` walks the whole review, independent parts included. Mechanical parts, independent documentation, and test-only cleanup go last.
|
|
57
|
+
- Document `size` is human review burden: `trivial`, `small`, `medium`, `large`, `very-large`. Forty files changing one import in one group are `small`; three files rewriting a contract the rest of the system hangs on can be `large`.
|
|
58
|
+
- Coverage: every hunk from the index sits in at least one group; duplicate refs across groups are allowed. Unreferenced hunks fail `validate` and show as Unassigned in the UI.
|
|
59
|
+
- Lockfiles stay in `skipped`; the UI gives them their own closed bucket. Hunk refs exist only for hunks the index lists.
|
|
60
|
+
- Stale refs (rebase of the pinned commits) fail `validate`; `serve` still starts, shows git at those SHAs, and flags the broken pointer. Re-run `index` and copy fresh refs. A dirty work tree does not make refs stale.
|
|
75
61
|
|
|
76
|
-
|
|
62
|
+
Hunk identity is `(path, oldStart, newStart)` plus `oldPath` when renamed. Copy `oldStart`, `oldLines`, `newStart`, and `newLines` from the index. Image files are hunks; copy their refs into groups. Git LFS images are read from `.git/lfs/objects` in the clone; a missing object leaves the image slot empty.
|
|
77
63
|
|
|
78
|
-
|
|
64
|
+
## lookFor
|
|
79
65
|
|
|
80
|
-
|
|
66
|
+
`lookFor` is for what the live diff does not make obvious. Empty is correct for a rename, a formatting change, or a wording-only docs group; leave it empty rather than fill it.
|
|
81
67
|
|
|
82
|
-
|
|
68
|
+
Each bullet is one inspectable claim: optionally a short risk tag (Subtle, Breaking, Race, Perf), then one sentence. When a behavior change hides in the hunk, a predicted trace earns a bullet: a small realistic input, where the old and new paths diverge, and the observable result. The human checks the claim against the live diff; pseudocode, diagrams, collapsed diffs, commit lists, and hunk counts stay out.
|
|
83
69
|
|
|
84
|
-
|
|
70
|
+
## Write the prose
|
|
85
71
|
|
|
86
|
-
|
|
72
|
+
Document `why`, group `why`, `summary`, and `lookFor` are for a tired engineer on the first read.
|
|
87
73
|
|
|
88
|
-
-
|
|
89
|
-
-
|
|
90
|
-
-
|
|
91
|
-
-
|
|
92
|
-
-
|
|
93
|
-
- If you are not sure two concerns depend on each other, leave `dependsOn` empty and give them different `part` names. A false split is easy to see. A false chain hides a mixed PR.
|
|
94
|
-
- Use `suggestedOrder` for the walk through the whole review, including independent parts.
|
|
95
|
-
- `summary` is one sentence that says what this layer is, so a human can keep the *what*. Document `summary` is one or two sentences for the whole change. `lookFor` is a short bullet list of what to inspect before accepting. Do not pack commits, file lists, and hunk counts into a single paragraph.
|
|
96
|
-
- Overview is Why then What. Write document `why` when a source names a motive. Do not skip it because the review has more than one part. Skip the Why section only when `why` is absent. Document `summary` is the what for the whole change and is always present. Each layer `why` is the why for that layer. Layer titles and summaries are the what of that layer. The live git diff is the how. Do not paraphrase the patch as why.
|
|
97
|
-
- Set document `size` to the human review burden, not file or hunk count: `trivial`, `small`, `medium`, `large`, `very-large`. Forty files that only change an import in one layer are `small`. Three files that rewrite a contract the rest of the stack hangs on can be `large`.
|
|
98
|
-
- Every hunk from `index` must appear in at least one group. Duplicate refs across groups are allowed. Unreferenced hunks fail `validate` and show up as Unassigned in the UI.
|
|
99
|
-
- Lockfiles are not hunks. Leave them in `skipped`. Do not add hunk refs for them. The UI has a Lockfiles bucket, closed until the reader opens a file.
|
|
100
|
-
- Stale refs (rebase, edited working tree) fail `validate`. `serve` still starts, shows live git, and flags the broken pointer. Do not invent a replacement hunk.
|
|
101
|
-
|
|
102
|
-
Hunk identity is `(path, oldStart, newStart)` plus `oldPath` when renamed. Copy `oldStart` / `oldLines` / `newStart` / `newLines` from the index. Do not guess numbers from memory. Image files are hunks too — copy those refs into groups. Lockfiles and other binaries stay in `skipped`. Git LFS images are read from `.git/lfs/objects` in the clone. If the object is missing, the image slot is empty. Do not paste image bytes or lockfile contents into `review.json`.
|
|
103
|
-
|
|
104
|
-
Schema: [references/review.schema.json](./references/review.schema.json). Example document: [references/example.md](./references/example.md).
|
|
105
|
-
|
|
106
|
-
## Accuracy
|
|
107
|
-
|
|
108
|
-
- Do not generate, clean up, or rewrite diffs.
|
|
109
|
-
- Do not invent the why from the patch. Write it from tickets, issues, pull-request or merge-request descriptions, coding-agent transcripts, or from how the layers depend on each other. If those sources are silent, omit document `why`. A second part does not cancel it. Always write document `summary`.
|
|
110
|
-
- Do not snapshot the repo into `review.json`.
|
|
111
|
-
- Do not write `review.json` or the index dump into the repository under review. Use a temp directory.
|
|
112
|
-
- Opening a review whose `source` refs do not resolve in cwd is a user error. The CLI must refuse.
|
|
113
|
-
- The UI only displays git output. The browser never computes diffs.
|
|
74
|
+
- One thought per sentence; split past about 25 words.
|
|
75
|
+
- Present tense. Name who does what.
|
|
76
|
+
- Use the real symbol, path, flag, or command.
|
|
77
|
+
- Cut every word that does no work. No changelog voice, no puffery, no "not just X, but Y".
|
|
78
|
+
- A straightforward group needs only its title, `why`, and `summary`; the live diff does the rest.
|
|
@@ -2,7 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
Pointers and prose only. The `@@` numbers must come from `comprehende index`, not from reading the patch. Shape: [review.schema.json](./review.schema.json).
|
|
4
4
|
|
|
5
|
-
`
|
|
5
|
+
- `login` depends on `cookie`. Both use `part` "Session cookie".
|
|
6
|
+
- `docs` is a separate part, last in `suggestedOrder`, because it could have been its own pull request.
|
|
7
|
+
- Ticket #12 names why this work exists, so document `why` is present. Document `summary` names both stories.
|
|
8
|
+
- `login` `summary` names how those hunks meet. `login` `lookFor` is a predicted trace. `docs` has no `lookFor`.
|
|
6
9
|
|
|
7
10
|
```json
|
|
8
11
|
{
|
|
@@ -13,30 +16,29 @@ Pointers and prose only. The `@@` numbers must come from `comprehende index`, no
|
|
|
13
16
|
"range": "origin/main...HEAD"
|
|
14
17
|
},
|
|
15
18
|
"size": "small",
|
|
16
|
-
"why": "
|
|
17
|
-
"summary": "
|
|
19
|
+
"why": "Ticket #12 requires login sessions that client scripts cannot read.",
|
|
20
|
+
"summary": "`setSessionCookie` applies HttpOnly cookie options, and the login route uses it. The README documents this behavior.",
|
|
18
21
|
"tickets": [
|
|
19
22
|
{
|
|
20
23
|
"id": "#12",
|
|
21
|
-
"title": "
|
|
22
|
-
"part": "
|
|
24
|
+
"title": "HttpOnly session cookies",
|
|
25
|
+
"part": "Session cookie"
|
|
23
26
|
}
|
|
24
27
|
],
|
|
25
28
|
"groups": [
|
|
26
29
|
{
|
|
27
|
-
"id": "
|
|
28
|
-
"title": "
|
|
29
|
-
"why": "
|
|
30
|
-
"summary": "
|
|
31
|
-
"part": "
|
|
30
|
+
"id": "cookie",
|
|
31
|
+
"title": "Session cookie helper",
|
|
32
|
+
"why": "The login route needs one helper to apply the session cookie options.",
|
|
33
|
+
"summary": "`setSessionCookie` applies the required options to session cookies.",
|
|
34
|
+
"part": "Session cookie",
|
|
32
35
|
"lookFor": [
|
|
33
|
-
"
|
|
34
|
-
"Foundation: later layers depend on these shapes."
|
|
36
|
+
"Breaking. `setSessionCookie` throws when the caller passes `httpOnly: false`."
|
|
35
37
|
],
|
|
36
38
|
"suggestedOrder": 0,
|
|
37
39
|
"hunkRefs": [
|
|
38
40
|
{
|
|
39
|
-
"path": "src/
|
|
41
|
+
"path": "src/auth/session.ts",
|
|
40
42
|
"oldStart": 1,
|
|
41
43
|
"oldLines": 20,
|
|
42
44
|
"newStart": 1,
|
|
@@ -45,17 +47,19 @@ Pointers and prose only. The `@@` numbers must come from `comprehende index`, no
|
|
|
45
47
|
]
|
|
46
48
|
},
|
|
47
49
|
{
|
|
48
|
-
"id": "
|
|
49
|
-
"title": "
|
|
50
|
-
"why": "#12
|
|
51
|
-
"summary": "
|
|
52
|
-
"part": "
|
|
53
|
-
"lookFor": [
|
|
54
|
-
|
|
50
|
+
"id": "login",
|
|
51
|
+
"title": "Login route",
|
|
52
|
+
"why": "Ticket #12 requires HttpOnly session cookies. The route must set them through the helper.",
|
|
53
|
+
"summary": "The login route in `login.ts` uses `setSessionCookie` from `session.ts`.",
|
|
54
|
+
"part": "Session cookie",
|
|
55
|
+
"lookFor": [
|
|
56
|
+
"For `rememberMe = false`, compare the cookie: old code permits script access; new code sets `HttpOnly` and omits `Max-Age`."
|
|
57
|
+
],
|
|
58
|
+
"dependsOn": ["cookie"],
|
|
55
59
|
"suggestedOrder": 1,
|
|
56
60
|
"hunkRefs": [
|
|
57
61
|
{
|
|
58
|
-
"path": "src/
|
|
62
|
+
"path": "src/api/login.ts",
|
|
59
63
|
"oldStart": 10,
|
|
60
64
|
"oldLines": 8,
|
|
61
65
|
"newStart": 10,
|
|
@@ -66,10 +70,9 @@ Pointers and prose only. The `@@` numbers must come from `comprehende index`, no
|
|
|
66
70
|
{
|
|
67
71
|
"id": "docs",
|
|
68
72
|
"title": "README wording",
|
|
69
|
-
"why": "
|
|
70
|
-
"summary": "
|
|
73
|
+
"why": "The README still describes the previous cookie behavior.",
|
|
74
|
+
"summary": "The README section on sessions matches the new cookie behavior.",
|
|
71
75
|
"part": "README",
|
|
72
|
-
"lookFor": ["No code imports this file."],
|
|
73
76
|
"suggestedOrder": 2,
|
|
74
77
|
"hunkRefs": [
|
|
75
78
|
{
|