claude-plan-review 0.5.0 → 0.5.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-plan-review",
3
- "version": "0.5.0",
3
+ "version": "0.5.2",
4
4
  "description": "Review, comment on, and approve/reject Claude Code plans in a local GitHub-style web UI — with persistent comments, version history, and diffs.",
5
5
  "type": "module",
6
6
  "bin": {
package/src/mcp.js CHANGED
@@ -25,12 +25,13 @@ import { getReview, recordPlan } from "./store.js";
25
25
 
26
26
  const HERE = dirname(fileURLToPath(import.meta.url));
27
27
  const SERVER_SCRIPT = join(HERE, "server.js");
28
+ const pkg = JSON.parse(readFileSync(join(HERE, "..", "package.json"), "utf8"));
28
29
 
29
30
  // Latest MCP protocol revision we implement. We echo the client's requested
30
31
  // version back when it sends one (the compatible behaviour for a version-
31
32
  // agnostic tools server), else advertise this.
32
33
  const PROTOCOL_VERSION = "2025-06-18";
33
- const SERVER_INFO = { name: "claude-plan-review", version: "0.4.0" };
34
+ const SERVER_INFO = { name: "claude-plan-review", version: pkg.version };
34
35
 
35
36
  const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
36
37
 
package/src/ui/app.js CHANGED
@@ -35,7 +35,7 @@ const state = {
35
35
  docCache: new Map(), // slug → {slug,title,parent,markdown,html}
36
36
  manifestCache: new Map(), // version n → manifest|null (for the diff doc union)
37
37
  allComments: [], // every comment on the version (each carries `doc`) — drives badges
38
- viewAsTree: false, // single-doc display-only outline mode
38
+ viewAsTree: true, // single-doc display-only outline mode (always on for single-doc plans)
39
39
  treeSection: -1, // selected outline section index (-1 = show all)
40
40
  _sections: null, // cached outline sections for the current preview
41
41
  // --- deletion ---
@@ -89,8 +89,6 @@ function showEmpty(msg) {
89
89
  $("docSidebar").hidden = true;
90
90
  $("reviewActions").hidden = true;
91
91
  $("saveActions").hidden = true;
92
- $("deleteVerBtn").hidden = true;
93
- $("treeToggle").hidden = true;
94
92
  }
95
93
 
96
94
  async function loadProjects() {
@@ -123,7 +121,6 @@ async function selectProject(key, wantV) {
123
121
  const fmt = (v) => `v${v.n} · ${new Date(v.createdAt).toLocaleString()}${v.n === latest ? " (current)" : ""}`;
124
122
  $("versionSel").innerHTML = versions.map((v) => `<option value="${v.n}">${esc(fmt(v))}</option>`).join("");
125
123
  $("versionSel").value = String(state.version);
126
- $("deleteVerBtn").hidden = false;
127
124
 
128
125
  // base = the version right before current, if any
129
126
  state.baseVersion = versions.length > 1 ? versions[versions.findIndex((v) => v.n === state.version) - 1]?.n ?? versions[0].n : null;
@@ -139,7 +136,6 @@ async function selectProject(key, wantV) {
139
136
  async function loadVersion(n) {
140
137
  state.version = n;
141
138
  hideSelPop();
142
- state.viewAsTree = false;
143
139
  state.treeSection = -1;
144
140
  state.docCache = new Map();
145
141
  state.data = await api(`/api/projects/${enc(state.key)}/versions/${n}`);
@@ -149,7 +145,9 @@ async function loadVersion(n) {
149
145
  const isTree = docs.length > 1;
150
146
  state.kind = state.data.kind || (isTree ? "tree" : "single");
151
147
  $("diffCur").textContent = n;
152
- updateTreeToggle();
148
+ // Tree view is always on for single-doc plans (heading outline); real multi-doc
149
+ // trees use the doc sidebar instead, so they don't also apply the outline view.
150
+ state.viewAsTree = !isTree;
153
151
 
154
152
  if (isTree) {
155
153
  // sidebar badge counts come from one unscoped fetch; threads filter it per doc.
@@ -431,15 +429,6 @@ function renderHeadingTree() {
431
429
  return rows.join("");
432
430
  }
433
431
 
434
- function updateTreeToggle() {
435
- const isTree = state.manifest && state.manifest.docs.length > 1;
436
- const t = $("treeToggle");
437
- t.hidden = isTree; // real doc trees get the sidebar automatically
438
- if (isTree) state.viewAsTree = false;
439
- t.classList.toggle("active", state.viewAsTree);
440
- t.textContent = state.viewAsTree ? "Exit tree view" : "View as tree";
441
- }
442
-
443
432
  // ---------- comments ----------
444
433
  async function addComment(line, lineEnd, body, quote) {
445
434
  if (!body.trim()) return;
@@ -1025,15 +1014,6 @@ function wireUI() {
1025
1014
  };
1026
1015
  });
1027
1016
 
1028
- // view-as-tree (single-doc, display-only)
1029
- $("treeToggle").onclick = () => {
1030
- state.viewAsTree = !state.viewAsTree;
1031
- state.treeSection = -1;
1032
- updateTreeToggle();
1033
- renderPreview();
1034
- renderSidebar();
1035
- };
1036
-
1037
1017
  // sidebar navigation — doc rows (tree) or outline sections (view-as-tree)
1038
1018
  $("docSidebar").addEventListener("click", (e) => {
1039
1019
  const row = e.target.closest("[data-doc]");
@@ -1106,8 +1086,8 @@ function wireUI() {
1106
1086
  await resolve("reject");
1107
1087
  };
1108
1088
 
1109
- // deletion + manage — delete fires immediately; the modal is blocked-only
1110
- $("deleteVerBtn").onclick = () => deleteVersionNow();
1089
+ // deletion + manage — header entry points are hidden for now, but the underlying
1090
+ // logic (deleteVersionNow / openManageModal / performDelete) is kept intact.
1111
1091
  $("deleteCancel").onclick = async () => {
1112
1092
  const pd = state.pendingDelete;
1113
1093
  $("deleteModal").hidden = true;
@@ -1120,7 +1100,6 @@ function wireUI() {
1120
1100
  };
1121
1101
  $("deleteForce").onclick = () => performDelete(true);
1122
1102
 
1123
- $("manageBtn").onclick = () => openManageModal();
1124
1103
  $("manageClose").onclick = () => ($("manageModal").hidden = true);
1125
1104
  $("manageList").addEventListener("click", (e) => {
1126
1105
  const btn = e.target.closest("[data-mg]");
package/src/ui/index.html CHANGED
@@ -24,7 +24,6 @@
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>
28
27
  </div>
29
28
  <div class="saveActions" id="saveActions" hidden>
30
29
  <button class="btn" id="saveBtn">Save to gist</button>
@@ -35,7 +34,6 @@
35
34
  <button class="btn approve" id="approveBtn">Approve plan</button>
36
35
  <button class="btn reject" id="rejectBtn">Request changes</button>
37
36
  </div>
38
- <button class="iconbtn" id="manageBtn" title="Manage &amp; delete plans" aria-label="Manage plans">🗄</button>
39
37
  <button class="iconbtn" id="themeToggle" title="Toggle light / dark theme" aria-label="Toggle theme">🌓</button>
40
38
  </header>
41
39
 
@@ -49,7 +47,6 @@
49
47
  <section class="panel active" id="panel-preview">
50
48
  <div class="preview-toolbar">
51
49
  <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
50
  </div>
54
51
  <div class="preview-layout">
55
52
  <aside class="doc-sidebar" id="docSidebar" hidden></aside>
package/src/ui/style.css CHANGED
@@ -200,9 +200,6 @@ textarea {
200
200
  /* ---------- multi-document: sidebar + layout ---------- */
201
201
  .preview-toolbar { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin: 0 0 10px; }
202
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
203
 
207
204
  .preview-layout { display: flex; align-items: flex-start; gap: 20px; }
208
205
  .preview-main { flex: 1; min-width: 0; }