claude-plan-review 0.3.2 β 0.4.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 +126 -4
- package/package.json +2 -1
- package/skill/SKILL.md +86 -0
- package/src/cli.js +192 -7
- package/src/hook.js +31 -8
- package/src/mcp.js +444 -0
- package/src/paths.js +17 -0
- package/src/plan-parse.js +238 -0
- package/src/server.js +261 -10
- package/src/stop-gate.js +73 -0
- package/src/store.js +309 -33
- package/src/ui/app.js +649 -108
- package/src/ui/index.html +51 -15
- package/src/ui/style.css +73 -18
package/src/ui/index.html
CHANGED
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
<label>Version
|
|
25
25
|
<select id="versionSel"></select>
|
|
26
26
|
</label>
|
|
27
|
+
<button class="iconbtn" id="deleteVerBtn" title="Delete this version" aria-label="Delete this version" hidden>π</button>
|
|
27
28
|
</div>
|
|
28
29
|
<div class="saveActions" id="saveActions" hidden>
|
|
29
30
|
<button class="btn" id="saveBtn">Save to gist</button>
|
|
@@ -34,30 +35,34 @@
|
|
|
34
35
|
<button class="btn approve" id="approveBtn">Approve plan</button>
|
|
35
36
|
<button class="btn reject" id="rejectBtn">Request changes</button>
|
|
36
37
|
</div>
|
|
38
|
+
<button class="iconbtn" id="manageBtn" title="Manage & delete plans" aria-label="Manage plans">π</button>
|
|
37
39
|
<button class="iconbtn" id="themeToggle" title="Toggle light / dark theme" aria-label="Toggle theme">π</button>
|
|
38
40
|
</header>
|
|
39
41
|
|
|
40
42
|
<nav class="tabs">
|
|
41
|
-
<button class="tab active" data-tab="preview">Preview
|
|
42
|
-
<button class="tab" data-tab="source">Source & comments <span class="count" id="cCount"></span></button>
|
|
43
|
+
<button class="tab active" data-tab="preview">Preview <span class="count" id="cCount"></span></button>
|
|
43
44
|
<button class="tab" data-tab="diff">Diff</button>
|
|
44
45
|
</nav>
|
|
45
46
|
|
|
46
47
|
<main>
|
|
47
|
-
<!-- PREVIEW -->
|
|
48
|
+
<!-- PREVIEW + COMMENTS -->
|
|
48
49
|
<section class="panel active" id="panel-preview">
|
|
49
|
-
<
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
50
|
+
<div class="preview-toolbar">
|
|
51
|
+
<p class="selhint">Select any text in the plan to comment on it.</p>
|
|
52
|
+
<button class="btn tree-toggle" id="treeToggle" hidden>View as tree</button>
|
|
53
|
+
</div>
|
|
54
|
+
<div class="preview-layout">
|
|
55
|
+
<aside class="doc-sidebar" id="docSidebar" hidden></aside>
|
|
56
|
+
<div class="preview-main">
|
|
57
|
+
<article class="markdown-body" id="preview"></article>
|
|
58
|
+
<div class="general">
|
|
59
|
+
<h3>General comments</h3>
|
|
60
|
+
<div id="generalList"></div>
|
|
61
|
+
<div class="composer">
|
|
62
|
+
<textarea id="generalInput" placeholder="Leave a general comment on this planβ¦"></textarea>
|
|
63
|
+
<button class="btn" id="generalAdd">Comment</button>
|
|
64
|
+
</div>
|
|
65
|
+
</div>
|
|
61
66
|
</div>
|
|
62
67
|
</div>
|
|
63
68
|
</section>
|
|
@@ -68,6 +73,9 @@
|
|
|
68
73
|
<label>Compare base
|
|
69
74
|
<select id="baseSel"></select>
|
|
70
75
|
</label>
|
|
76
|
+
<label id="diffDocWrap" hidden>Document
|
|
77
|
+
<select id="diffDocSel"></select>
|
|
78
|
+
</label>
|
|
71
79
|
<span class="arrow">β current v<span id="diffCur"></span></span>
|
|
72
80
|
<div class="modetoggle">
|
|
73
81
|
<button class="seg active" data-mode="split">Side-by-side</button>
|
|
@@ -112,6 +120,34 @@
|
|
|
112
120
|
</div>
|
|
113
121
|
</div>
|
|
114
122
|
|
|
123
|
+
<div class="confirmModal" id="deleteModal" hidden>
|
|
124
|
+
<div class="box">
|
|
125
|
+
<h3 id="deleteTitle">Delete</h3>
|
|
126
|
+
<p id="deleteDesc"></p>
|
|
127
|
+
<div class="pendingInfo" id="deletePending" hidden></div>
|
|
128
|
+
<div class="row">
|
|
129
|
+
<button class="btn" id="deleteCancel">Cancel</button>
|
|
130
|
+
<button class="btn reject" id="deleteConfirm">Delete</button>
|
|
131
|
+
<button class="btn reject" id="deleteForce" hidden>Force delete</button>
|
|
132
|
+
</div>
|
|
133
|
+
</div>
|
|
134
|
+
</div>
|
|
135
|
+
|
|
136
|
+
<div class="manageModal" id="manageModal" hidden>
|
|
137
|
+
<div class="box wide">
|
|
138
|
+
<h3>Manage plans</h3>
|
|
139
|
+
<p class="hint">Delete individual versions, several at once, or a whole project. Deletes are permanent.</p>
|
|
140
|
+
<div id="manageList"></div>
|
|
141
|
+
<div class="row">
|
|
142
|
+
<button class="btn" id="manageClose">Close</button>
|
|
143
|
+
</div>
|
|
144
|
+
</div>
|
|
145
|
+
</div>
|
|
146
|
+
|
|
147
|
+
<div class="selpop" id="selPop" hidden>
|
|
148
|
+
<button class="btn primary" id="selComment">π¬ Comment</button>
|
|
149
|
+
</div>
|
|
150
|
+
|
|
115
151
|
<div class="toast" id="toast" hidden></div>
|
|
116
152
|
</div>
|
|
117
153
|
<script src="/app.js"></script>
|
package/src/ui/style.css
CHANGED
|
@@ -100,24 +100,22 @@ main { flex: 1; padding: 22px; max-width: 1100px; width: 100%; margin: 0 auto; }
|
|
|
100
100
|
.markdown-body table { border-collapse: collapse; }
|
|
101
101
|
.markdown-body th, .markdown-body td { border: 1px solid var(--border); padding: 6px 12px; }
|
|
102
102
|
|
|
103
|
-
/*
|
|
104
|
-
.
|
|
105
|
-
.
|
|
106
|
-
.
|
|
107
|
-
.
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
}
|
|
111
|
-
.
|
|
112
|
-
|
|
113
|
-
.
|
|
114
|
-
.srow.has-comments .sgutter { box-shadow: inset 2px 0 0 #d29922; }
|
|
115
|
-
.source.dragging { user-select: none; }
|
|
116
|
-
.source.dragging .sgutter { cursor: ns-resize; }
|
|
117
|
-
.srow.sel { background: color-mix(in srgb, var(--accent) 14%, transparent); }
|
|
118
|
-
.srow.sel .sgutter { background: color-mix(in srgb, var(--accent) 26%, transparent); color: var(--fg); }
|
|
119
|
-
.threads { padding: 0 10px 0 62px; background: var(--bg-soft); }
|
|
103
|
+
/* preview commenting: select text β comment inline */
|
|
104
|
+
.selhint { color: var(--fg-muted); font-size: 12px; margin: 0 0 10px; }
|
|
105
|
+
.markdown-body .md-block { margin-left: -16px; padding-left: 16px; } /* gutter for the has-comments marker */
|
|
106
|
+
.markdown-body .md-block.has-comments { box-shadow: inset 3px 0 0 #d29922; }
|
|
107
|
+
.markdown-body ::selection { background: color-mix(in srgb, var(--accent) 28%, transparent); }
|
|
108
|
+
|
|
109
|
+
.selpop { position: fixed; z-index: 40; }
|
|
110
|
+
.selpop .btn.primary { background: var(--accent); border-color: var(--accent); color: #fff; box-shadow: 0 2px 10px #0004; }
|
|
111
|
+
.selpop .btn.primary:hover { filter: brightness(1.08); }
|
|
112
|
+
|
|
113
|
+
.threads { margin: 8px 0 14px; }
|
|
120
114
|
.comment .loc { font-family: var(--mono); color: var(--accent); }
|
|
115
|
+
.cquote {
|
|
116
|
+
border-left: 3px solid var(--accent); padding: 3px 10px; margin: 6px 12px; color: var(--fg-muted);
|
|
117
|
+
font-style: italic; background: var(--bg-soft); border-radius: 0 4px 4px 0; white-space: pre-wrap; word-break: break-word;
|
|
118
|
+
}
|
|
121
119
|
|
|
122
120
|
.comment {
|
|
123
121
|
border: 1px solid var(--border); border-radius: 8px; margin: 8px 0; background: var(--bg); font-family: var(--sans);
|
|
@@ -129,7 +127,9 @@ main { flex: 1; padding: 22px; max-width: 1100px; width: 100%; margin: 0 auto; }
|
|
|
129
127
|
.comment .del:hover { color: var(--red); }
|
|
130
128
|
|
|
131
129
|
.composer { display: flex; gap: 8px; margin: 8px 0 12px; }
|
|
132
|
-
.composer.inline { padding:
|
|
130
|
+
.composer.inline { display: block; padding: 10px 12px; margin: 8px 0 14px; background: var(--bg-soft); border: 1px solid var(--border); border-radius: 8px; }
|
|
131
|
+
.composer.inline .cquote { margin: 0 0 8px; }
|
|
132
|
+
.composer.inline .composer-row { display: flex; gap: 8px; }
|
|
133
133
|
textarea {
|
|
134
134
|
flex: 1; font-family: var(--sans); font-size: 13px; padding: 8px 10px; border: 1px solid var(--border);
|
|
135
135
|
border-radius: 6px; background: var(--bg); color: var(--fg); min-height: 38px; resize: vertical;
|
|
@@ -196,3 +196,58 @@ textarea {
|
|
|
196
196
|
padding: 10px 18px; border-radius: 8px; font-size: 13px; z-index: 60; box-shadow: 0 4px 16px #0004; }
|
|
197
197
|
|
|
198
198
|
.empty { color: var(--fg-muted); padding: 40px; text-align: center; }
|
|
199
|
+
|
|
200
|
+
/* ---------- multi-document: sidebar + layout ---------- */
|
|
201
|
+
.preview-toolbar { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin: 0 0 10px; }
|
|
202
|
+
.preview-toolbar .selhint { margin: 0; }
|
|
203
|
+
.tree-toggle { font-size: 12px; padding: 4px 10px; flex: none; }
|
|
204
|
+
.tree-toggle.active { background: var(--accent); border-color: var(--accent); color: #fff; }
|
|
205
|
+
.tree-toggle.active:hover { filter: brightness(1.08); }
|
|
206
|
+
|
|
207
|
+
.preview-layout { display: flex; align-items: flex-start; gap: 20px; }
|
|
208
|
+
.preview-main { flex: 1; min-width: 0; }
|
|
209
|
+
|
|
210
|
+
.doc-sidebar {
|
|
211
|
+
flex: none; width: 220px; align-self: stretch; position: sticky; top: 96px;
|
|
212
|
+
border: 1px solid var(--border); border-radius: 8px; background: var(--bg-soft);
|
|
213
|
+
padding: 6px; font-size: 13px; max-height: calc(100vh - 120px); overflow-y: auto;
|
|
214
|
+
}
|
|
215
|
+
.doc-sidebar .sb-head {
|
|
216
|
+
font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: .04em;
|
|
217
|
+
color: var(--fg-muted); padding: 6px 8px 8px;
|
|
218
|
+
}
|
|
219
|
+
.doc-sidebar .sb-row {
|
|
220
|
+
display: flex; align-items: center; gap: 6px; padding: 6px 8px; border-radius: 6px;
|
|
221
|
+
color: var(--fg); text-decoration: none; cursor: pointer; line-height: 1.3;
|
|
222
|
+
}
|
|
223
|
+
.doc-sidebar .sb-row:hover { background: var(--border-soft); }
|
|
224
|
+
.doc-sidebar .sb-row.active { background: var(--border-soft); font-weight: 600; box-shadow: inset 2px 0 0 var(--accent); }
|
|
225
|
+
.doc-sidebar .sb-title { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
226
|
+
.sb-badge { flex: none; background: var(--border-soft); border-radius: 999px; padding: 0 7px; font-size: 11px; color: var(--fg-muted); }
|
|
227
|
+
.sb-dot { flex: none; width: 7px; height: 7px; border-radius: 999px; background: #d29922; }
|
|
228
|
+
|
|
229
|
+
/* view-as-tree hides blocks display-only β they stay in the DOM for line anchoring */
|
|
230
|
+
.md-block.tree-hidden, .threads.tree-hidden, .composer.inline.tree-hidden { display: none !important; }
|
|
231
|
+
|
|
232
|
+
/* diff document select reuses the .diffbar label styling automatically */
|
|
233
|
+
|
|
234
|
+
/* ---------- delete confirm + manage modals ---------- */
|
|
235
|
+
.confirmModal, .manageModal { position: fixed; inset: 0; background: #00000066; display: flex; align-items: center; justify-content: center; z-index: 50; }
|
|
236
|
+
.confirmModal .box, .manageModal .box { background: var(--bg); border: 1px solid var(--border); border-radius: 10px; padding: 20px; width: 460px; max-width: 92vw; }
|
|
237
|
+
.manageModal .box.wide { width: 620px; max-height: 84vh; display: flex; flex-direction: column; }
|
|
238
|
+
.confirmModal h3, .manageModal h3 { margin-top: 0; }
|
|
239
|
+
.confirmModal p, .manageModal .hint { color: var(--fg-muted); font-size: 13px; }
|
|
240
|
+
.confirmModal .row, .manageModal .row { display: flex; justify-content: flex-end; gap: 10px; margin-top: 16px; }
|
|
241
|
+
.confirmModal .btn:disabled, .manageModal .btn:disabled { opacity: .5; cursor: not-allowed; filter: none; }
|
|
242
|
+
.pendingInfo { background: #fff8c5; color: #7d4e00; font-size: 12.5px; padding: 10px 12px; border-radius: 6px; margin-top: 12px; line-height: 1.5; }
|
|
243
|
+
|
|
244
|
+
#manageList { overflow-y: auto; margin-top: 8px; }
|
|
245
|
+
.mg-project { border: 1px solid var(--border); border-radius: 8px; margin: 10px 0; overflow: hidden; }
|
|
246
|
+
.mg-phead { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 8px 12px; background: var(--bg-soft); border-bottom: 1px solid var(--border-soft); }
|
|
247
|
+
.mg-name { font-weight: 600; display: flex; align-items: center; gap: 7px; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
248
|
+
.mg-actions { display: flex; gap: 8px; flex: none; }
|
|
249
|
+
.btn.sm { font-size: 12px; padding: 4px 9px; }
|
|
250
|
+
.mg-vers { padding: 6px 12px; }
|
|
251
|
+
.mg-ver { display: flex; align-items: center; gap: 8px; padding: 4px 0; font-size: 13px; cursor: pointer; }
|
|
252
|
+
.mg-ver .mg-vn { font-weight: 600; font-family: var(--mono); font-size: 12.5px; }
|
|
253
|
+
.mg-meta { color: var(--fg-muted); font-size: 12px; }
|