create-walle 0.9.30 → 0.9.31
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 +1 -1
- package/template/claude-task-manager/api-prompts.js +4 -4
- package/template/claude-task-manager/api-reviews.js +153 -3
- package/template/claude-task-manager/approval-agent.js +37 -5
- package/template/claude-task-manager/docs/prompt-manager-redesign-proposal.html +666 -0
- package/template/claude-task-manager/docs/resume-ux-redesign.html +493 -0
- package/template/claude-task-manager/docs/review-redesign-proposal.html +892 -0
- package/template/claude-task-manager/lib/db-owner-cooperative-scheduler.js +10 -1
- package/template/claude-task-manager/lib/headless-term-service.js +12 -1
- package/template/claude-task-manager/lib/native-agent-model-args.js +118 -0
- package/template/claude-task-manager/lib/session-history.js +4 -1
- package/template/claude-task-manager/lib/tui-input-modes.js +40 -0
- package/template/claude-task-manager/providers/claude-code.js +20 -1
- package/template/claude-task-manager/public/css/reviews.css +232 -0
- package/template/claude-task-manager/public/index.html +785 -134
- package/template/claude-task-manager/public/js/document-review-links.js +40 -4
- package/template/claude-task-manager/public/js/file-context-menu.js +185 -0
- package/template/claude-task-manager/public/js/message-renderer.js +27 -1
- package/template/claude-task-manager/public/js/resume-state.js +186 -0
- package/template/claude-task-manager/public/js/reviews.js +377 -70
- package/template/claude-task-manager/public/js/screenshot-router.js +91 -0
- package/template/claude-task-manager/public/js/session-search-utils.js +26 -0
- package/template/claude-task-manager/public/js/state-sync-client.js +95 -17
- package/template/claude-task-manager/public/js/stream-view.js +87 -20
- package/template/claude-task-manager/server.js +151 -6
- package/template/package.json +1 -1
- package/template/wall-e/api-walle.js +21 -3
- package/template/wall-e/chat.js +101 -8
- package/template/wall-e/llm/client.js +64 -5
- package/template/wall-e/llm/codex-cli.js +71 -23
- package/template/wall-e/llm/codex-cli.plugin.json +1 -0
- package/template/wall-e/llm/default-fallback.js +12 -6
- package/template/wall-e/llm/provider-error.js +7 -1
- package/template/wall-e/llm/provider-health-state.js +557 -11
- package/template/wall-e/llm/registry.js +6 -0
- package/template/wall-e/llm/routing-policy.js +255 -25
|
@@ -0,0 +1,666 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en" data-theme="dark">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
6
|
+
<title>CTM Prompt Manager — Redesign Proposal</title>
|
|
7
|
+
<style>
|
|
8
|
+
/* ===== CTM theme tokens (copied verbatim from index.html so this mock reads native) ===== */
|
|
9
|
+
:root {
|
|
10
|
+
--bg: #1a1b26; --bg-light: #24283b; --bg-lighter: #2f3349; --bg-card: #24283b;
|
|
11
|
+
--bg-panel: #1f2335; --bg-elevated: #2b3045; --bg-input: #1a1b26;
|
|
12
|
+
--bg-hover: rgba(255,255,255,0.06); --code-bg: rgba(122,162,247,0.12);
|
|
13
|
+
--fg: #c0caf5; --fg-dim: #565f89; --fg-muted: #8b94bd;
|
|
14
|
+
--accent: #7aa2f7; --accent-hover: #89b4fa; --accent-fg: #0d1117; --accent-soft: rgba(122,162,247,0.13);
|
|
15
|
+
--green: #9ece6a; --success-soft: rgba(158,206,106,0.14);
|
|
16
|
+
--red: #f7768e; --danger-soft: rgba(247,118,142,0.14);
|
|
17
|
+
--yellow: #e0af68; --warning-soft: rgba(224,175,104,0.14);
|
|
18
|
+
--purple: #bb9af7; --border: #3b4261; --focus-ring: rgba(122,162,247,0.32);
|
|
19
|
+
--overlay-bg: rgba(5,8,15,0.72);
|
|
20
|
+
--syn-kw: #bb9af7; --syn-fn: #7aa2f7; --syn-str: #9ece6a; --syn-num: #ff9e64;
|
|
21
|
+
--syn-com: #565f89; --syn-type: #2ac3de; --syn-prop: #73daca; --syn-punc: #89ddff;
|
|
22
|
+
--shadow-lg: 0 18px 46px rgba(0,0,0,0.42), 0 0 0 1px rgba(255,255,255,0.03) inset;
|
|
23
|
+
}
|
|
24
|
+
html[data-theme="light"] {
|
|
25
|
+
--bg: #f6f7f9; --bg-light: #ffffff; --bg-lighter: #eceef2; --bg-card: #ffffff;
|
|
26
|
+
--bg-panel: #fafbfc; --bg-elevated: #ffffff; --bg-input: #ffffff;
|
|
27
|
+
--bg-hover: rgba(15,23,42,0.045); --code-bg: rgba(15,23,42,0.06);
|
|
28
|
+
--fg: #0f172a; --fg-dim: #3d4b5e; --fg-muted: #52606f;
|
|
29
|
+
--accent: #3b66e0; --accent-hover: #2c54c8; --accent-fg: #ffffff; --accent-soft: rgba(59,102,224,0.10);
|
|
30
|
+
--green: #15803d; --success-soft: rgba(21,128,61,0.10);
|
|
31
|
+
--red: #b91c1c; --danger-soft: rgba(185,28,28,0.10);
|
|
32
|
+
--yellow: #92400e; --warning-soft: rgba(146,64,14,0.10);
|
|
33
|
+
--purple: #7c3aed; --border: rgba(15,23,42,0.10); --focus-ring: rgba(59,102,224,0.32);
|
|
34
|
+
--overlay-bg: rgba(15,23,42,0.40);
|
|
35
|
+
--syn-kw: #7c3aed; --syn-fn: #2c54c8; --syn-str: #15803d; --syn-num: #b45309;
|
|
36
|
+
--syn-com: #94a3b8; --syn-type: #0e7490; --syn-prop: #0f766e; --syn-punc: #2563eb;
|
|
37
|
+
--shadow-lg: 0 24px 60px rgba(15,23,42,0.18), 0 8px 20px rgba(15,23,42,0.08), 0 0 0 1px rgba(15,23,42,0.04);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
41
|
+
html { scroll-behavior: smooth; }
|
|
42
|
+
body {
|
|
43
|
+
font-family: -apple-system, BlinkMacSystemFont, 'SF Pro Text', 'Segoe UI', system-ui, sans-serif;
|
|
44
|
+
background: var(--bg); color: var(--fg);
|
|
45
|
+
line-height: 1.55; -webkit-font-smoothing: antialiased;
|
|
46
|
+
}
|
|
47
|
+
.mono { font-family: 'SF Mono', 'JetBrains Mono', Menlo, Consolas, monospace; }
|
|
48
|
+
a { color: var(--accent); }
|
|
49
|
+
|
|
50
|
+
/* ===== proposal chrome ===== */
|
|
51
|
+
.topbar {
|
|
52
|
+
position: sticky; top: 0; z-index: 50;
|
|
53
|
+
display: flex; align-items: center; gap: 18px;
|
|
54
|
+
padding: 12px 26px; background: color-mix(in srgb, var(--bg) 86%, transparent);
|
|
55
|
+
backdrop-filter: blur(14px) saturate(1.1); border-bottom: 1px solid var(--border);
|
|
56
|
+
}
|
|
57
|
+
.topbar .brand { font-weight: 700; letter-spacing: -0.01em; font-size: 15px; }
|
|
58
|
+
.topbar .brand b { color: var(--accent); }
|
|
59
|
+
.topbar nav { display: flex; gap: 4px; margin-left: 6px; flex-wrap: wrap; }
|
|
60
|
+
.topbar nav a { font-size: 12.5px; color: var(--fg-muted); text-decoration: none; padding: 5px 10px; border-radius: 7px; }
|
|
61
|
+
.topbar nav a:hover { background: var(--bg-hover); color: var(--fg); }
|
|
62
|
+
.topbar .spacer { flex: 1; }
|
|
63
|
+
.toggle {
|
|
64
|
+
display: inline-flex; align-items: center; gap: 7px; cursor: pointer;
|
|
65
|
+
font-size: 12px; color: var(--fg-dim); background: var(--bg-light);
|
|
66
|
+
border: 1px solid var(--border); border-radius: 8px; padding: 6px 11px; user-select: none;
|
|
67
|
+
}
|
|
68
|
+
.toggle:hover { color: var(--fg); border-color: var(--accent); }
|
|
69
|
+
|
|
70
|
+
.wrap { max-width: 1180px; margin: 0 auto; padding: 0 26px 120px; }
|
|
71
|
+
.hero { padding: 64px 0 30px; }
|
|
72
|
+
.eyebrow { font-size: 11px; font-weight: 700; letter-spacing: 0.14em; text-transform: uppercase; color: var(--accent); margin-bottom: 16px; }
|
|
73
|
+
.hero h1 { font-size: 42px; line-height: 1.08; letter-spacing: -0.025em; font-weight: 750; max-width: 19ch; }
|
|
74
|
+
.hero h1 em { font-style: normal; color: var(--accent); }
|
|
75
|
+
.hero p.lead { margin-top: 18px; font-size: 17px; color: var(--fg-muted); max-width: 66ch; line-height: 1.6; }
|
|
76
|
+
.meta-row { margin-top: 26px; display: flex; gap: 22px; flex-wrap: wrap; font-size: 12.5px; color: var(--fg-dim); }
|
|
77
|
+
.meta-row b { color: var(--fg); font-weight: 600; }
|
|
78
|
+
|
|
79
|
+
section { padding: 46px 0; border-top: 1px solid var(--border); }
|
|
80
|
+
.sec-head { display: flex; align-items: baseline; gap: 14px; margin-bottom: 8px; }
|
|
81
|
+
.sec-num { font-size: 12px; font-weight: 700; color: var(--accent); font-family: 'SF Mono', Menlo, monospace; background: var(--accent-soft); border-radius: 6px; padding: 3px 8px; }
|
|
82
|
+
h2 { font-size: 27px; letter-spacing: -0.02em; font-weight: 700; }
|
|
83
|
+
.sec-sub { color: var(--fg-muted); font-size: 15px; max-width: 74ch; margin: 14px 0 30px; line-height: 1.6; }
|
|
84
|
+
|
|
85
|
+
/* ===== issue audit cards ===== */
|
|
86
|
+
.issues { display: grid; grid-template-columns: repeat(auto-fit, minmax(330px, 1fr)); gap: 16px; }
|
|
87
|
+
.issue { background: var(--bg-card); border: 1px solid var(--border); border-radius: 12px; padding: 20px 20px 18px; position: relative; overflow: hidden; }
|
|
88
|
+
.issue::before { content: ''; position: absolute; left: 0; top: 0; bottom: 0; width: 3px; background: var(--red); }
|
|
89
|
+
.issue .tag { display: inline-block; font-size: 10.5px; font-weight: 700; letter-spacing: 0.05em; text-transform: uppercase; color: var(--red); background: var(--danger-soft); padding: 3px 8px; border-radius: 5px; margin-bottom: 11px; }
|
|
90
|
+
.issue h3 { font-size: 15.5px; font-weight: 650; margin-bottom: 8px; }
|
|
91
|
+
.issue p { font-size: 13.5px; color: var(--fg-muted); line-height: 1.55; }
|
|
92
|
+
.issue code { font-family: 'SF Mono', Menlo, monospace; font-size: 11.5px; color: var(--fg-dim); background: var(--code-bg); padding: 1px 5px; border-radius: 4px; }
|
|
93
|
+
.issue .fix { margin-top: 13px; padding-top: 12px; border-top: 1px dashed var(--border); font-size: 12.5px; color: var(--fg); display: flex; gap: 8px; }
|
|
94
|
+
.issue .fix b { color: var(--green); font-weight: 700; flex-shrink: 0; }
|
|
95
|
+
|
|
96
|
+
/* ===== mock frame ===== */
|
|
97
|
+
.mock { margin-top: 6px; border: 1px solid var(--border); border-radius: 14px; overflow: hidden; box-shadow: var(--shadow-lg); background: var(--bg); }
|
|
98
|
+
.mock-caption { display: flex; align-items: center; gap: 9px; padding: 9px 14px; background: var(--bg-lighter); border-bottom: 1px solid var(--border); font-size: 11.5px; color: var(--fg-dim); }
|
|
99
|
+
.dot { width: 10px; height: 10px; border-radius: 50%; flex-shrink: 0; }
|
|
100
|
+
.dot.r { background: #ff5f57; } .dot.y { background: #febc2e; } .dot.g { background: #28c840; }
|
|
101
|
+
.mock-caption .url { margin-left: 10px; font-family: 'SF Mono', Menlo, monospace; font-size: 11px; color: var(--fg-muted); background: var(--bg); border: 1px solid var(--border); border-radius: 7px; padding: 4px 12px; flex: 1; }
|
|
102
|
+
.mock-label { font-size: 11.5px; color: var(--fg-dim); margin: 16px 0 6px; font-family: 'SF Mono', Menlo, monospace; }
|
|
103
|
+
|
|
104
|
+
/* shared app shell inside mocks */
|
|
105
|
+
.shell-header { display: flex; align-items: center; gap: 12px; padding: 11px 16px; background: var(--bg-panel); border-bottom: 1px solid var(--border); }
|
|
106
|
+
.searchbox { display: flex; align-items: center; gap: 9px; background: var(--bg-input); border: 1px solid var(--border); border-radius: 9px; padding: 7px 13px; color: var(--fg-dim); font-size: 13px; }
|
|
107
|
+
.searchbox svg { flex-shrink: 0; opacity: 0.7; }
|
|
108
|
+
.kbd { font-family: 'SF Mono', Menlo, monospace; font-size: 10.5px; color: var(--fg-dim); border: 1px solid var(--border); border-radius: 5px; padding: 1px 6px; background: var(--bg); }
|
|
109
|
+
.grow { flex: 1; }
|
|
110
|
+
.btn-accent { font-size: 12.5px; font-weight: 600; color: var(--accent-fg); background: var(--accent); border: 0; border-radius: 8px; padding: 6px 13px; cursor: default; }
|
|
111
|
+
|
|
112
|
+
/* ===== axis table (the real problem) ===== */
|
|
113
|
+
.axis-table { width: 100%; border-collapse: collapse; margin-top: 8px; font-size: 13px; }
|
|
114
|
+
.axis-table th { text-align: left; font-size: 10.5px; text-transform: uppercase; letter-spacing: 0.06em; color: var(--fg-dim); padding: 9px 12px; border-bottom: 1px solid var(--border); font-weight: 700; }
|
|
115
|
+
.axis-table td { padding: 11px 12px; border-bottom: 1px solid var(--border); color: var(--fg-muted); vertical-align: top; line-height: 1.5; }
|
|
116
|
+
.axis-table td b { color: var(--fg); font-weight: 600; }
|
|
117
|
+
.axis-table .ax { font-family: 'SF Mono', Menlo, monospace; color: var(--accent); white-space: nowrap; }
|
|
118
|
+
.axis-table .collide { color: var(--red); }
|
|
119
|
+
|
|
120
|
+
/* ===== prompt-manager sidebar/list mock ===== */
|
|
121
|
+
.pm-shell { display: grid; grid-template-columns: 264px 1fr; min-height: 452px; background: var(--bg); }
|
|
122
|
+
.pm-side { border-right: 1px solid var(--border); background: var(--bg-panel); padding: 14px 12px; display: flex; flex-direction: column; gap: 14px; }
|
|
123
|
+
.pm-bigsearch { display: flex; align-items: center; gap: 9px; background: var(--bg-input); border: 1px solid var(--border); border-radius: 10px; padding: 9px 12px; font-size: 13px; color: var(--fg-dim); }
|
|
124
|
+
.pm-bigsearch svg { opacity: 0.6; }
|
|
125
|
+
.pm-group-title { font-size: 10px; font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase; color: var(--fg-dim); margin: 0 4px 7px; }
|
|
126
|
+
.pm-quick { display: flex; flex-direction: column; gap: 2px; }
|
|
127
|
+
.pm-qitem { display: flex; align-items: center; gap: 10px; padding: 7px 10px; border-radius: 8px; font-size: 13px; color: var(--fg-muted); cursor: pointer; }
|
|
128
|
+
.pm-qitem:hover { background: var(--bg-hover); color: var(--fg); }
|
|
129
|
+
.pm-qitem.active { background: var(--accent-soft); color: var(--accent); font-weight: 600; }
|
|
130
|
+
.pm-qitem .ct { margin-left: auto; font-size: 10.5px; color: var(--fg-dim); font-family: 'SF Mono', Menlo, monospace; }
|
|
131
|
+
.pm-qitem.active .ct { color: var(--accent); }
|
|
132
|
+
.pm-tags { display: flex; flex-wrap: wrap; gap: 6px; }
|
|
133
|
+
.tag-chip { font-size: 11px; padding: 3px 9px; border-radius: 20px; background: var(--bg-lighter); color: var(--fg-muted); border: 1px solid var(--border); cursor: pointer; }
|
|
134
|
+
.tag-chip:hover { border-color: var(--accent); }
|
|
135
|
+
.tag-chip.on { background: var(--accent); color: var(--accent-fg); border-color: var(--accent); font-weight: 600; }
|
|
136
|
+
.pm-main { padding: 16px 18px; overflow: hidden; }
|
|
137
|
+
.pm-mainhead { display: flex; align-items: center; gap: 10px; margin-bottom: 14px; }
|
|
138
|
+
.pm-mainhead h4 { font-size: 13px; font-weight: 700; letter-spacing: 0.02em; text-transform: uppercase; color: var(--fg-muted); }
|
|
139
|
+
.pm-mainhead .count { font-size: 11px; color: var(--fg-dim); background: var(--bg-lighter); border-radius: 20px; padding: 2px 9px; font-weight: 600; }
|
|
140
|
+
.pm-row { display: flex; align-items: center; gap: 13px; padding: 12px 14px; border: 1px solid var(--border); border-radius: 11px; margin-bottom: 8px; background: var(--bg-card); cursor: pointer; transition: border-color .12s, transform .12s; }
|
|
141
|
+
.pm-row:hover { border-color: var(--accent); transform: translateX(2px); }
|
|
142
|
+
.pm-row.sel { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent-soft); }
|
|
143
|
+
.pm-row .star { color: var(--yellow); flex-shrink: 0; }
|
|
144
|
+
.pm-row .star.off { color: var(--fg-dim); }
|
|
145
|
+
.pm-row .pbody { flex: 1; min-width: 0; }
|
|
146
|
+
.pm-row .ptitle { font-size: 13.5px; font-weight: 600; display: flex; align-items: center; gap: 8px; }
|
|
147
|
+
.pm-row .ptitle mark { background: var(--warning-soft); color: var(--yellow); border-radius: 3px; padding: 0 2px; }
|
|
148
|
+
.pm-row .psub { font-size: 11px; color: var(--fg-dim); margin-top: 4px; display: flex; gap: 8px; align-items: center; }
|
|
149
|
+
.mini-tag { font-family: 'SF Mono', Menlo, monospace; font-size: 10px; color: var(--purple); background: color-mix(in srgb, var(--purple) 12%, transparent); border-radius: 5px; padding: 1px 6px; }
|
|
150
|
+
.vbadge { font-family: 'SF Mono', Menlo, monospace; font-size: 10px; color: var(--green); background: var(--success-soft); border-radius: 5px; padding: 1px 6px; }
|
|
151
|
+
.pm-row .when { margin-left: auto; font-size: 10.5px; color: var(--fg-dim); font-family: 'SF Mono', Menlo, monospace; flex-shrink: 0; }
|
|
152
|
+
|
|
153
|
+
/* ===== editor split mock ===== */
|
|
154
|
+
.ed-toolbar { display: flex; align-items: center; gap: 5px; padding: 8px 14px; background: var(--bg-panel); border-bottom: 1px solid var(--border); font-size: 11.5px; color: var(--fg-dim); }
|
|
155
|
+
.ed-toolbar .tb { border: 1px solid var(--border); border-radius: 6px; padding: 2px 8px; background: var(--bg-light); font-family: 'SF Mono', Menlo, monospace; font-size: 11px; }
|
|
156
|
+
.ed-toolbar .seg { display: inline-flex; background: var(--bg-light); border: 1px solid var(--border); border-radius: 8px; padding: 2px; gap: 2px; }
|
|
157
|
+
.ed-toolbar .seg b { font-weight: 600; font-size: 11px; color: var(--fg-muted); padding: 3px 9px; border-radius: 5px; }
|
|
158
|
+
.ed-toolbar .seg b.on { background: var(--accent); color: var(--accent-fg); }
|
|
159
|
+
.token-meter { margin-left: auto; font-family: 'SF Mono', Menlo, monospace; font-size: 11px; color: var(--fg-dim); display: inline-flex; gap: 6px; align-items: center; }
|
|
160
|
+
.token-meter .ok { color: var(--green); }
|
|
161
|
+
.ed-split { display: grid; grid-template-columns: 1fr 1fr; min-height: 312px; background: var(--bg); }
|
|
162
|
+
.ed-pane { padding: 18px 20px; font-family: 'SF Mono', 'JetBrains Mono', Menlo, monospace; font-size: 12.5px; line-height: 1.85; overflow: hidden; }
|
|
163
|
+
.ed-pane.left { border-right: 1px solid var(--border); }
|
|
164
|
+
.ed-pane .ln { color: var(--fg); white-space: pre-wrap; }
|
|
165
|
+
.var-tok { color: var(--purple); background: color-mix(in srgb, var(--purple) 16%, transparent); border-radius: 4px; padding: 0 3px; }
|
|
166
|
+
.ctx-tok { color: var(--syn-num); background: color-mix(in srgb, var(--syn-num) 16%, transparent); border-radius: 4px; padding: 0 3px; }
|
|
167
|
+
.md-h { color: var(--syn-fn); font-weight: 700; }
|
|
168
|
+
.md-bullet { color: var(--accent); }
|
|
169
|
+
.md-code { color: var(--syn-str); }
|
|
170
|
+
.pane-tag { font-family: 'SF Mono', Menlo, monospace; font-size: 10px; color: var(--fg-dim); text-transform: uppercase; letter-spacing: 0.08em; margin-bottom: 12px; display: block; }
|
|
171
|
+
.prev-body { font-family: -apple-system, system-ui, sans-serif; font-size: 13px; line-height: 1.65; color: var(--fg); }
|
|
172
|
+
.prev-body h3 { font-size: 16px; margin-bottom: 8px; }
|
|
173
|
+
.prev-body p { color: var(--fg-muted); margin-bottom: 8px; }
|
|
174
|
+
.prev-body .pill { color: var(--accent); font-weight: 600; }
|
|
175
|
+
|
|
176
|
+
/* ===== centered floating mock stage (fill-form, palette) ===== */
|
|
177
|
+
.mock-stage { padding: 40px 20px; background: var(--bg); display: grid; place-items: center; background-image: radial-gradient(circle at 1px 1px, var(--bg-hover) 1px, transparent 0); background-size: 22px 22px; }
|
|
178
|
+
.fillform { width: 430px; background: var(--bg-elevated); border: 1px solid var(--border); border-radius: 13px; box-shadow: var(--shadow-lg); padding: 18px 20px; }
|
|
179
|
+
.ff-head { display: flex; align-items: center; gap: 9px; margin-bottom: 16px; }
|
|
180
|
+
.ff-head .fft { font-size: 14px; font-weight: 650; }
|
|
181
|
+
.ff-head .ffs { font-size: 11px; color: var(--fg-dim); margin-left: auto; font-family: 'SF Mono', Menlo, monospace; }
|
|
182
|
+
.ff-field { margin-bottom: 13px; }
|
|
183
|
+
.ff-field label { display: block; font-size: 10.5px; color: var(--fg-dim); margin-bottom: 5px; text-transform: uppercase; letter-spacing: 0.05em; }
|
|
184
|
+
.ff-field label b { color: var(--purple); font-family: 'SF Mono', Menlo, monospace; text-transform: none; letter-spacing: 0; }
|
|
185
|
+
.ff-input { background: var(--bg-input); border: 1px solid var(--border); border-radius: 8px; padding: 8px 12px; font-size: 13px; color: var(--fg); font-family: 'SF Mono', Menlo, monospace; display: flex; align-items: center; gap: 8px; }
|
|
186
|
+
.ff-input.focused { border-color: var(--accent); box-shadow: 0 0 0 3px var(--focus-ring); }
|
|
187
|
+
.ff-input .ph { color: var(--fg-dim); }
|
|
188
|
+
.ff-input.select { justify-content: space-between; }
|
|
189
|
+
.ff-actions { display: flex; gap: 9px; margin-top: 18px; }
|
|
190
|
+
.ff-btn { flex: 1; text-align: center; font-size: 12.5px; font-weight: 600; padding: 8px; border-radius: 8px; cursor: default; }
|
|
191
|
+
.ff-btn.primary { background: var(--accent); color: var(--accent-fg); }
|
|
192
|
+
.ff-btn.ghost { background: var(--bg-light); color: var(--fg-muted); border: 1px solid var(--border); }
|
|
193
|
+
|
|
194
|
+
.palette { width: 500px; background: var(--bg-elevated); border: 1px solid var(--border); border-radius: 13px; box-shadow: var(--shadow-lg); overflow: hidden; }
|
|
195
|
+
.pal-search { display: flex; align-items: center; gap: 11px; padding: 14px 17px; border-bottom: 1px solid var(--border); font-size: 14.5px; color: var(--fg); }
|
|
196
|
+
.pal-search svg { opacity: 0.6; }
|
|
197
|
+
.pal-search .cursor { width: 1.5px; height: 17px; background: var(--accent); animation: blink 1.1s steps(1) infinite; }
|
|
198
|
+
@keyframes blink { 50% { opacity: 0; } }
|
|
199
|
+
.pal-sec { font-size: 10px; font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase; color: var(--fg-dim); padding: 10px 17px 5px; }
|
|
200
|
+
.pal-item { display: flex; align-items: center; gap: 12px; padding: 9px 17px; cursor: pointer; }
|
|
201
|
+
.pal-item.sel { background: var(--accent-soft); box-shadow: inset 3px 0 0 var(--accent); }
|
|
202
|
+
.pal-item .pi-icn { color: var(--accent); flex-shrink: 0; }
|
|
203
|
+
.pal-item .pi-title { font-size: 13.5px; color: var(--fg); }
|
|
204
|
+
.pal-item .pi-title b { color: var(--accent); }
|
|
205
|
+
.pal-item .pi-sub { font-size: 10.5px; color: var(--fg-dim); margin-left: auto; font-family: 'SF Mono', Menlo, monospace; }
|
|
206
|
+
.pal-foot { display: flex; gap: 16px; padding: 9px 17px; border-top: 1px solid var(--border); background: var(--bg-panel); font-size: 11px; color: var(--fg-dim); }
|
|
207
|
+
|
|
208
|
+
/* ===== prior-art callout ===== */
|
|
209
|
+
.priorart { display: flex; gap: 13px; margin-top: 20px; padding: 14px 17px; background: var(--bg-lighter); border: 1px solid var(--border); border-radius: 11px; font-size: 12.5px; color: var(--fg-muted); line-height: 1.55; }
|
|
210
|
+
.priorart .pa-icn { color: var(--purple); flex-shrink: 0; margin-top: 1px; }
|
|
211
|
+
.priorart b { color: var(--fg); font-weight: 600; }
|
|
212
|
+
.priorart code { font-family: 'SF Mono', Menlo, monospace; font-size: 11px; color: var(--accent); background: var(--accent-soft); border-radius: 4px; padding: 1px 5px; }
|
|
213
|
+
|
|
214
|
+
/* ===== alternative option cards ===== */
|
|
215
|
+
.alt-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 18px; margin-top: 8px; }
|
|
216
|
+
.alt-card { background: var(--bg-card); border: 1px solid var(--border); border-radius: 12px; padding: 20px; }
|
|
217
|
+
.alt-card.rec { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent-soft); }
|
|
218
|
+
.alt-card h4 { font-size: 15px; margin-bottom: 4px; display: flex; align-items: center; gap: 9px; flex-wrap: wrap; }
|
|
219
|
+
.alt-card .rectag { font-size: 10px; font-weight: 700; letter-spacing: 0.05em; text-transform: uppercase; color: var(--accent-fg); background: var(--accent); padding: 2px 8px; border-radius: 20px; }
|
|
220
|
+
.alt-card .sub { font-size: 12.5px; color: var(--fg-dim); margin-bottom: 13px; }
|
|
221
|
+
.alt-card ul { list-style: none; }
|
|
222
|
+
.alt-card li { font-size: 13px; color: var(--fg-muted); padding: 5px 0 5px 22px; position: relative; line-height: 1.5; }
|
|
223
|
+
.alt-card li::before { content: '→'; position: absolute; left: 0; color: var(--accent); }
|
|
224
|
+
.alt-card li.con::before { content: '×'; color: var(--red); }
|
|
225
|
+
.alt-card code { font-family: 'SF Mono', Menlo, monospace; font-size: 11.5px; color: var(--accent); background: var(--accent-soft); border-radius: 4px; padding: 1px 5px; }
|
|
226
|
+
|
|
227
|
+
/* ===== roadmap ===== */
|
|
228
|
+
.roadmap { display: flex; flex-direction: column; gap: 2px; margin-top: 10px; }
|
|
229
|
+
.phase { display: flex; gap: 16px; padding: 17px 18px; background: var(--bg-card); border: 1px solid var(--border); }
|
|
230
|
+
.phase:first-child { border-radius: 12px 12px 0 0; }
|
|
231
|
+
.phase:last-child { border-radius: 0 0 12px 12px; }
|
|
232
|
+
.phase .pn { font-family: 'SF Mono', Menlo, monospace; font-size: 13px; font-weight: 700; color: var(--accent); flex-shrink: 0; width: 92px; }
|
|
233
|
+
.phase .pn small { display: block; color: var(--fg-dim); font-weight: 400; font-size: 10px; margin-top: 3px; }
|
|
234
|
+
.phase .pbody h4 { font-size: 14px; margin-bottom: 4px; }
|
|
235
|
+
.phase .pbody p { font-size: 12.5px; color: var(--fg-muted); line-height: 1.55; }
|
|
236
|
+
.phase .pbody code { font-family: 'SF Mono', Menlo, monospace; font-size: 11.5px; color: var(--fg-dim); background: var(--code-bg); padding: 1px 5px; border-radius: 4px; }
|
|
237
|
+
.phase .risk { font-size: 10.5px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; padding: 2px 8px; border-radius: 20px; margin-left: auto; flex-shrink: 0; height: fit-content; }
|
|
238
|
+
.risk.low { color: var(--green); background: var(--success-soft); }
|
|
239
|
+
.risk.med { color: var(--yellow); background: var(--warning-soft); }
|
|
240
|
+
|
|
241
|
+
footer { padding: 50px 0 0; border-top: 1px solid var(--border); color: var(--fg-dim); font-size: 12.5px; line-height: 1.7; }
|
|
242
|
+
footer a { color: var(--fg-muted); }
|
|
243
|
+
|
|
244
|
+
@media (max-width: 900px) {
|
|
245
|
+
.alt-grid { grid-template-columns: 1fr; }
|
|
246
|
+
.pm-shell, .ed-split { grid-template-columns: 1fr; }
|
|
247
|
+
.pm-side, .ed-pane.left { border-right: 0; border-bottom: 1px solid var(--border); }
|
|
248
|
+
.hero h1 { font-size: 32px; }
|
|
249
|
+
.palette, .fillform { width: 100%; }
|
|
250
|
+
}
|
|
251
|
+
</style>
|
|
252
|
+
</head>
|
|
253
|
+
<body>
|
|
254
|
+
|
|
255
|
+
<div class="topbar">
|
|
256
|
+
<div class="brand">CTM <b>Prompt Manager</b> — Redesign Proposal</div>
|
|
257
|
+
<nav>
|
|
258
|
+
<a href="#problem">The problem</a>
|
|
259
|
+
<a href="#audit">Issues</a>
|
|
260
|
+
<a href="#find">Findability</a>
|
|
261
|
+
<a href="#editor">Editor</a>
|
|
262
|
+
<a href="#reuse">Reuse</a>
|
|
263
|
+
<a href="#plan">Roadmap</a>
|
|
264
|
+
</nav>
|
|
265
|
+
<div class="spacer"></div>
|
|
266
|
+
<div class="toggle" onclick="toggleTheme()">
|
|
267
|
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="4"/><path d="M12 2v2M12 20v2M2 12h2M20 12h2M5 5l1.5 1.5M17.5 17.5L19 19M19 5l-1.5 1.5M6.5 17.5L5 19"/></svg>
|
|
268
|
+
<span id="themeLabel">Dark</span>
|
|
269
|
+
</div>
|
|
270
|
+
</div>
|
|
271
|
+
|
|
272
|
+
<div class="wrap">
|
|
273
|
+
|
|
274
|
+
<div class="hero">
|
|
275
|
+
<div class="eyebrow">Design proposal · v1</div>
|
|
276
|
+
<h1>Organize, author, and <em>reuse</em> prompts — without the maze.</h1>
|
|
277
|
+
<p class="lead">
|
|
278
|
+
The Prompt Manager isn't short on features — it's <b>over-axised</b>. Prompts are filed across
|
|
279
|
+
seven overlapping systems at once, the editor is a plain rich-text box that ignores what a prompt
|
|
280
|
+
actually is, and the most valuable capabilities are already in the database but never reach the UI.
|
|
281
|
+
This proposal fixes <b>findability</b>, <b>authoring</b>, and <b>reuse</b> in three phases — reusing
|
|
282
|
+
the schema and plumbing that already exist.
|
|
283
|
+
</p>
|
|
284
|
+
<div class="meta-row">
|
|
285
|
+
<div><b>Scope</b> · #prompts page only — sessions untouched</div>
|
|
286
|
+
<div><b>Surprise</b> · templates, variables & chains already in the DB</div>
|
|
287
|
+
<div><b>Theme</b> · native CTM tokens — toggle top-right</div>
|
|
288
|
+
</div>
|
|
289
|
+
</div>
|
|
290
|
+
|
|
291
|
+
<!-- ===================== THE REAL PROBLEM ===================== -->
|
|
292
|
+
<section id="problem">
|
|
293
|
+
<div class="sec-head"><span class="sec-num">01</span><h2>The real problem isn't too few features</h2></div>
|
|
294
|
+
<p class="sec-sub">
|
|
295
|
+
A deep dive across the frontend (<code class="mono">public/js/prompts.js</code>, ~4,260 lines),
|
|
296
|
+
backend (<code class="mono">api-prompts.js</code> + <code class="mono">db.js</code>), and the live UI
|
|
297
|
+
found the opposite of "missing features." Prompts can be filed along <b>seven independent axes at the
|
|
298
|
+
same time</b> — each its own filter, with no canonical mental model for where a prompt "lives." The
|
|
299
|
+
result is decision fatigue when saving and ambiguity when finding.
|
|
300
|
+
</p>
|
|
301
|
+
<table class="axis-table">
|
|
302
|
+
<thead><tr><th>Axis today</th><th>What it's for</th><th>Where it collides</th></tr></thead>
|
|
303
|
+
<tbody>
|
|
304
|
+
<tr><td class="ax">folders</td><td>Manual hierarchy in the sidebar</td><td class="collide">Overlaps tags & domains — three ways to "categorize"</td></tr>
|
|
305
|
+
<tr><td class="ax">7 domains</td><td>Hardcoded: coding, ops, writing, research, personal, meta, general</td><td class="collide">Same job as tags, but fixed & auto-assigned — can't edit</td></tr>
|
|
306
|
+
<tr><td class="ax">5 lifecycle states</td><td>draft / used / frequent / template / archived</td><td class="collide">Mixes <b>status</b> (draft) with <b>type</b> (template) with <b>usage</b> (frequent)</td></tr>
|
|
307
|
+
<tr><td class="ax">groups</td><td>1-level parent/child "composite" prompts</td><td class="collide">A fourth container concept beside folders</td></tr>
|
|
308
|
+
<tr><td class="ax">tags</td><td>Free-form per-prompt labels</td><td class="collide">The natural primary axis — but demoted below all the above</td></tr>
|
|
309
|
+
<tr><td class="ax">star</td><td>Favorite flag</td><td class="collide">Near-duplicate of pin</td></tr>
|
|
310
|
+
<tr><td class="ax">pin</td><td>Float-to-top flag</td><td class="collide">Near-duplicate of star</td></tr>
|
|
311
|
+
</tbody>
|
|
312
|
+
</table>
|
|
313
|
+
<p class="sec-sub" style="margin-top: 26px;">
|
|
314
|
+
Meanwhile, the editor is a <code class="mono">contenteditable</code> div driven by
|
|
315
|
+
<code class="mono">document.execCommand</code> (<code class="mono">prompts.js:184</code>,
|
|
316
|
+
<code class="mono">:358</code>) — WYSIWYG bold/italic/lists built for documents, not for the templated
|
|
317
|
+
markdown that coding prompts actually are. And three powerful capabilities already exist in the schema
|
|
318
|
+
but have <b>no real UI</b>: <code class="mono">is_template</code>/<code class="mono">template_vars</code>,
|
|
319
|
+
the <code class="mono">templates</code> table, and a full <code class="mono">chains</code> /
|
|
320
|
+
<code class="mono">chain_nodes</code> / <code class="mono">chain_edges</code> workflow graph
|
|
321
|
+
(<code class="mono">db.js</code> schema ~671–813).
|
|
322
|
+
</p>
|
|
323
|
+
</section>
|
|
324
|
+
|
|
325
|
+
<!-- ===================== AUDIT ===================== -->
|
|
326
|
+
<section id="audit">
|
|
327
|
+
<div class="sec-head"><span class="sec-num">02</span><h2>Issue audit — traced to code</h2></div>
|
|
328
|
+
<p class="sec-sub">Each issue is tied to the responsible code so the redesign targets causes, not symptoms.</p>
|
|
329
|
+
<div class="issues">
|
|
330
|
+
<div class="issue">
|
|
331
|
+
<span class="tag">Organization</span>
|
|
332
|
+
<h3>Seven filters, no mental model</h3>
|
|
333
|
+
<p>The sidebar header stacks <code>#pe-context-filter</code>, <code>#pe-lifecycle-filter</code>, a star toggle, search, and AI-search — plus folders, groups, and pins elsewhere. Saving a prompt means picking among redundant axes.</p>
|
|
334
|
+
<div class="fix"><b>FIX</b><span>Collapse to one model: search + favorites + tags primary; the rest auto-derived.</span></div>
|
|
335
|
+
</div>
|
|
336
|
+
<div class="issue">
|
|
337
|
+
<span class="tag">Editor</span>
|
|
338
|
+
<h3>A document editor for code prompts</h3>
|
|
339
|
+
<p>Plain <code>contenteditable</code> + <code>execCommand</code> — no markdown highlighting, no <code>{{variable}}</code> awareness, no live preview, no token count. Prompts are markdown, but you edit them as styled rich text.</p>
|
|
340
|
+
<div class="fix"><b>FIX</b><span>A markdown/code editor with variable highlighting, preview, and a live token meter.</span></div>
|
|
341
|
+
</div>
|
|
342
|
+
<div class="issue">
|
|
343
|
+
<span class="tag">Latent power</span>
|
|
344
|
+
<h3>Templates & variables exist — invisibly</h3>
|
|
345
|
+
<p><code>template_vars</code>, the <code>templates</code> table, and <code>chains</code> graph are all in <code>db.js</code>, but there's no form to fill variables and no chain UI. The best capability is dormant.</p>
|
|
346
|
+
<div class="fix"><b>FIX</b><span>Variable fill-in form at insert time; surface chains as a Phase 4 capability.</span></div>
|
|
347
|
+
</div>
|
|
348
|
+
<div class="issue">
|
|
349
|
+
<span class="tag">Reuse</span>
|
|
350
|
+
<h3>No quick path from prompt → session</h3>
|
|
351
|
+
<p>Reuse means: open #prompts, hunt, copy, switch tabs, paste. <code>sendToNewSession</code> (<code>prompts.js:2278</code>) exists, but there's no fast keyboard-first insert from wherever you are.</p>
|
|
352
|
+
<div class="fix"><b>FIX</b><span>A command-palette quick-insert over title + body, keyboard-only.</span></div>
|
|
353
|
+
</div>
|
|
354
|
+
<div class="issue">
|
|
355
|
+
<span class="tag">Search</span>
|
|
356
|
+
<h3>Strong engine, weak surface</h3>
|
|
357
|
+
<p>FTS5 full-text (<code>prompts_fts</code>) and semantic AI-search already exist server-side, but the UI buries them in a small box beside four other controls, with no scope clarity.</p>
|
|
358
|
+
<div class="fix"><b>FIX</b><span>Promote search to the primary affordance; results-first list, body matches highlighted.</span></div>
|
|
359
|
+
</div>
|
|
360
|
+
<div class="issue" style="--red: var(--green);">
|
|
361
|
+
<span class="tag" style="color: var(--green); background: var(--success-soft);">Reusable</span>
|
|
362
|
+
<h3>What's already good — keep it</h3>
|
|
363
|
+
<p>Versioning (<code>prompt_versions</code>), usage tracking (<code>prompt_usage</code>), FTS5, the copilot/improve endpoints, image annotation, and the token system all stay. This is mostly a <b>front-end</b> reshaping.</p>
|
|
364
|
+
<div class="fix"><b>KEEP</b><span>No schema rewrite — activate what's there, add small additive endpoints.</span></div>
|
|
365
|
+
</div>
|
|
366
|
+
</div>
|
|
367
|
+
</section>
|
|
368
|
+
|
|
369
|
+
<!-- ===================== FINDABILITY ===================== -->
|
|
370
|
+
<section id="find">
|
|
371
|
+
<div class="sec-head"><span class="sec-num">03</span><h2>Findability — one model, not seven</h2></div>
|
|
372
|
+
<p class="sec-sub">
|
|
373
|
+
Phase 1 flagship. Make the sidebar answer one question — "which prompt do I want?" — with a big
|
|
374
|
+
search up top, three quick-views (Favorites / Recent / All), and <b>tags as the one editable axis</b>.
|
|
375
|
+
Domains and lifecycle become auto-derived facets, not manual choices you have to make on every save.
|
|
376
|
+
</p>
|
|
377
|
+
|
|
378
|
+
<div class="mock">
|
|
379
|
+
<div class="mock-caption"><span class="dot r"></span><span class="dot y"></span><span class="dot g"></span><span class="url">localhost:3456/#prompts</span></div>
|
|
380
|
+
<div class="shell-header">
|
|
381
|
+
<strong style="font-size:13px;">Prompts</strong>
|
|
382
|
+
<div class="grow"></div>
|
|
383
|
+
<div class="searchbox" style="width:240px;"><svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="11" cy="11" r="7"/><path d="M21 21l-4-4"/></svg><span>Search title & body…</span><span class="kbd">⌘K</span></div>
|
|
384
|
+
<button class="btn-accent">+ New</button>
|
|
385
|
+
</div>
|
|
386
|
+
<div class="pm-shell">
|
|
387
|
+
<div class="pm-side">
|
|
388
|
+
<div class="pm-bigsearch"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="11" cy="11" r="7"/><path d="M21 21l-4-4"/></svg><span>review</span></div>
|
|
389
|
+
<div>
|
|
390
|
+
<div class="pm-group-title">Views</div>
|
|
391
|
+
<div class="pm-quick">
|
|
392
|
+
<div class="pm-qitem"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M3 6h18M3 12h18M3 18h18"/></svg>All prompts<span class="ct">142</span></div>
|
|
393
|
+
<div class="pm-qitem active"><svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor" stroke="none"><path d="M12 2l3 7h7l-5.5 4 2 7-6.5-4.5L5.5 27l2-7L2 9h7z"/></svg>Favorites<span class="ct">9</span></div>
|
|
394
|
+
<div class="pm-qitem"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/></svg>Recent<span class="ct">20</span></div>
|
|
395
|
+
</div>
|
|
396
|
+
</div>
|
|
397
|
+
<div>
|
|
398
|
+
<div class="pm-group-title">Tags</div>
|
|
399
|
+
<div class="pm-tags">
|
|
400
|
+
<span class="tag-chip on">#review</span>
|
|
401
|
+
<span class="tag-chip">#debugging</span>
|
|
402
|
+
<span class="tag-chip">#refactor</span>
|
|
403
|
+
<span class="tag-chip">#ctm</span>
|
|
404
|
+
<span class="tag-chip">#walle</span>
|
|
405
|
+
<span class="tag-chip">#writing</span>
|
|
406
|
+
<span class="tag-chip">#perf</span>
|
|
407
|
+
</div>
|
|
408
|
+
</div>
|
|
409
|
+
</div>
|
|
410
|
+
<div class="pm-main">
|
|
411
|
+
<div class="pm-mainhead"><h4>Favorites · #review</h4><span class="count">4 matches</span></div>
|
|
412
|
+
<div class="pm-row sel">
|
|
413
|
+
<svg class="star" width="15" height="15" viewBox="0 0 24 24" fill="currentColor"><path d="M12 2l3 7h7l-5.5 4 2 7-6.5-4.5L5.5 27l2-7L2 9h7z"/></svg>
|
|
414
|
+
<div class="pbody"><div class="ptitle">Deep code <mark>review</mark> — find bugs & cleanups <span class="mini-tag">{{2 vars}}</span></div><div class="psub"><span class="mini-tag">#review</span><span class="mini-tag">#ctm</span><span class="vbadge">v7</span><span>used 23×</span></div></div>
|
|
415
|
+
<span class="when">2h ago</span>
|
|
416
|
+
</div>
|
|
417
|
+
<div class="pm-row">
|
|
418
|
+
<svg class="star" width="15" height="15" viewBox="0 0 24 24" fill="currentColor"><path d="M12 2l3 7h7l-5.5 4 2 7-6.5-4.5L5.5 27l2-7L2 9h7z"/></svg>
|
|
419
|
+
<div class="pbody"><div class="ptitle">PR <mark>review</mark> checklist</div><div class="psub"><span class="mini-tag">#review</span><span class="vbadge">v3</span><span>used 11×</span></div></div>
|
|
420
|
+
<span class="when">1d ago</span>
|
|
421
|
+
</div>
|
|
422
|
+
<div class="pm-row">
|
|
423
|
+
<svg class="star" width="15" height="15" viewBox="0 0 24 24" fill="currentColor"><path d="M12 2l3 7h7l-5.5 4 2 7-6.5-4.5L5.5 27l2-7L2 9h7z"/></svg>
|
|
424
|
+
<div class="pbody"><div class="ptitle">Security <mark>review</mark> pass — OWASP top 10 <span class="mini-tag">{{file}}</span></div><div class="psub"><span class="mini-tag">#review</span><span class="mini-tag">#perf</span><span>used 6×</span></div></div>
|
|
425
|
+
<span class="when">3d ago</span>
|
|
426
|
+
</div>
|
|
427
|
+
<div class="pm-row">
|
|
428
|
+
<svg class="star" width="15" height="15" viewBox="0 0 24 24" fill="currentColor"><path d="M12 2l3 7h7l-5.5 4 2 7-6.5-4.5L5.5 27l2-7L2 9h7z"/></svg>
|
|
429
|
+
<div class="pbody"><div class="ptitle">Self-<mark>review</mark> before commit</div><div class="psub"><span class="mini-tag">#review</span><span class="vbadge">v2</span></div></div>
|
|
430
|
+
<span class="when">5d ago</span>
|
|
431
|
+
</div>
|
|
432
|
+
</div>
|
|
433
|
+
</div>
|
|
434
|
+
</div>
|
|
435
|
+
|
|
436
|
+
<div class="priorart">
|
|
437
|
+
<svg class="pa-icn" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><path d="M12 16v-4M12 8h.01"/></svg>
|
|
438
|
+
<div><b>Prior art:</b> Raycast, Promptlight, and LangSmith all converge on <b>tags + favorites + powerful search</b> over deep folder trees — true nested folders are rare and often deliberately rejected. Google AI Studio's title-only search is the field's most-cited weakness; CTM already has FTS5 over the body, so don't repeat it.</div>
|
|
439
|
+
</div>
|
|
440
|
+
|
|
441
|
+
<h3 style="font-size:18px; margin:34px 0 4px;">Two ways to get there</h3>
|
|
442
|
+
<div class="alt-grid">
|
|
443
|
+
<div class="alt-card rec">
|
|
444
|
+
<h4>Option A — Consolidate & simplify <span class="rectag">Recommended</span></h4>
|
|
445
|
+
<div class="sub">Reduce seven axes to one clear model.</div>
|
|
446
|
+
<ul>
|
|
447
|
+
<li>Primary: <code>search</code> + <code>Favorites/Recent/All</code> + editable <code>#tags</code></li>
|
|
448
|
+
<li>Merge <b>domains → tags</b> (reuse <code>autoTagAllPrompts</code> to backfill)</li>
|
|
449
|
+
<li>Lifecycle becomes auto signal (frequent/recent), not a manual field</li>
|
|
450
|
+
<li>Fold <b>star + pin</b> into one Favorite</li>
|
|
451
|
+
<li>Folders optional/secondary for those who want them</li>
|
|
452
|
+
<li class="con">More migration + a settling period for existing data</li>
|
|
453
|
+
</ul>
|
|
454
|
+
</div>
|
|
455
|
+
<div class="alt-card">
|
|
456
|
+
<h4>Option B — Additive polish</h4>
|
|
457
|
+
<div class="sub">Keep every axis, improve the surface.</div>
|
|
458
|
+
<ul>
|
|
459
|
+
<li>Unify the scattered controls into one filter bar</li>
|
|
460
|
+
<li>Promote search; highlight body matches</li>
|
|
461
|
+
<li>Keep folders, domains, lifecycle, groups as-is</li>
|
|
462
|
+
<li>Lower risk, no data migration</li>
|
|
463
|
+
<li class="con">The underlying overlap (the real problem) remains</li>
|
|
464
|
+
</ul>
|
|
465
|
+
</div>
|
|
466
|
+
</div>
|
|
467
|
+
<p class="sec-sub" style="margin-top:18px;"><b>Recommendation:</b> Option A. The overlap <em>is</em> the complaint — polishing seven axes only makes a prettier maze. The domain→tag backfill already exists, so migration is mostly mechanical.</p>
|
|
468
|
+
</section>
|
|
469
|
+
|
|
470
|
+
<!-- ===================== EDITOR ===================== -->
|
|
471
|
+
<section id="editor">
|
|
472
|
+
<div class="sec-head"><span class="sec-num">04</span><h2>Editor — author what a prompt really is</h2></div>
|
|
473
|
+
<p class="sec-sub">
|
|
474
|
+
Phase 2 flagship. Prompts here are templated markdown sent to coding agents. The editor should treat
|
|
475
|
+
them that way: highlight markdown structure and <code>{{variables}}</code>, preview the rendered result,
|
|
476
|
+
and show a live token meter — instead of a styled rich-text box.
|
|
477
|
+
</p>
|
|
478
|
+
|
|
479
|
+
<div class="mock">
|
|
480
|
+
<div class="mock-caption"><span class="dot r"></span><span class="dot y"></span><span class="dot g"></span><span class="url">localhost:3456/#prompts → Deep code review</span></div>
|
|
481
|
+
<div class="ed-toolbar">
|
|
482
|
+
<span class="seg"><b class="on">Edit</b><b>Preview</b><b>Split</b></span>
|
|
483
|
+
<span class="tb">{{ }}</span>
|
|
484
|
+
<span class="tb">/ snippet</span>
|
|
485
|
+
<span class="tb">@ file</span>
|
|
486
|
+
<span class="token-meter">⌁ <span class="ok">412</span> / 200k tokens · 1,840 chars</span>
|
|
487
|
+
</div>
|
|
488
|
+
<div class="ed-split">
|
|
489
|
+
<div class="ed-pane left">
|
|
490
|
+
<span class="pane-tag">Markdown · source</span>
|
|
491
|
+
<div class="ln"><span class="md-h"># Deep code review</span></div>
|
|
492
|
+
<div class="ln"> </div>
|
|
493
|
+
<div class="ln">Review <span class="var-tok">{{file}}</span> on branch <span class="var-tok">{{branch}}</span> and</div>
|
|
494
|
+
<div class="ln">report bugs, then cleanups. Be specific.</div>
|
|
495
|
+
<div class="ln"> </div>
|
|
496
|
+
<div class="ln"><span class="md-h">## Context</span></div>
|
|
497
|
+
<div class="ln"><span class="md-bullet">-</span> Recent diff: <span class="ctx-tok">!`git diff HEAD~1`</span></div>
|
|
498
|
+
<div class="ln"><span class="md-bullet">-</span> Conventions: <span class="ctx-tok">@CLAUDE.md</span></div>
|
|
499
|
+
<div class="ln"><span class="md-bullet">-</span> Date: <span class="ctx-tok">{date}</span></div>
|
|
500
|
+
<div class="ln"> </div>
|
|
501
|
+
<div class="ln">Focus on <span class="md-code">`correctness`</span> first.</div>
|
|
502
|
+
</div>
|
|
503
|
+
<div class="ed-pane">
|
|
504
|
+
<span class="pane-tag">Live preview · variables filled</span>
|
|
505
|
+
<div class="prev-body">
|
|
506
|
+
<h3>Deep code review</h3>
|
|
507
|
+
<p>Review <span class="pill">server.js</span> on branch <span class="pill">prompts</span> and report bugs, then cleanups. Be specific.</p>
|
|
508
|
+
<h3 style="font-size:14px;">Context</h3>
|
|
509
|
+
<p>• Recent diff: <span style="color:var(--syn-num)">‹3 files, +88 −12›</span><br>
|
|
510
|
+
• Conventions: <span style="color:var(--syn-num)">‹CLAUDE.md, 2.1k›</span><br>
|
|
511
|
+
• Date: <span style="color:var(--syn-num)">2026-06-23</span></p>
|
|
512
|
+
<p>Focus on <code style="font-family:'SF Mono',Menlo,monospace;color:var(--syn-str)">correctness</code> first.</p>
|
|
513
|
+
</div>
|
|
514
|
+
</div>
|
|
515
|
+
</div>
|
|
516
|
+
</div>
|
|
517
|
+
|
|
518
|
+
<div class="priorart">
|
|
519
|
+
<svg class="pa-icn" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><path d="M12 16v-4M12 8h.01"/></svg>
|
|
520
|
+
<div><b>Prior art:</b> A live in-editor <b>token counter</b> is documented mainly in Google AI Studio — a genuine differentiator. The Anthropic Console "Variables window" separates template text from inputs; Claude Code's <code>!`cmd`</code> and <code>@file</code> inject live repo context. Both map directly onto what CTM prompts need.</div>
|
|
521
|
+
</div>
|
|
522
|
+
|
|
523
|
+
<h3 style="font-size:18px; margin:34px 0 4px;">Two editor directions</h3>
|
|
524
|
+
<div class="alt-grid">
|
|
525
|
+
<div class="alt-card rec">
|
|
526
|
+
<h4>Option A — Markdown / code editor <span class="rectag">Recommended</span></h4>
|
|
527
|
+
<div class="sub">CodeMirror-style, built for markdown prompts.</div>
|
|
528
|
+
<ul>
|
|
529
|
+
<li>Markdown + <code>{{variable}}</code> + <code>!`cmd`</code>/<code>@file</code> syntax highlighting</li>
|
|
530
|
+
<li>Edit / Preview / Split modes; live preview pane</li>
|
|
531
|
+
<li>Live token + character meter against the model limit</li>
|
|
532
|
+
<li><code>/</code> snippet insert (reuse the existing slash picker)</li>
|
|
533
|
+
<li>Image paste & annotation retained as an add-on layer</li>
|
|
534
|
+
<li class="con">Larger build: introduce CodeMirror; migrate HTML content → markdown</li>
|
|
535
|
+
</ul>
|
|
536
|
+
</div>
|
|
537
|
+
<div class="alt-card">
|
|
538
|
+
<h4>Option B — Enhanced WYSIWYG</h4>
|
|
539
|
+
<div class="sub">Keep <code>contenteditable</code>, add the missing bits.</div>
|
|
540
|
+
<ul>
|
|
541
|
+
<li>Render <code>{{variables}}</code> as inline chips</li>
|
|
542
|
+
<li>Add a token/char counter + a preview toggle</li>
|
|
543
|
+
<li>Slash-snippet insert; keep image annotation first-class</li>
|
|
544
|
+
<li>Lower risk; no content-format migration</li>
|
|
545
|
+
<li class="con">No real syntax highlighting; <code>execCommand</code> quirks remain</li>
|
|
546
|
+
</ul>
|
|
547
|
+
</div>
|
|
548
|
+
</div>
|
|
549
|
+
<p class="sec-sub" style="margin-top:18px;"><b>Recommendation:</b> Option A for coding prompts — markdown is the native format and highlighting/preview pay off daily. Keep B as the low-risk fallback if the markdown migration proves heavier than expected; image annotation survives either way.</p>
|
|
550
|
+
</section>
|
|
551
|
+
|
|
552
|
+
<!-- ===================== REUSE ===================== -->
|
|
553
|
+
<section id="reuse">
|
|
554
|
+
<div class="sec-head"><span class="sec-num">05</span><h2>Reuse — turn prompts into instruments</h2></div>
|
|
555
|
+
<p class="sec-sub">
|
|
556
|
+
Phase 3 flagship, and the highest-leverage win. Activate the <code>template_vars</code> already in the
|
|
557
|
+
schema: when you insert a prompt, fill its variables in a quick form, and reach any prompt from anywhere
|
|
558
|
+
with a keyboard-first command palette. Dynamic context (<code>{date}</code>, <code>{clipboard}</code>,
|
|
559
|
+
<code>!`cmd`</code>, <code>@file</code>) makes a single saved prompt adapt to the current repo.
|
|
560
|
+
</p>
|
|
561
|
+
|
|
562
|
+
<div class="mock-label">A · Fill-in form at insert time — from <code class="mono">template_vars</code></div>
|
|
563
|
+
<div class="mock">
|
|
564
|
+
<div class="mock-caption"><span class="dot r"></span><span class="dot y"></span><span class="dot g"></span><span class="url">Insert "Deep code review" → fill variables</span></div>
|
|
565
|
+
<div class="mock-stage">
|
|
566
|
+
<div class="fillform">
|
|
567
|
+
<div class="ff-head"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="var(--accent)" stroke-width="2"><path d="M4 7h16M4 12h10M4 17h7"/></svg><span class="fft">Deep code review</span><span class="ffs">2 variables</span></div>
|
|
568
|
+
<div class="ff-field">
|
|
569
|
+
<label>file <b>{{file}}</b></label>
|
|
570
|
+
<div class="ff-input focused"><span>server.js</span><span class="grow"></span><span style="width:1.5px;height:15px;background:var(--accent);"></span></div>
|
|
571
|
+
</div>
|
|
572
|
+
<div class="ff-field">
|
|
573
|
+
<label>branch <b>{{branch}}</b> · choices</label>
|
|
574
|
+
<div class="ff-input select"><span>prompts</span><svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M6 9l6 6 6-6"/></svg></div>
|
|
575
|
+
</div>
|
|
576
|
+
<div class="ff-field">
|
|
577
|
+
<label>auto-filled context</label>
|
|
578
|
+
<div class="ff-input"><span class="ph">!`git diff HEAD~1` → ‹3 files, +88 −12›</span></div>
|
|
579
|
+
</div>
|
|
580
|
+
<div class="ff-actions">
|
|
581
|
+
<div class="ff-btn ghost">Copy</div>
|
|
582
|
+
<div class="ff-btn primary">Send to session ↵</div>
|
|
583
|
+
</div>
|
|
584
|
+
</div>
|
|
585
|
+
</div>
|
|
586
|
+
</div>
|
|
587
|
+
|
|
588
|
+
<div class="mock-label" style="margin-top:26px;">B · Command-palette quick-insert — fuzzy over title + body, keyboard-only</div>
|
|
589
|
+
<div class="mock">
|
|
590
|
+
<div class="mock-caption"><span class="dot r"></span><span class="dot y"></span><span class="dot g"></span><span class="url">Press ⌘K anywhere → insert a prompt</span></div>
|
|
591
|
+
<div class="mock-stage">
|
|
592
|
+
<div class="palette">
|
|
593
|
+
<div class="pal-search"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="11" cy="11" r="7"/><path d="M21 21l-4-4"/></svg><span>rev</span><span class="cursor"></span></div>
|
|
594
|
+
<div class="pal-sec">Prompts</div>
|
|
595
|
+
<div class="pal-item sel"><svg class="pi-icn" width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M4 7h16M4 12h10M4 17h7"/></svg><span class="pi-title">Deep code <b>rev</b>iew — find bugs & cleanups</span><span class="pi-sub">2 vars · used 23×</span></div>
|
|
596
|
+
<div class="pal-item"><svg class="pi-icn" width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M4 7h16M4 12h10M4 17h7"/></svg><span class="pi-title">PR <b>rev</b>iew checklist</span><span class="pi-sub">used 11×</span></div>
|
|
597
|
+
<div class="pal-item"><svg class="pi-icn" width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M4 7h16M4 12h10M4 17h7"/></svg><span class="pi-title">Security <b>rev</b>iew pass — OWASP top 10</span><span class="pi-sub">1 var · used 6×</span></div>
|
|
598
|
+
<div class="pal-foot"><span><span class="kbd">↑</span><span class="kbd">↓</span> navigate</span><span><span class="kbd">↵</span> fill & insert</span><span><span class="kbd">⌥↵</span> insert raw</span><span><span class="kbd">esc</span> close</span></div>
|
|
599
|
+
</div>
|
|
600
|
+
</div>
|
|
601
|
+
</div>
|
|
602
|
+
|
|
603
|
+
<div class="priorart">
|
|
604
|
+
<svg class="pa-icn" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><path d="M12 16v-4M12 8h.01"/></svg>
|
|
605
|
+
<div><b>Prior art:</b> Espanso Forms (<code>type: choice</code>), VS Code tabstops (<code>${1|a,b,c|}</code>), and Copilot's <code>${input:var}</code> are the reference models for fill-in fields with defaults, choice dropdowns, and a final-cursor marker. Raycast/Promptlight set the bar for the palette. CTM already has the global-hotkey daemon (<code>bin/ctm-hotkey.swift</code>) and <code>sendToNewSession</code> plumbing to wire it up.</div>
|
|
606
|
+
</div>
|
|
607
|
+
|
|
608
|
+
<p class="sec-sub" style="margin-top:22px;">
|
|
609
|
+
<b>Beyond v1:</b> the dormant <code>chains</code> / <code>chain_nodes</code> / <code>chain_edges</code>
|
|
610
|
+
tables describe prompt workflows (a graph of prompts with conditions). Surfacing even a linear "run these
|
|
611
|
+
in sequence" view is a natural Phase 4 — the data model is already there.
|
|
612
|
+
</p>
|
|
613
|
+
</section>
|
|
614
|
+
|
|
615
|
+
<!-- ===================== ROADMAP ===================== -->
|
|
616
|
+
<section id="plan">
|
|
617
|
+
<div class="sec-head"><span class="sec-num">06</span><h2>Phased roadmap</h2></div>
|
|
618
|
+
<p class="sec-sub">One flagship per phase, ordered by leverage-per-risk. Each phase is independently shippable and reuses existing schema and endpoints — no rewrite.</p>
|
|
619
|
+
<div class="roadmap">
|
|
620
|
+
<div class="phase">
|
|
621
|
+
<div class="pn">Phase 1<small>Findability</small></div>
|
|
622
|
+
<div class="pbody"><h4>One organization model</h4><p>Consolidate the sidebar in <code>prompts.js</code>/<code>prompts.css</code>: big search + Favorites/Recent/All + tags. Backfill domains→tags via <code>autoTagAllPrompts</code>; collapse star+pin. Mostly front-end + a data migration.</p></div>
|
|
623
|
+
<span class="risk med">Med</span>
|
|
624
|
+
</div>
|
|
625
|
+
<div class="phase">
|
|
626
|
+
<div class="pn">Phase 2<small>Editor</small></div>
|
|
627
|
+
<div class="pbody"><h4>Markdown / code editor</h4><p>Introduce a CodeMirror-style editor: markdown + <code>{{var}}</code> highlighting, Edit/Preview/Split, live token meter, <code>/</code> snippets. Keep image annotation as an add-on. Migrate stored HTML → markdown.</p></div>
|
|
628
|
+
<span class="risk med">Med</span>
|
|
629
|
+
</div>
|
|
630
|
+
<div class="phase">
|
|
631
|
+
<div class="pn">Phase 3<small>Reuse</small></div>
|
|
632
|
+
<div class="pbody"><h4>Variables + quick-insert</h4><p>Fill-in form from <code>template_vars</code> (defaults, choice dropdowns, cursor marker); <code>⌘K</code> command palette over title+body wired to <code>sendToNewSession</code>; dynamic context <code>{date}</code>/<code>!`cmd`</code>/<code>@file</code>.</p></div>
|
|
633
|
+
<span class="risk low">Low</span>
|
|
634
|
+
</div>
|
|
635
|
+
<div class="phase">
|
|
636
|
+
<div class="pn">Phase 4<small>Stretch</small></div>
|
|
637
|
+
<div class="pbody"><h4>Chains & version diff</h4><p>Surface the dormant <code>chains</code> graph (start with linear sequences) and add a side-by-side version diff over <code>prompt_versions</code>. Both build on data that already exists.</p></div>
|
|
638
|
+
<span class="risk low">Low</span>
|
|
639
|
+
</div>
|
|
640
|
+
</div>
|
|
641
|
+
</section>
|
|
642
|
+
|
|
643
|
+
<footer>
|
|
644
|
+
CTM Prompt Manager redesign proposal · self-contained mock using the live app theme tokens ·
|
|
645
|
+
toggle <a href="javascript:toggleTheme()">dark / light</a> to preview both.<br>
|
|
646
|
+
What I'd build first → <b>Phase 3 (Reuse)</b> is the lowest-risk, highest-leverage win and activates schema that already exists; <b>Phase 1 (Findability)</b> removes the daily friction.
|
|
647
|
+
Build is a separate greenlit step — implemented on <a href="javascript:void(0)">/ctm-dev</a> with tests, per project rules.
|
|
648
|
+
</footer>
|
|
649
|
+
</div>
|
|
650
|
+
|
|
651
|
+
<script>
|
|
652
|
+
function toggleTheme() {
|
|
653
|
+
const html = document.documentElement;
|
|
654
|
+
const next = html.getAttribute('data-theme') === 'dark' ? 'light' : 'dark';
|
|
655
|
+
html.setAttribute('data-theme', next);
|
|
656
|
+
document.getElementById('themeLabel').textContent = next === 'dark' ? 'Dark' : 'Light';
|
|
657
|
+
}
|
|
658
|
+
// subtle staggered reveal on load
|
|
659
|
+
document.querySelectorAll('section, .hero').forEach((el, i) => {
|
|
660
|
+
el.style.opacity = '0'; el.style.transform = 'translateY(10px)';
|
|
661
|
+
el.style.transition = 'opacity .5s ease, transform .5s ease';
|
|
662
|
+
setTimeout(() => { el.style.opacity = '1'; el.style.transform = 'none'; }, 60 + i * 55);
|
|
663
|
+
});
|
|
664
|
+
</script>
|
|
665
|
+
</body>
|
|
666
|
+
</html>
|