@vintasoftware/pr-review-canvas 0.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.
Files changed (157) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +192 -0
  3. package/bin/pr-review.mjs +5 -0
  4. package/docs/reference.md +340 -0
  5. package/package.json +74 -0
  6. package/pr-review.config.example.yml +68 -0
  7. package/prompts/chat-seed.md +64 -0
  8. package/prompts/generation-format.md +255 -0
  9. package/prompts/generation-strict.md +34 -0
  10. package/prompts/generation-surfacing.md +67 -0
  11. package/prompts/layers-default.md +13 -0
  12. package/prompts/quality-standards.md +32 -0
  13. package/skills/pr-review-canvas/SKILL.md +177 -0
  14. package/src/acpx/acpx.ts +530 -0
  15. package/src/acpx/agents.ts +85 -0
  16. package/src/acpx/events.ts +216 -0
  17. package/src/acpx/ndjson.ts +69 -0
  18. package/src/acpx/preflight.ts +44 -0
  19. package/src/canvas/export.ts +95 -0
  20. package/src/canvas/import.ts +138 -0
  21. package/src/canvas/name.ts +55 -0
  22. package/src/canvas/zip.ts +123 -0
  23. package/src/chat/chat-manager.ts +389 -0
  24. package/src/chat/context.ts +160 -0
  25. package/src/chat/seed.ts +71 -0
  26. package/src/chat/threads.ts +114 -0
  27. package/src/cli.ts +199 -0
  28. package/src/commands.ts +424 -0
  29. package/src/config.ts +142 -0
  30. package/src/contract/api.ts +190 -0
  31. package/src/contract/canvas-manifest.ts +29 -0
  32. package/src/contract/chat.ts +76 -0
  33. package/src/contract/comments.ts +96 -0
  34. package/src/contract/discovery.ts +20 -0
  35. package/src/contract/generation-context.ts +77 -0
  36. package/src/contract/keys.ts +14 -0
  37. package/src/contract/links.ts +5 -0
  38. package/src/contract/mermaid-fences.ts +4 -0
  39. package/src/contract/review-artifact.ts +324 -0
  40. package/src/contract/settings.ts +144 -0
  41. package/src/contract/state.ts +46 -0
  42. package/src/contract/validation.ts +43 -0
  43. package/src/git/diff-collector.ts +151 -0
  44. package/src/git/git.ts +115 -0
  45. package/src/git/lang.ts +1 -0
  46. package/src/git/materialize.ts +79 -0
  47. package/src/git/patch-lines.ts +60 -0
  48. package/src/github/attachments.ts +288 -0
  49. package/src/github/capabilities.ts +112 -0
  50. package/src/github/comments.ts +132 -0
  51. package/src/github/gh.ts +196 -0
  52. package/src/github/post-comment.ts +104 -0
  53. package/src/github/post-review.ts +44 -0
  54. package/src/github/pr.ts +133 -0
  55. package/src/github/review-body.ts +72 -0
  56. package/src/github/threads.ts +63 -0
  57. package/src/paths.ts +10 -0
  58. package/src/project-config.ts +219 -0
  59. package/src/prompt-files.ts +26 -0
  60. package/src/review/diagram-nodes.ts +227 -0
  61. package/src/review/doctor.ts +139 -0
  62. package/src/review/glob.ts +33 -0
  63. package/src/review/install-skill.ts +107 -0
  64. package/src/review/normalize.ts +209 -0
  65. package/src/review/prepare.ts +165 -0
  66. package/src/review/prompt.ts +233 -0
  67. package/src/review/publish.ts +209 -0
  68. package/src/review/skill-command.ts +4 -0
  69. package/src/review/test-paths.ts +32 -0
  70. package/src/review/text-length.ts +15 -0
  71. package/src/review/trim-caps.ts +114 -0
  72. package/src/review/validate-folds.ts +110 -0
  73. package/src/review/validate.ts +520 -0
  74. package/src/server/app.ts +46 -0
  75. package/src/server/bundle.ts +266 -0
  76. package/src/server/capped-body.ts +62 -0
  77. package/src/server/context.ts +174 -0
  78. package/src/server/env.ts +7 -0
  79. package/src/server/errors.ts +65 -0
  80. package/src/server/html.ts +140 -0
  81. package/src/server/node-server.ts +42 -0
  82. package/src/server/routes/api.ts +256 -0
  83. package/src/server/routes/chat-routes.ts +221 -0
  84. package/src/server/routes/pages.ts +64 -0
  85. package/src/server/routes/review-routes.ts +245 -0
  86. package/src/server/routes/static.ts +114 -0
  87. package/src/server/security.ts +104 -0
  88. package/src/server/sse.ts +67 -0
  89. package/src/store/atomic-json.ts +68 -0
  90. package/src/store/canvas-store.ts +120 -0
  91. package/src/store/data-dir.ts +29 -0
  92. package/src/store/derived-store.ts +93 -0
  93. package/src/store/pr-store.ts +69 -0
  94. package/src/store/settings-store.ts +152 -0
  95. package/src/store/state-store.ts +121 -0
  96. package/static/js/anchors.js +141 -0
  97. package/static/js/api.js +542 -0
  98. package/static/js/app.js +418 -0
  99. package/static/js/ask.js +35 -0
  100. package/static/js/chat-context.js +137 -0
  101. package/static/js/chat-scroll.js +114 -0
  102. package/static/js/chat.js +843 -0
  103. package/static/js/code-folds.js +200 -0
  104. package/static/js/commands.js +110 -0
  105. package/static/js/comment-link.js +37 -0
  106. package/static/js/composer.js +241 -0
  107. package/static/js/contract-types.d.ts +59 -0
  108. package/static/js/deep-link.js +160 -0
  109. package/static/js/diagram.js +582 -0
  110. package/static/js/diff-decorations.js +204 -0
  111. package/static/js/diff-renderer.js +860 -0
  112. package/static/js/dom.js +145 -0
  113. package/static/js/download.js +52 -0
  114. package/static/js/empty-state.js +161 -0
  115. package/static/js/errors.js +135 -0
  116. package/static/js/fences.js +90 -0
  117. package/static/js/header.js +134 -0
  118. package/static/js/hunks.js +62 -0
  119. package/static/js/import-zone.js +95 -0
  120. package/static/js/interactions.js +952 -0
  121. package/static/js/keyboard.js +131 -0
  122. package/static/js/keys.js +97 -0
  123. package/static/js/lang.js +54 -0
  124. package/static/js/layers.js +596 -0
  125. package/static/js/links.js +150 -0
  126. package/static/js/markdown.js +232 -0
  127. package/static/js/mermaid-fences.js +55 -0
  128. package/static/js/nav.js +91 -0
  129. package/static/js/overview.js +85 -0
  130. package/static/js/points.js +247 -0
  131. package/static/js/progress.js +49 -0
  132. package/static/js/proposed-comment.js +133 -0
  133. package/static/js/quick-questions.js +216 -0
  134. package/static/js/regenerate.js +69 -0
  135. package/static/js/review-session.js +257 -0
  136. package/static/js/scroll-spy.js +66 -0
  137. package/static/js/selection.js +193 -0
  138. package/static/js/settings.js +206 -0
  139. package/static/js/signoff.js +171 -0
  140. package/static/js/skin.js +56 -0
  141. package/static/js/store.js +35 -0
  142. package/static/js/theme.js +56 -0
  143. package/static/js/threads.js +78 -0
  144. package/static/js/vendor.d.ts +15 -0
  145. package/static/styles/base.css +223 -0
  146. package/static/styles/chat-tools.css +130 -0
  147. package/static/styles/chat.css +140 -0
  148. package/static/styles/commands.css +156 -0
  149. package/static/styles/diff.css +258 -0
  150. package/static/styles/header.css +114 -0
  151. package/static/styles/layout.css +123 -0
  152. package/static/styles/panels.css +152 -0
  153. package/static/styles/responsive.css +80 -0
  154. package/static/styles/review-actions.css +124 -0
  155. package/static/styles/review.css +473 -0
  156. package/static/styles/skin-github.css +356 -0
  157. package/static/styles.css +14 -0
@@ -0,0 +1,223 @@
1
+ /* PR review canvas. Tokens and component rules follow ai-plans/assets/pr-review-canvas/design-reference.html;
2
+ the diff table keeps the prior-art rules (moved-code tints, hljs tokens). Both themes through light-dark(). */
3
+
4
+ *,
5
+ *::before,
6
+ *::after {
7
+ box-sizing: border-box;
8
+ }
9
+
10
+ :root {
11
+ color-scheme: light dark;
12
+ --fs: 14px;
13
+ --lh: 1.5;
14
+ --rail-w: 240px;
15
+ --chat-w: 340px;
16
+ --main-pad: 20px 20px 40px;
17
+ --gap: 20px;
18
+ --r: 0;
19
+ --s1: var(--v1);
20
+ --s2: var(--v2);
21
+ --s3: var(--v3);
22
+ --s4: var(--v4);
23
+ --s5: var(--v5);
24
+ --s6: var(--v6);
25
+ --sans: -apple-system, BlinkMacSystemFont, "Segoe UI", "Noto Sans", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji";
26
+ --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace;
27
+
28
+ --v1: light-dark(#ffd43b, #ffe066);
29
+ --v2: light-dark(#ffa94d, #ffc078);
30
+ --v3: light-dark(#f783ac, #faa2c1);
31
+ --v4: light-dark(#da77f2, #e599f7);
32
+ --v5: light-dark(#9775fa, #b197fc);
33
+ --v6: light-dark(#748ffc, #91a7ff);
34
+ --stripe-y: linear-gradient(180deg, var(--v1) 0 1px, var(--v2) 1px 2px, var(--v3) 2px 3px, var(--v4) 3px 4px, var(--v5) 4px 5px, var(--v6) 5px 6px);
35
+
36
+ --bg: light-dark(#ffffff, #1e1f2b);
37
+ --panel: light-dark(#ffffff, #282a3a);
38
+ --panel-2: light-dark(#f3f3f3, #303341);
39
+ --ink: light-dark(#3a3739, #eaf2f1);
40
+ --shadow: light-dark(#3a3739, #696d77);
41
+ --line: light-dark(#dddddd, #3a3d4b);
42
+ --line-strong: var(--ink);
43
+ --fg: light-dark(#3a3739, #eaf2f1);
44
+ --fg-muted: light-dark(#565554, #a4a8b3);
45
+ --fg-dim: var(--fg-muted);
46
+ --accent: light-dark(#3b5bdb, #91a7ff);
47
+ --accent-bg: light-dark(#edf2ff, rgba(145, 167, 255, 0.14));
48
+ --purple: light-dark(#8b4dff, #c39ac9);
49
+ --annot-bg: light-dark(#f3f0ff, rgba(195, 154, 201, 0.14));
50
+ --ok: light-dark(#0c7411, #bad761);
51
+ --bad: light-dark(#c40400, #ff657a);
52
+ --warn: light-dark(#caa512, #ffd76d);
53
+ --warn-bg: var(--annot-bg);
54
+ --sev-blocker: light-dark(#db0400, #ff657a);
55
+ --sev-major: var(--warn);
56
+ --sev-minor: light-dark(#808080, #696d77);
57
+ --sq-mark: light-dark(#3a3739, #1e1f2b);
58
+ /* Added and deleted lines carry GitHub's light tints in both skins, so a diff reads the same
59
+ here as it does on the pull request. */
60
+ --add-bg: light-dark(#e6ffec, rgba(186, 215, 97, 0.14));
61
+ --add-w: light-dark(#abf2bc, rgba(186, 215, 97, 0.4));
62
+ --del-bg: light-dark(#ffebe9, rgba(255, 101, 122, 0.14));
63
+ --del-w: light-dark(#ffc1c0, rgba(255, 101, 122, 0.42));
64
+ --mv-bg: light-dark(rgba(139, 77, 255, 0.07), rgba(195, 154, 201, 0.1));
65
+ --hunk-bg: var(--accent-bg);
66
+ --focus: var(--accent);
67
+ --progress: light-dark(#0f8a15, #bad761);
68
+
69
+ /* Syntax tokens: Monokai Light (light) and Monokai Pro Octagon (dark), both ≥ 4.5:1 on the panel. */
70
+ --syn-comment: light-dark(#75715e, #888d94);
71
+ --syn-keyword: light-dark(#a626a4, #ff657a);
72
+ --syn-string: light-dark(#986801, #ffd76d);
73
+ --syn-number: light-dark(#8b4dff, #c39ac9);
74
+ --syn-title: light-dark(#0b6a2f, #bad761);
75
+ --syn-type: light-dark(#0b5cad, #9cd1bb);
76
+ --syn-attr: light-dark(#0b6a2f, #ffd76d);
77
+ --syn-tag: light-dark(#c40400, #ff657a);
78
+ --syn-meta: light-dark(#3b5bdb, #91a7ff);
79
+ }
80
+
81
+ /* The server writes `data-theme` for every load. `auto` matches neither rule, which leaves the
82
+ `color-scheme: light dark` above to follow the operating system. */
83
+ :root[data-theme="dark"] {
84
+ color-scheme: dark;
85
+ }
86
+ :root[data-theme="light"] {
87
+ color-scheme: light;
88
+ }
89
+
90
+ html {
91
+ background: var(--bg);
92
+ color: var(--fg);
93
+ font-family: var(--sans);
94
+ font-size: var(--fs);
95
+ line-height: var(--lh);
96
+ -webkit-text-size-adjust: 100%;
97
+ }
98
+ body {
99
+ margin: 0;
100
+ min-height: 100vh;
101
+ }
102
+ .page {
103
+ min-height: 100vh;
104
+ display: flex;
105
+ flex-direction: column;
106
+ }
107
+ a {
108
+ color: var(--accent);
109
+ text-underline-offset: 2px;
110
+ }
111
+ h1,
112
+ h2,
113
+ h3,
114
+ h4,
115
+ h5,
116
+ h6 {
117
+ margin: 0;
118
+ font-weight: 600;
119
+ line-height: 1.25;
120
+ }
121
+ h1 {
122
+ font-size: 20px;
123
+ overflow-wrap: anywhere;
124
+ }
125
+ h2 {
126
+ font-size: 16px;
127
+ }
128
+ h3 {
129
+ font-size: 14px;
130
+ }
131
+ p {
132
+ margin: 0 0 0.6em;
133
+ }
134
+ p:last-child {
135
+ margin-bottom: 0;
136
+ }
137
+ ul,
138
+ ol {
139
+ margin: 0;
140
+ padding: 0;
141
+ list-style: none;
142
+ }
143
+ code,
144
+ pre,
145
+ .mono,
146
+ .path,
147
+ .loc,
148
+ .snip {
149
+ font-family: var(--mono);
150
+ font-size: 0.92em;
151
+ }
152
+ code {
153
+ background: var(--panel-2);
154
+ border: 1px solid var(--line);
155
+ padding: 0 4px;
156
+ font-size: 0.9em;
157
+ }
158
+ pre {
159
+ margin: 0;
160
+ overflow-x: auto;
161
+ }
162
+ pre code {
163
+ display: block;
164
+ padding: 8px 10px;
165
+ font-size: 12px;
166
+ line-height: 20px;
167
+ }
168
+ b,
169
+ strong {
170
+ font-weight: 600;
171
+ }
172
+ .sr {
173
+ position: absolute;
174
+ width: 1px;
175
+ height: 1px;
176
+ overflow: hidden;
177
+ clip: rect(0 0 0 0);
178
+ white-space: nowrap;
179
+ }
180
+ .skip {
181
+ position: absolute;
182
+ left: -999px;
183
+ top: 8px;
184
+ z-index: 100;
185
+ background: var(--panel);
186
+ padding: 8px 12px;
187
+ border: 1px solid var(--accent);
188
+ }
189
+ .skip:focus {
190
+ left: 8px;
191
+ }
192
+ :focus-visible {
193
+ outline: 3px solid var(--focus);
194
+ outline-offset: 1px;
195
+ }
196
+ .muted {
197
+ color: var(--fg-muted);
198
+ }
199
+ .ok {
200
+ color: var(--ok);
201
+ }
202
+ .bad {
203
+ color: var(--bad);
204
+ }
205
+ .small {
206
+ font-size: 11px;
207
+ }
208
+ .lbl {
209
+ display: block;
210
+ font-size: 12px;
211
+ font-weight: 600;
212
+ color: var(--fg-muted);
213
+ }
214
+ .loading {
215
+ padding: 40px 20px;
216
+ color: var(--fg-muted);
217
+ text-align: center;
218
+ }
219
+
220
+ /* The hidden attribute takes priority over component layout styles. */
221
+ [hidden]:not([hidden="until-found"]) {
222
+ display: none !important;
223
+ }
@@ -0,0 +1,130 @@
1
+ /* Chat context, proposed comments, quick questions, and settings. */
2
+ .ctx-line {
3
+ display: flex;
4
+ align-items: baseline;
5
+ gap: 6px;
6
+ flex-wrap: wrap;
7
+ }
8
+ .ctx-chip {
9
+ border: 1px solid var(--ink);
10
+ background: var(--panel-2);
11
+ padding: 1px 6px;
12
+ font-family: var(--mono);
13
+ color: var(--fg);
14
+ max-width: 100%;
15
+ overflow-wrap: anywhere;
16
+ cursor: default;
17
+ }
18
+ .ctx-chip:focus-visible,
19
+ .qq-item:focus-visible {
20
+ outline: 2px solid var(--accent);
21
+ outline-offset: 1px;
22
+ }
23
+ .turn.u {
24
+ border-left-color: var(--ink);
25
+ }
26
+ .transcript .turn:last-child {
27
+ margin-bottom: 4px;
28
+ }
29
+ .cmd.unseen {
30
+ position: absolute;
31
+ left: 50%;
32
+ bottom: 128px;
33
+ transform: translateX(-50%);
34
+ background: var(--panel-2);
35
+ border: 2px solid var(--ink);
36
+ padding: 2px 10px;
37
+ box-shadow: 2px 2px 0 var(--shadow);
38
+ z-index: 4;
39
+ }
40
+ .proposed {
41
+ border: 2px solid var(--ink);
42
+ background: var(--panel-2);
43
+ box-shadow: 2px 2px 0 var(--shadow);
44
+ padding: 8px 10px;
45
+ margin: 10px 0;
46
+ }
47
+ .proposed-h {
48
+ display: flex;
49
+ gap: 8px;
50
+ align-items: baseline;
51
+ flex-wrap: wrap;
52
+ margin-bottom: 6px;
53
+ }
54
+ .proposed-h .mono {
55
+ font-size: 12px;
56
+ color: var(--fg-muted);
57
+ overflow-wrap: anywhere;
58
+ }
59
+ .proposed .tbtns {
60
+ margin-top: 8px;
61
+ display: flex;
62
+ gap: 12px;
63
+ flex-wrap: wrap;
64
+ }
65
+ .proposed-invalid {
66
+ border: 1px dashed var(--line);
67
+ padding: 6px 8px;
68
+ overflow-x: auto;
69
+ }
70
+ .qq-menu {
71
+ position: fixed;
72
+ z-index: 20;
73
+ min-width: 260px;
74
+ display: flex;
75
+ flex-direction: column;
76
+ border: 2px solid var(--ink);
77
+ background: var(--bg);
78
+ box-shadow: 3px 3px 0 var(--shadow);
79
+ }
80
+ .qq-item {
81
+ text-align: left;
82
+ border: 0;
83
+ background: none;
84
+ font: inherit;
85
+ color: var(--fg);
86
+ padding: 6px 10px;
87
+ cursor: pointer;
88
+ }
89
+ .qq-item:hover,
90
+ .qq-item:focus-visible {
91
+ background: var(--panel-2);
92
+ }
93
+ dialog.settings {
94
+ max-width: 560px;
95
+ width: calc(100vw - 32px);
96
+ padding: 20px;
97
+ overflow-wrap: anywhere;
98
+ }
99
+ dialog.settings .field {
100
+ display: grid;
101
+ grid-template-columns: 180px minmax(0, 1fr);
102
+ gap: 8px;
103
+ align-items: center;
104
+ margin: 10px 0;
105
+ }
106
+ dialog.settings .panel-ro {
107
+ border: 1px solid var(--line);
108
+ background: var(--panel-2);
109
+ padding: 8px 10px;
110
+ margin: 14px 0 6px;
111
+ }
112
+ dialog.settings .panel-ro h3 {
113
+ margin-bottom: 6px;
114
+ }
115
+ dialog.settings .probe-result:empty {
116
+ display: none;
117
+ }
118
+ @media (max-width: 480px) {
119
+ dialog.settings .field {
120
+ grid-template-columns: minmax(0, 1fr);
121
+ }
122
+ dialog.settings .dialog-actions {
123
+ flex-wrap: wrap;
124
+ }
125
+ }
126
+ @media (max-width: 1360px) {
127
+ .cmd.unseen {
128
+ bottom: 160px;
129
+ }
130
+ }
@@ -0,0 +1,140 @@
1
+ /* ---- AI Chat ---- */
2
+ .chat {
3
+ padding: 0 1px;
4
+ display: flex;
5
+ flex-direction: column;
6
+ align-self: start;
7
+ height: 100vh;
8
+ background: transparent;
9
+ }
10
+ .handle {
11
+ position: absolute;
12
+ left: -1px;
13
+ top: 0;
14
+ bottom: 0;
15
+ width: 10px;
16
+ margin: 0;
17
+ padding: 0;
18
+ border: 0;
19
+ background: transparent;
20
+ cursor: col-resize;
21
+ color: var(--fg-dim);
22
+ display: flex;
23
+ align-items: center;
24
+ justify-content: center;
25
+ z-index: 3;
26
+ }
27
+ .handle::before {
28
+ content: "";
29
+ width: 4px;
30
+ height: 36px;
31
+ border-left: 1px solid currentColor;
32
+ border-right: 1px solid currentColor;
33
+ }
34
+ .handle:hover,
35
+ .handle:focus-visible {
36
+ color: var(--fg);
37
+ background: var(--panel-2);
38
+ }
39
+ .chat-h {
40
+ display: flex;
41
+ flex-wrap: wrap;
42
+ gap: 8px;
43
+ align-items: center;
44
+ padding: 10px 14px;
45
+ border-bottom: 1px solid var(--ink);
46
+ background: var(--panel-2);
47
+ }
48
+ .chat-h h2 {
49
+ margin-right: auto;
50
+ }
51
+ .chat-h select {
52
+ padding: 3px 6px;
53
+ font-size: 13px;
54
+ flex: 1 1 120px;
55
+ min-width: 0;
56
+ width: 0;
57
+ }
58
+ select,
59
+ input,
60
+ textarea {
61
+ font: inherit;
62
+ color: var(--fg);
63
+ background: var(--bg);
64
+ border: 2px solid var(--ink);
65
+ border-radius: var(--r);
66
+ padding: 5px 8px;
67
+ max-width: 100%;
68
+ min-width: 0;
69
+ }
70
+ select:disabled,
71
+ input:disabled,
72
+ textarea:disabled {
73
+ color: var(--fg-muted);
74
+ border-color: var(--line);
75
+ cursor: not-allowed;
76
+ }
77
+ .ctx-line {
78
+ padding: 8px 14px;
79
+ font-size: 12px;
80
+ color: var(--fg-muted);
81
+ border-bottom: 1px solid var(--line);
82
+ margin: 0;
83
+ }
84
+ .transcript {
85
+ padding: 14px;
86
+ flex: 1 1 auto;
87
+ min-height: 0;
88
+ overflow: auto;
89
+ /* Reaching the top or bottom of the transcript stops there; the page behind stays put. */
90
+ overscroll-behavior: contain;
91
+ }
92
+ .transcript .empty {
93
+ color: var(--fg-muted);
94
+ font-size: 13px;
95
+ }
96
+ .turn {
97
+ margin-bottom: 18px;
98
+ padding-left: 12px;
99
+ border-left: 2px solid var(--line);
100
+ }
101
+ .turn.a {
102
+ border-left-color: var(--purple);
103
+ }
104
+ .role {
105
+ display: block;
106
+ font-size: 11px;
107
+ letter-spacing: 0.06em;
108
+ font-weight: 700;
109
+ text-transform: uppercase;
110
+ color: var(--fg-muted);
111
+ margin-bottom: 4px;
112
+ }
113
+ .turn.a .role {
114
+ color: var(--accent);
115
+ }
116
+ .snip {
117
+ border: 1px solid var(--ink);
118
+ background: var(--panel-2);
119
+ font-size: 12px;
120
+ line-height: 20px;
121
+ padding: 6px 10px;
122
+ margin: 6px 0 8px;
123
+ white-space: pre;
124
+ }
125
+ .chat-composer {
126
+ padding: 12px 14px;
127
+ border-top: 1px solid var(--ink);
128
+ background: var(--panel-2);
129
+ display: grid;
130
+ gap: 8px;
131
+ }
132
+ textarea {
133
+ width: 100%;
134
+ resize: vertical;
135
+ min-height: 64px;
136
+ }
137
+ .chat-composer .cmd.fill {
138
+ padding: 4px 10px;
139
+ box-shadow: 2px 2px 0 var(--shadow);
140
+ }
@@ -0,0 +1,156 @@
1
+ /* ---- Commands: the one clickable style ---- */
2
+ .cmd {
3
+ display: inline-block;
4
+ background: none;
5
+ border: 0;
6
+ padding: 0;
7
+ margin: 0;
8
+ color: var(--accent);
9
+ font: inherit;
10
+ font-weight: 600;
11
+ cursor: pointer;
12
+ text-decoration: none;
13
+ white-space: nowrap;
14
+ line-height: inherit;
15
+ }
16
+ .cmd::before {
17
+ content: "[ ";
18
+ }
19
+ .cmd::after {
20
+ content: " ]";
21
+ }
22
+ .cmd:hover {
23
+ text-decoration: underline;
24
+ text-underline-offset: 3px;
25
+ text-decoration-thickness: 2px;
26
+ }
27
+ .cmd:disabled,
28
+ .cmd[aria-disabled="true"] {
29
+ color: var(--fg-dim);
30
+ cursor: not-allowed;
31
+ text-decoration: none;
32
+ }
33
+ .cmd[aria-busy="true"] {
34
+ color: var(--fg-muted);
35
+ cursor: progress;
36
+ }
37
+ .cmd.fill {
38
+ background: var(--accent);
39
+ color: var(--bg);
40
+ padding: 6px 12px;
41
+ box-shadow: 3px 3px 0 var(--shadow);
42
+ transition:
43
+ transform 0.08s ease-out,
44
+ box-shadow 0.08s ease-out;
45
+ }
46
+ .cmd.fill:hover {
47
+ text-decoration: none;
48
+ transform: translate(-1px, -1px);
49
+ box-shadow: 4px 4px 0 var(--shadow);
50
+ }
51
+ .cmd.fill:active {
52
+ transform: translate(1px, 1px);
53
+ box-shadow: 1px 1px 0 var(--shadow);
54
+ }
55
+ .cmd.big {
56
+ font-size: 16px;
57
+ padding: 12px 24px;
58
+ box-shadow: 5px 5px 0 var(--shadow);
59
+ }
60
+ .cmd.big:hover {
61
+ transform: translate(-2px, -2px);
62
+ box-shadow: 7px 7px 0 var(--shadow);
63
+ }
64
+ .cmd-err {
65
+ display: inline-block;
66
+ margin-left: 8px;
67
+ color: var(--bad);
68
+ font-size: 12px;
69
+ }
70
+ .tbtns {
71
+ display: inline-flex;
72
+ gap: 10px;
73
+ flex-wrap: wrap;
74
+ align-items: center;
75
+ }
76
+ .tbtns.end {
77
+ justify-content: flex-end;
78
+ }
79
+ .chk {
80
+ display: inline-flex;
81
+ align-items: center;
82
+ gap: 6px;
83
+ cursor: pointer;
84
+ white-space: nowrap;
85
+ }
86
+ .chk input {
87
+ margin: 0;
88
+ width: 14px;
89
+ height: 14px;
90
+ accent-color: var(--accent);
91
+ }
92
+ .chk input:disabled {
93
+ cursor: not-allowed;
94
+ }
95
+ .pill {
96
+ display: inline-block;
97
+ font-size: 11px;
98
+ line-height: 18px;
99
+ padding: 0 6px;
100
+ border: 1px solid var(--ink);
101
+ border-radius: var(--r);
102
+ white-space: nowrap;
103
+ font-weight: 600;
104
+ color: var(--fg);
105
+ }
106
+ .pill.open {
107
+ color: var(--ok);
108
+ border-color: currentColor;
109
+ }
110
+ .pill.draft,
111
+ .pill.closed {
112
+ color: var(--fg-muted);
113
+ border-color: currentColor;
114
+ }
115
+ .pill.merged {
116
+ color: var(--purple);
117
+ border-color: currentColor;
118
+ }
119
+ .pill.agent {
120
+ color: var(--fg);
121
+ border-color: var(--ink);
122
+ }
123
+ .pill.add,
124
+ .pill.del {
125
+ border-color: transparent;
126
+ font-family: var(--mono);
127
+ }
128
+ .pill.add {
129
+ color: var(--ok);
130
+ background: light-dark(var(--add-bg), var(--panel));
131
+ }
132
+ .pill.del {
133
+ color: var(--bad);
134
+ background: light-dark(var(--del-bg), var(--panel));
135
+ }
136
+ .pill.risk {
137
+ color: var(--fg);
138
+ background: var(--panel-2);
139
+ font-weight: 600;
140
+ }
141
+ .pill.risk.model {
142
+ border-style: dashed;
143
+ }
144
+ .pill.kind {
145
+ text-transform: lowercase;
146
+ color: var(--fg-muted);
147
+ border-color: var(--line);
148
+ }
149
+ .pill.test-tag {
150
+ color: #1e1f2b;
151
+ background: var(--s1);
152
+ border-color: var(--ink);
153
+ font-size: 10px;
154
+ letter-spacing: 0.06em;
155
+ text-transform: uppercase;
156
+ }