vibe-coding-master 0.0.9 → 0.0.10
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 +33 -23
- package/dist/backend/api/app-settings-routes.js +8 -0
- package/dist/backend/api/message-routes.js +3 -1
- package/dist/backend/api/session-routes.js +7 -1
- package/dist/backend/api/task-routes.js +3 -10
- package/dist/backend/api/translation-routes.js +21 -3
- package/dist/backend/runtime/terminal-submit.js +20 -0
- package/dist/backend/server.js +8 -4
- package/dist/backend/services/app-settings-service.js +28 -0
- package/dist/backend/services/claude-transcript-service.js +12 -8
- package/dist/backend/services/command-dispatcher.js +2 -1
- package/dist/backend/services/message-service.js +10 -6
- package/dist/backend/services/project-service.js +0 -3
- package/dist/backend/services/session-service.js +7 -4
- package/dist/backend/services/task-service.js +65 -56
- package/dist/backend/services/translation-service.js +264 -77
- package/dist/shared/types/app-settings.js +1 -0
- package/dist-frontend/assets/index-B1vIIwLq.js +88 -0
- package/dist-frontend/assets/index-DPyKuEOz.css +32 -0
- package/dist-frontend/index.html +2 -2
- package/docs/cc-best-practices.md +4 -4
- package/docs/product-design.md +64 -29
- package/docs/v1-architecture-design.md +82 -48
- package/docs/v1-implementation-plan.md +73 -53
- package/package.json +3 -1
- package/dist/backend/ws/translation-ws.js +0 -35
- package/dist-frontend/assets/index-CuiNNOzj.css +0 -32
- package/dist-frontend/assets/index-D59GuHCR.js +0 -58
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2014 The xterm.js authors. All rights reserved.
|
|
3
|
+
* Copyright (c) 2012-2013, Christopher Jeffrey (MIT License)
|
|
4
|
+
* https://github.com/chjj/term.js
|
|
5
|
+
* @license MIT
|
|
6
|
+
*
|
|
7
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
8
|
+
* of this software and associated documentation files (the "Software"), to deal
|
|
9
|
+
* in the Software without restriction, including without limitation the rights
|
|
10
|
+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
11
|
+
* copies of the Software, and to permit persons to whom the Software is
|
|
12
|
+
* furnished to do so, subject to the following conditions:
|
|
13
|
+
*
|
|
14
|
+
* The above copyright notice and this permission notice shall be included in
|
|
15
|
+
* all copies or substantial portions of the Software.
|
|
16
|
+
*
|
|
17
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
18
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
19
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
20
|
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
21
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
22
|
+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
23
|
+
* THE SOFTWARE.
|
|
24
|
+
*
|
|
25
|
+
* Originally forked from (with the author's permission):
|
|
26
|
+
* Fabrice Bellard's javascript vt100 for jslinux:
|
|
27
|
+
* http://bellard.org/jslinux/
|
|
28
|
+
* Copyright (c) 2011 Fabrice Bellard
|
|
29
|
+
* The original design remains. The terminal itself
|
|
30
|
+
* has been extended to include xterm CSI codes, among
|
|
31
|
+
* other features.
|
|
32
|
+
*/.xterm{cursor:text;position:relative;user-select:none;-ms-user-select:none;-webkit-user-select:none}.xterm.focus,.xterm:focus{outline:none}.xterm .xterm-helpers{position:absolute;top:0;z-index:5}.xterm .xterm-helper-textarea{padding:0;border:0;margin:0;position:absolute;opacity:0;left:-9999em;top:0;width:0;height:0;z-index:-5;white-space:nowrap;overflow:hidden;resize:none}.xterm .composition-view{background:#000;color:#fff;display:none;position:absolute;white-space:nowrap;z-index:1}.xterm .composition-view.active{display:block}.xterm .xterm-viewport{background-color:#000;overflow-y:scroll;cursor:default;position:absolute;right:0;left:0;top:0;bottom:0}.xterm .xterm-screen{position:relative}.xterm .xterm-screen canvas{position:absolute;left:0;top:0}.xterm .xterm-scroll-area{visibility:hidden}.xterm-char-measure-element{display:inline-block;visibility:hidden;position:absolute;top:0;left:-9999em;line-height:normal}.xterm.enable-mouse-events{cursor:default}.xterm.xterm-cursor-pointer,.xterm .xterm-cursor-pointer{cursor:pointer}.xterm.column-select.focus{cursor:crosshair}.xterm .xterm-accessibility:not(.debug),.xterm .xterm-message{position:absolute;left:0;top:0;bottom:0;right:0;z-index:10;color:transparent;pointer-events:none}.xterm .xterm-accessibility-tree:not(.debug) *::selection{color:transparent}.xterm .xterm-accessibility-tree{-webkit-user-select:text;user-select:text;white-space:pre}.xterm .live-region{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}.xterm-dim{opacity:1!important}.xterm-underline-1{text-decoration:underline}.xterm-underline-2{text-decoration:double underline}.xterm-underline-3{text-decoration:wavy underline}.xterm-underline-4{text-decoration:dotted underline}.xterm-underline-5{text-decoration:dashed underline}.xterm-overline{text-decoration:overline}.xterm-overline.xterm-underline-1{text-decoration:overline underline}.xterm-overline.xterm-underline-2{text-decoration:overline double underline}.xterm-overline.xterm-underline-3{text-decoration:overline wavy underline}.xterm-overline.xterm-underline-4{text-decoration:overline dotted underline}.xterm-overline.xterm-underline-5{text-decoration:overline dashed underline}.xterm-strikethrough{text-decoration:line-through}.xterm-screen .xterm-decoration-container .xterm-decoration{z-index:6;position:absolute}.xterm-screen .xterm-decoration-container .xterm-decoration.xterm-decoration-top-layer{z-index:7}.xterm-decoration-overview-ruler{z-index:8;position:absolute;top:0;right:0;pointer-events:none}.xterm-decoration-top{z-index:2;position:relative}:root{color-scheme:light;font-family:Inter,ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif;background:#f5f2ea;color:#1c2024;line-height:1.5}html,body,#root{height:100%}*{box-sizing:border-box}body{margin:0;min-width:320px;min-height:100vh;background:#f5f2ea}button,input,select,textarea{font:inherit}button{border:1px solid #9ba6ad;background:#f8f7f2;color:#1d252b;border-radius:6px;min-height:34px;padding:6px 10px;cursor:pointer}button:hover:not(:disabled){background:#eef4f2;border-color:#607d74}button:disabled{cursor:not-allowed;opacity:.55}.danger-button{border-color:#b84a45;background:#fff1ee;color:#8d211d;font-weight:750}.danger-button:hover:not(:disabled){border-color:#8d211d;background:#ffe2dc}input,select,textarea:not(.xterm-helper-textarea){width:100%;border:1px solid #b9b0a1;border-radius:6px;background:#fffdf8;color:#202326;padding:8px 10px}textarea:not(.xterm-helper-textarea){min-height:240px;resize:vertical;font-family:Menlo,Monaco,Consolas,monospace;font-size:12px}h1,h2,p{margin-top:0}h1{margin-bottom:4px;font-size:26px;line-height:1.15}h2{margin-bottom:10px;font-size:14px;letter-spacing:0}.app-shell{display:grid;grid-template-columns:minmax(280px,320px) minmax(0,1fr);height:100vh;min-height:0;overflow:hidden}.app-shell.is-sidebar-collapsed{grid-template-columns:46px minmax(0,1fr)}.app-sidebar{position:relative;min-width:0;border-right:1px solid #d3c9b8;background:#fbfaf6;padding:14px;overflow:auto}.app-shell.is-sidebar-collapsed .app-sidebar{overflow:hidden;padding:8px}.sidebar-toggle{position:absolute;top:10px;right:10px;z-index:2;display:grid;place-items:center;width:28px;min-height:28px;padding:0;background:#fffdf8}.sidebar-toggle:before{width:8px;height:8px;border-color:currentColor;border-style:solid;border-width:0 2px 2px 0;content:"";transform:translate(2px) rotate(135deg)}.app-shell.is-sidebar-collapsed .sidebar-toggle{left:9px;right:auto}.app-shell.is-sidebar-collapsed .sidebar-toggle:before{transform:translate(-2px) rotate(-45deg)}.sidebar-content{min-width:0}.app-shell.is-sidebar-collapsed .sidebar-content{width:0;opacity:0;pointer-events:none}.app-main{min-width:0;height:100%;padding:14px 16px;overflow:auto}.brand-header{display:flex;gap:12px;align-items:baseline;margin-bottom:10px;padding-right:34px}.brand-header strong{font-size:18px}.brand-header span,.muted,.workspace-branch,.workspace-worktree{color:#667071;font-size:13px}.sidebar-section{margin-bottom:8px;border:1px solid #e0d6c7;border-radius:8px;background:#fffdfa;overflow:hidden}.sidebar-section-toggle{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:8px;align-items:center;width:100%;min-height:34px;border:0;border-radius:0;background:transparent;color:#1c2024;font-size:13px;font-weight:750;text-align:left}.sidebar-section-toggle:hover{background:#f5f1e8}.sidebar-section-toggle[aria-expanded=true]{border-bottom:1px solid #ece5d9}.sidebar-section-chevron{width:8px;height:8px;border-color:currentColor;border-style:solid;border-width:0 2px 2px 0;transform:rotate(45deg)}.sidebar-section-toggle[aria-expanded=true] .sidebar-section-chevron{transform:rotate(-135deg)}.sidebar-section-content{padding:8px}.repo-connect,.project-summary,.harness-panel,.task-create{margin:0}.inline-form{display:grid;grid-template-columns:minmax(0,1fr);gap:8px}.inline-form.has-recent-paths{grid-template-columns:minmax(0,1fr) auto}.inline-form>input{grid-column:1 / -1}.inline-form>button{justify-self:end}.inline-form.has-recent-paths>button{justify-self:auto}.repo-recent-select{min-width:0;max-width:none}.project-summary dl{display:grid;gap:8px;margin:0}.project-summary div{min-width:0}.project-summary dt{color:#6c6255;font-size:12px}.project-summary dd{margin:0;overflow-wrap:anywhere;font-size:13px}.warnings,.error-banner{border:1px solid #c87b54;background:#fff4ed;color:#6f3218;border-radius:6px;padding:10px 12px}.warnings{margin:12px 0 0;padding-left:26px;font-size:13px}.harness-panel{display:grid;gap:8px}.harness-panel-header{display:flex;justify-content:space-between;gap:8px;align-items:center}.harness-panel-header h2,.harness-panel-header p,.harness-result p{margin-bottom:0}.harness-actions{display:flex;flex-wrap:wrap;gap:6px;justify-content:flex-end}.harness-file-list{display:grid;gap:6px;margin:0;padding:0;list-style:none}.harness-file-list li{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:8px;align-items:center;border:1px solid #ece5d9;border-radius:6px;padding:6px 8px;background:#fffdfa}.harness-file-list span{overflow:hidden;font-size:12px;font-weight:650;text-overflow:ellipsis;white-space:nowrap}.harness-changes,.harness-result{border:1px solid #e0d6c7;border-radius:6px;padding:8px;background:#f8f7f2;font-size:12px}.harness-changes h3{margin:0 0 4px;font-size:12px}.harness-changes ul,.harness-result ul{margin:0;padding-left:18px}.task-create form{display:grid;gap:8px}.task-create-preview{display:grid;gap:2px;border:1px solid #e0d6c7;border-radius:6px;background:#f8f7f2;padding:6px 8px}.task-create-option{display:flex;align-items:center;gap:8px;color:#1f242b;font-size:13px;font-weight:700}.task-create-option input{width:16px;height:16px;margin:0}.task-create-preview span{color:#255f3d;font-size:12px;font-weight:700}.task-create-preview small{overflow:hidden;color:#687273;font-size:11px;text-overflow:ellipsis;white-space:nowrap}.task-nav{display:grid;gap:8px}.task-nav-item{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:8px;align-items:center;text-align:left}.task-nav-item.is-active,.role-tab.is-active{border-color:#2f6f73;background:#e8f1ef}.sidebar-settings{display:grid;gap:8px}.sidebar-settings button{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:8px;align-items:center;width:100%;text-align:left}.sidebar-settings .settings-toggle.is-active{border-color:#2f6f73;background:#e8f1ef}.sidebar-settings .theme-mode-toggle span:last-child{font-weight:750}.workspace-header{display:grid;grid-template-columns:minmax(180px,auto) minmax(420px,1fr) auto auto;gap:16px;align-items:center;margin-bottom:6px}.workspace-title-line{display:flex;flex-wrap:wrap;gap:10px;align-items:baseline;min-width:0}.workspace-title-line h1{margin-bottom:0;font-size:18px;line-height:1.15}.workspace-branch{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.workspace-worktree{max-width:260px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.eyebrow{color:#7a5c2f;font-size:12px;font-weight:700;text-transform:uppercase}.role-tabs{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:6px;margin-bottom:8px;min-width:0}.workspace-header .role-tabs{margin-bottom:0}.role-tab{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:6px;align-items:center;min-height:30px;padding:4px 8px;text-align:left}.workflow-panel{display:grid;gap:8px;margin:0}.workflow-summary p{margin-bottom:0}.workflow-summary p{color:#4f5558;font-size:13px}.workflow-steps{display:grid;grid-template-columns:minmax(0,1fr);gap:6px;margin:0;padding:0;list-style:none}.workflow-steps li{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:6px;align-items:center;min-height:28px;border:1px solid #ece5d9;border-radius:6px;padding:4px 6px;background:#fffdfa}.workflow-steps li.is-current{border-color:#2f6f73;background:#e8f1ef}.workflow-steps span{overflow:hidden;color:#394246;font-size:12px;font-weight:650;text-overflow:ellipsis;white-space:nowrap}.workspace-grid{display:grid;grid-template-columns:minmax(0,1fr);flex:1;gap:10px;align-items:stretch;min-height:0}.workspace-main{min-width:0;min-height:0;display:flex;flex-direction:column;gap:8px}.role-console-stack{min-width:0;min-height:0;flex:1;display:flex;flex-direction:column}.role-console-panel{min-width:0;min-height:0;flex:1;display:none}.role-console-panel.is-active{display:flex;flex-direction:column}.session-console,.message-panel,.event-log,.empty-workspace{border:1px solid #d6d0c6;border-radius:8px;background:#fffdf8;padding:10px}.task-workspace{display:flex;flex-direction:column;gap:8px;height:100%;min-height:0}.session-console{display:grid;grid-template-rows:auto minmax(0,1fr);gap:8px;flex:1;height:100%;min-height:0}.session-console-top{display:flex;gap:10px;align-items:center;justify-content:space-between}.session-controls{display:flex;flex-wrap:wrap;gap:8px;align-items:center;justify-content:space-between;margin:0 0 8px}.permission-mode-field{display:grid;grid-template-columns:auto minmax(180px,260px);gap:8px;align-items:center;width:fit-content;max-width:100%}.permission-mode-field span{color:#5f6a6c;font-size:13px;font-weight:650}.permission-mode-field small{display:block;color:#7b8587;font-size:11px;font-weight:500;line-height:1.2}.permission-mode-field select{width:100%;min-height:30px;border:1px solid #b9b0a1;border-radius:6px;background:#fffdf8;color:#202326;padding:4px 8px}.session-toolbar{display:flex;flex-wrap:wrap;gap:6px;justify-content:flex-end}.session-toolbar button{min-height:30px;padding:4px 9px}.translation-toggle{display:inline-flex;align-items:center;justify-content:center;min-height:28px;border:1px solid #b5bec4;border-radius:6px;background:#fffefa;color:#4f5558;font-size:12px;font-weight:650;padding:3px 10px;white-space:nowrap}.translation-toggle.is-active{border-color:#2f7e84;background:#e8f4f2;color:#145e64}.translation-settings-grid input[type=checkbox]{width:auto}.session-console-body{display:grid;grid-template-columns:minmax(0,1fr);min-width:0;min-height:0;height:100%}.session-console-body.has-translation{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:10px;align-items:stretch}.terminal-pane,.translation-pane{display:grid;min-width:0;min-height:0;height:100%}.terminal-frame,.terminal-empty{width:100%;height:100%;min-height:0;border-radius:6px;overflow:hidden;background:#111316}.terminal-empty{display:grid;place-items:center;align-content:center;gap:8px;color:#d6d0c6;border:1px solid #292d31}.translation-panel{display:grid;grid-template-rows:auto minmax(0,1fr) auto;gap:8px;height:100%;min-height:0;border:1px solid #292d31;border-radius:6px;background:#0d1117;color:#d6deeb;padding:8px;min-width:0;width:100%;overflow:hidden;font-family:Menlo,Monaco,Consolas,monospace}.translation-panel-header{display:grid;gap:3px}.translation-panel-titlebar,.translation-panel-actions,.translation-status-row{display:flex;flex-wrap:wrap;gap:6px;align-items:center;justify-content:space-between}.translation-panel-header h2,.translation-panel-header p{margin-bottom:0}.translation-panel-titlebar h2{font-size:16px}.translation-panel-header p,.translation-composer span{color:#8b949e;font-size:12px}.translation-panel-actions button{border-color:#3a4149;background:#161b22;color:#d6deeb;min-height:26px;padding:2px 8px;font-size:12px}.translation-panel-actions button:hover:not(:disabled),.translation-composer-actions button:hover:not(:disabled){border-color:#58a6ff;background:#1f2937}.translation-panel-actions .auto-send-toggle.is-active{border-color:#56d364;background:#12261a;color:#d6deeb}.translation-panel-actions{justify-content:flex-end}.translation-status-row{flex-wrap:nowrap}.translation-status-row p:last-child{flex:0 0 auto;text-align:right}.translation-entry-list{display:grid;align-content:start;gap:8px;min-height:0;min-width:0;overflow-x:hidden;overflow-y:auto;scrollbar-color:#4b5563 #0d1117}.translation-entry{border:0;border-radius:0;background:transparent;min-width:0;max-width:100%;padding:0}.translation-entry pre{box-sizing:border-box;margin:0;max-height:none;max-width:100%;min-width:0;overflow:visible;white-space:pre-wrap;overflow-wrap:anywhere;font-family:Menlo,Monaco,Consolas,monospace;font-size:12px;line-height:1.45;color:#d6deeb}.translation-markdown{max-width:100%;min-width:0;color:#d6deeb;font-size:12px;line-height:1.55;overflow-wrap:anywhere}.translation-markdown>:first-child{margin-top:0}.translation-markdown>:last-child{margin-bottom:0}.translation-markdown p,.translation-markdown ul,.translation-markdown ol,.translation-markdown blockquote,.translation-markdown pre,.translation-markdown table{margin:0 0 8px}.translation-markdown h1,.translation-markdown h2,.translation-markdown h3,.translation-markdown h4,.translation-markdown h5,.translation-markdown h6{margin:10px 0 6px;color:#f0f6fc;font-weight:700;line-height:1.25}.translation-markdown h1{font-size:17px}.translation-markdown h2{font-size:15px}.translation-markdown h3,.translation-markdown h4,.translation-markdown h5,.translation-markdown h6{font-size:13px}.translation-markdown ul,.translation-markdown ol{padding-left:22px}.translation-markdown li{margin:2px 0}.translation-markdown .task-list-item{list-style:none}.translation-markdown input[type=checkbox]{width:13px;height:13px;margin:0 6px 0 0;accent-color:#56d364}.translation-markdown blockquote{border-left:3px solid #3a4149;color:#b7c0ca;padding-left:10px}.translation-markdown a{color:#79c0ff}.translation-markdown code{border-radius:4px;background:#161b22;color:#f0f6fc;padding:1px 4px;font-family:Menlo,Monaco,Consolas,monospace;font-size:.95em}.translation-markdown pre{overflow-x:auto;border:1px solid #292d31;border-radius:6px;background:#111316;padding:8px;white-space:pre}.translation-markdown pre code{background:transparent;padding:0}.translation-markdown table{display:block;max-width:100%;overflow-x:auto;border-collapse:collapse}.translation-markdown img{max-width:100%;border-radius:4px}.translation-markdown th,.translation-markdown td{border:1px solid #30363d;padding:4px 6px;text-align:left;vertical-align:top}.translation-markdown hr{border:0;border-top:1px solid #292d31;margin:10px 0}.translation-entry.is-tool-output pre{display:block;overflow:hidden;color:#7d8590;text-overflow:ellipsis;white-space:nowrap;width:100%}.translation-entry-note{margin:2px 0 0;color:#6e7681;font-size:10px;line-height:1.35}.translation-entry-note.is-error{color:#a3715f}.translation-composer{display:grid;gap:6px;border-top:1px solid #292d31;padding-top:8px}.translation-composer-row{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:8px;align-items:stretch}.translation-composer textarea{width:100%;min-height:38px;max-height:88px;border-color:#3a4149;background:#0d1117;color:#d6deeb;font-family:inherit;font-size:12px;line-height:1.35;resize:vertical}.translation-composer textarea::placeholder{color:#7d8590}.translation-composer textarea::selection{background:#8b949e59;color:#fff}.translation-composer textarea:focus,.translation-composer textarea:focus-visible{border-color:#4b5563;outline:none;box-shadow:none}.translation-composer-actions{display:grid;align-content:start;gap:6px;min-width:104px}.translation-composer-actions button{border-color:#3a4149;background:#161b22;color:#d6deeb;width:100%;min-height:38px;padding:4px 9px;font-size:12px}.translation-panel .muted{color:#8b949e}.translation-panel .error-banner{border-color:#da7b72;background:#2d1518;color:#ffdcd7}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:20;display:grid;place-items:center;background:#181c1f61;padding:18px}.translation-settings-modal{display:grid;gap:12px;width:min(980px,100%);max-height:min(760px,92vh);overflow:auto;border:1px solid #d6d0c6;border-radius:8px;background:#fffdf8;padding:14px}.message-modal,.event-modal{display:grid;grid-template-rows:auto minmax(0,1fr);gap:12px;width:min(980px,100%);max-height:min(760px,92vh);overflow:hidden;border:1px solid #d6d0c6;border-radius:8px;background:#fffdf8;padding:14px}.translation-settings-modal header,.message-modal header,.event-modal header,.translation-settings-modal footer{display:flex;gap:8px;align-items:center;justify-content:space-between}.translation-prompt-settings{display:grid;gap:10px;border-top:1px solid #ece5d9;padding-top:12px}.translation-prompt-settings header{display:flex;gap:10px;align-items:end;justify-content:space-between}.translation-prompt-settings h3,.translation-prompt-settings p{margin-bottom:0}.translation-prompt-settings h3{font-size:13px}.translation-prompt-settings textarea{min-height:120px;max-height:260px;font-family:Menlo,Monaco,Consolas,monospace;font-size:12px}.translation-prompt-stack{display:grid;gap:10px}.translation-prompt-stack label{display:grid;gap:4px}.translation-prompt-stack span{color:#4f5558;font-size:12px;font-weight:650}.translation-settings-modal h2,.message-modal h2,.message-modal p,.event-modal h2,.event-modal p,.translation-settings-modal p{margin-bottom:0}.translation-settings-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px}.translation-settings-grid label{display:grid;gap:4px}.translation-settings-grid span{color:#4f5558;font-size:12px;font-weight:650}.translation-settings-grid select,.translation-prompt-settings select{min-height:34px;border:1px solid #b9b0a1;border-radius:6px;background:#fffdf8;color:#202326;padding:6px 10px}.translation-test-result{border-radius:6px;padding:8px;font-size:13px}.translation-test-result.is-ok{border:1px solid #6ea77e;background:#e6f3e9;color:#245334}.translation-test-result.is-error{border:1px solid #c46e5f;background:#fae9e6;color:#6f2b21}.message-panel{display:grid;gap:8px}.message-modal .message-panel,.event-modal .event-log{min-height:0;overflow:auto;border:0;background:transparent;padding:0}.message-panel-header{display:flex;justify-content:space-between;gap:12px;align-items:center}.message-panel-header h2,.message-panel-header p{margin-bottom:0}.message-controls,.message-mode-toggle,.message-actions{display:flex;flex-wrap:wrap;gap:8px;align-items:center}.message-mode-toggle{color:#4f5558;font-size:13px;font-weight:650}.message-mode-toggle input{width:auto}.message-list{display:grid;gap:8px;margin:0;padding:0;list-style:none}.message-item{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:10px;align-items:start;border:1px solid #ece5d9;border-radius:6px;padding:8px;background:#fffdfa}.message-meta{display:flex;flex-wrap:wrap;gap:8px;align-items:center;margin-bottom:4px}.message-meta time,.message-meta span:not(.status-badge),.message-path{color:#667071;font-size:12px}.message-sequence{min-width:32px;color:#1f242b;font-weight:800}.message-actions button{min-height:30px;padding:4px 10px}.message-item p{display:-webkit-box;margin-bottom:4px;overflow:hidden;-webkit-box-orient:vertical;-webkit-line-clamp:2}.message-path{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.event-log ol{margin:0;padding-left:22px;font-size:13px}.event-log{max-height:92px;overflow:auto}.event-log h2{margin-bottom:4px;font-size:13px}.event-log p{margin-bottom:0}.event-log li{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.status-badge{display:inline-flex;align-items:center;justify-content:center;min-width:66px;min-height:20px;border-radius:999px;padding:2px 8px;border:1px solid #c7c1b8;background:#f2eee7;color:#4f5558;font-size:11px;white-space:nowrap}.status-running,.status-ok{border-color:#6ea77e;background:#e6f3e9;color:#245334}.status-blocked,.status-crashed,.status-missing,.status-empty{border-color:#c46e5f;background:#fae9e6;color:#6f2b21}.status-waiting,.status-starting,.status-incomplete{border-color:#c4a34e;background:#f7efcf;color:#604e16}.status-exited,.status-done,.status-resumable,.status-staged,.status-delivered,.status-acknowledged{border-color:#7b98b8;background:#e9f0f8;color:#2e4e70}.status-pending_approval,.status-queued,.status-translating,.status-ready,.status-create,.status-insert,.status-update{border-color:#c4a34e;background:#f7efcf;color:#604e16}.status-rejected,.status-failed,.status-cancelled,.status-blocked{border-color:#c46e5f;background:#fae9e6;color:#6f2b21}.status-pending{border-color:#c7c1b8;background:#f2eee7;color:#4f5558}.status-translated,.status-preserved{border-color:#7b98b8;background:#e9f0f8;color:#2e4e70}.empty-workspace{max-width:680px}@media(max-width:980px){.app-shell,.workspace-grid{grid-template-columns:1fr}.app-sidebar{border-right:0;border-bottom:1px solid #d3c9b8}.role-tabs{grid-template-columns:repeat(2,minmax(0,1fr))}.workflow-panel,.workflow-steps,.session-console-body.has-translation,.translation-settings-grid{grid-template-columns:1fr}}@media(max-width:560px){.app-main,.app-sidebar{padding:12px}.workspace-header,.inline-form,.inline-form.has-recent-paths{grid-template-columns:1fr;display:grid}.role-tabs{grid-template-columns:1fr}.terminal-frame,.terminal-empty{min-height:300px;height:54vh}.permission-mode-field{grid-template-columns:1fr;width:100%}}:root[data-theme=dark]{color-scheme:dark;background:#0d1117;color:#e6edf3}:root[data-theme=dark] body,:root[data-theme=dark] .app-main{background:#0d1117;color:#e6edf3}:root[data-theme=dark] button{border-color:#3d4652;background:#161b22;color:#e6edf3}:root[data-theme=dark] button:hover:not(:disabled){border-color:#58a6ff;background:#1f2937}:root[data-theme=dark] input,:root[data-theme=dark] select,:root[data-theme=dark] textarea:not(.xterm-helper-textarea){border-color:#3d4652;background:#0d1117;color:#e6edf3}:root[data-theme=dark] input::placeholder,:root[data-theme=dark] textarea::placeholder{color:#7d8590}:root[data-theme=dark] .danger-button{border-color:#da7b72;background:#2d1518;color:#ffdcd7}:root[data-theme=dark] .danger-button:hover:not(:disabled){border-color:#ffa198;background:#3d1f23}:root[data-theme=dark] .app-sidebar{border-color:#30363d;background:#0f141b}:root[data-theme=dark] .sidebar-toggle{background:#161b22}:root[data-theme=dark] .brand-header span,:root[data-theme=dark] .muted,:root[data-theme=dark] .workspace-branch,:root[data-theme=dark] .workspace-worktree,:root[data-theme=dark] .message-meta time,:root[data-theme=dark] .message-meta span:not(.status-badge),:root[data-theme=dark] .message-path{color:#8b949e}:root[data-theme=dark] .sidebar-section,:root[data-theme=dark] .session-console,:root[data-theme=dark] .message-panel,:root[data-theme=dark] .event-log,:root[data-theme=dark] .empty-workspace,:root[data-theme=dark] .translation-settings-modal,:root[data-theme=dark] .message-modal,:root[data-theme=dark] .event-modal{border-color:#30363d;background:#11161d}:root[data-theme=dark] .sidebar-section-toggle{color:#e6edf3}:root[data-theme=dark] .sidebar-section-toggle:hover{background:#161b22}:root[data-theme=dark] .sidebar-section-toggle[aria-expanded=true],:root[data-theme=dark] .translation-prompt-settings{border-color:#30363d}:root[data-theme=dark] .project-summary dt,:root[data-theme=dark] .permission-mode-field span,:root[data-theme=dark] .translation-settings-grid span,:root[data-theme=dark] .translation-prompt-stack span,:root[data-theme=dark] .message-mode-toggle,:root[data-theme=dark] .workflow-summary p{color:#b7c0ca}:root[data-theme=dark] .permission-mode-field small,:root[data-theme=dark] .task-create-preview small{color:#8b949e}:root[data-theme=dark] .warnings,:root[data-theme=dark] .error-banner{border-color:#da7b72;background:#2d1518;color:#ffdcd7}:root[data-theme=dark] .harness-file-list li,:root[data-theme=dark] .harness-changes,:root[data-theme=dark] .harness-result,:root[data-theme=dark] .task-create-preview,:root[data-theme=dark] .workflow-steps li,:root[data-theme=dark] .message-item{border-color:#30363d;background:#0d1117}:root[data-theme=dark] .task-create-option{color:#e6edf3}:root[data-theme=dark] .task-create-preview span{color:#7ee787}:root[data-theme=dark] .workflow-steps span{color:#d6deeb}:root[data-theme=dark] .message-sequence{color:#f0f6fc}:root[data-theme=dark] .eyebrow{color:#d29922}:root[data-theme=dark] .task-nav-item.is-active,:root[data-theme=dark] .role-tab.is-active,:root[data-theme=dark] .workflow-steps li.is-current,:root[data-theme=dark] .sidebar-settings .settings-toggle.is-active,:root[data-theme=dark] .translation-toggle.is-active{border-color:#56d4dd;background:#10262b;color:#d6fbff}:root[data-theme=dark] .translation-toggle{border-color:#3d4652;background:#161b22;color:#b7c0ca}:root[data-theme=dark] .permission-mode-field select,:root[data-theme=dark] .translation-settings-grid select,:root[data-theme=dark] .translation-prompt-settings select{border-color:#3d4652;background:#0d1117;color:#e6edf3}:root[data-theme=dark] .terminal-empty{border-color:#30363d}:root[data-theme=dark] .modal-backdrop{background:#010409b8}:root[data-theme=dark] .message-modal .message-panel,:root[data-theme=dark] .event-modal .event-log{background:transparent}:root[data-theme=dark] .status-badge{border-color:#3d4652;background:#161b22;color:#d6deeb}:root[data-theme=dark] .translation-test-result.is-ok,:root[data-theme=dark] .status-running,:root[data-theme=dark] .status-ok{border-color:#3fb950;background:#12261a;color:#aff5b4}:root[data-theme=dark] .translation-test-result.is-error,:root[data-theme=dark] .status-blocked,:root[data-theme=dark] .status-crashed,:root[data-theme=dark] .status-missing,:root[data-theme=dark] .status-empty,:root[data-theme=dark] .status-rejected,:root[data-theme=dark] .status-failed,:root[data-theme=dark] .status-cancelled{border-color:#f85149;background:#2d1518;color:#ffdcd7}:root[data-theme=dark] .status-waiting,:root[data-theme=dark] .status-starting,:root[data-theme=dark] .status-incomplete,:root[data-theme=dark] .status-pending_approval,:root[data-theme=dark] .status-queued,:root[data-theme=dark] .status-translating,:root[data-theme=dark] .status-ready,:root[data-theme=dark] .status-create,:root[data-theme=dark] .status-insert,:root[data-theme=dark] .status-update{border-color:#d29922;background:#2d2208;color:#f8e3a1}:root[data-theme=dark] .status-exited,:root[data-theme=dark] .status-done,:root[data-theme=dark] .status-resumable,:root[data-theme=dark] .status-staged,:root[data-theme=dark] .status-delivered,:root[data-theme=dark] .status-acknowledged,:root[data-theme=dark] .status-translated,:root[data-theme=dark] .status-preserved{border-color:#388bfd;background:#10223a;color:#c9e2ff}:root[data-theme=dark] .status-pending{border-color:#3d4652;background:#161b22;color:#d6deeb}
|
package/dist-frontend/index.html
CHANGED
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
<meta charset="UTF-8" />
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
6
|
<title>VibeCodingMaster</title>
|
|
7
|
-
<script type="module" crossorigin src="/assets/index-
|
|
8
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
7
|
+
<script type="module" crossorigin src="/assets/index-B1vIIwLq.js"></script>
|
|
8
|
+
<link rel="stylesheet" crossorigin href="/assets/index-DPyKuEOz.css">
|
|
9
9
|
</head>
|
|
10
10
|
<body>
|
|
11
11
|
<div id="root"></div>
|
|
@@ -1486,11 +1486,11 @@ Branch rules:
|
|
|
1486
1486
|
- large work should use phase commits on the same task branch unless phases are independently releasable
|
|
1487
1487
|
- if a task becomes too large, split it into child tasks with explicit branch and PR ownership
|
|
1488
1488
|
|
|
1489
|
-
|
|
1489
|
+
Close Task rules:
|
|
1490
1490
|
|
|
1491
|
-
- after task completion,
|
|
1492
|
-
-
|
|
1493
|
-
-
|
|
1491
|
+
- after task completion, use VCM `Close Task` only when the user is ready to delete task-local state
|
|
1492
|
+
- for worktree-backed tasks, `Close Task` deletes the task worktree, deletes the task branch by default, and removes VCM task/session/message/orchestration metadata
|
|
1493
|
+
- `Close Task` does not check running role sessions or uncommitted changes; finish, commit, or preserve anything important before using it
|
|
1494
1494
|
|
|
1495
1495
|
Small commits:
|
|
1496
1496
|
|
package/docs/product-design.md
CHANGED
|
@@ -66,7 +66,7 @@ The workflow is a soft guide in V1. VCM computes readiness from handoff artifact
|
|
|
66
66
|
|
|
67
67
|
### 4.1 Task Worktree Model
|
|
68
68
|
|
|
69
|
-
Task-level worktree management is the
|
|
69
|
+
Task-level worktree management is the recommended default model for multi-task parallelism:
|
|
70
70
|
|
|
71
71
|
```text
|
|
72
72
|
one task
|
|
@@ -78,7 +78,9 @@ one task
|
|
|
78
78
|
|
|
79
79
|
VCM must not create worktrees per role. `project-manager`, `architect`, `coder`, and `reviewer` for the same task all run in the same task worktree and hand off sequentially.
|
|
80
80
|
|
|
81
|
-
When the user creates a task, VCM creates the branch and worktree immediately.
|
|
81
|
+
When the user creates a task, `Create worktree and branch` is selected by default. With that option selected, VCM creates the branch and worktree immediately. If the user clears the option, VCM creates the task in the currently connected repository path and records the current branch.
|
|
82
|
+
|
|
83
|
+
There is no separate later button named `Create task worktree`, and a task cannot be switched between worktree and non-worktree mode after creation.
|
|
82
84
|
|
|
83
85
|
Branch naming:
|
|
84
86
|
|
|
@@ -108,27 +110,33 @@ Task creation flow:
|
|
|
108
110
|
```text
|
|
109
111
|
New Task submit
|
|
110
112
|
-> validate task name
|
|
111
|
-
->
|
|
112
|
-
->
|
|
113
|
-
|
|
114
|
-
|
|
113
|
+
-> verify .ai/vcm/ is ignored
|
|
114
|
+
-> if Create worktree and branch is selected:
|
|
115
|
+
-> derive branch feature/<task-name>
|
|
116
|
+
-> derive worktree path .ai/vcm/worktrees/<task-name>
|
|
117
|
+
-> verify the base repo is clean
|
|
118
|
+
-> git worktree add -b feature/<task-name> .ai/vcm/worktrees/<task-name> <base-ref>
|
|
119
|
+
-> otherwise:
|
|
120
|
+
-> use the connected repo path and current branch
|
|
115
121
|
-> create task metadata
|
|
116
|
-
-> create handoff structure inside the task
|
|
117
|
-
-> open the task workspace with role session cwd = task
|
|
122
|
+
-> create handoff structure inside the task runtime repo
|
|
123
|
+
-> open the task workspace with role session cwd = task runtime repo
|
|
118
124
|
```
|
|
119
125
|
|
|
120
|
-
Task
|
|
126
|
+
Task close flow:
|
|
121
127
|
|
|
122
128
|
```text
|
|
123
|
-
|
|
124
|
-
->
|
|
125
|
-
->
|
|
126
|
-
->
|
|
127
|
-
-> remove
|
|
128
|
-
->
|
|
129
|
+
user clicks red Close Task
|
|
130
|
+
-> show destructive confirmation
|
|
131
|
+
-> explain that VCM deletes the task worktree and task branch
|
|
132
|
+
-> explain that VCM does not check running sessions or uncommitted changes
|
|
133
|
+
-> remove git worktree when the task owns one
|
|
134
|
+
-> delete the task branch by default when the task owns one
|
|
135
|
+
-> remove VCM task metadata from the base repo
|
|
136
|
+
-> remove task runtime metadata from the task runtime repo
|
|
129
137
|
```
|
|
130
138
|
|
|
131
|
-
|
|
139
|
+
Tasks created without a worktree do not own a separate branch/worktree, so Close Task removes only VCM metadata for those tasks.
|
|
132
140
|
|
|
133
141
|
## 5. Roles
|
|
134
142
|
|
|
@@ -242,10 +250,13 @@ The old `Dirty: yes/no` label is not used. The UI uses `Working tree: clean` or
|
|
|
242
250
|
|
|
243
251
|
`Settings` contains:
|
|
244
252
|
|
|
253
|
+
- `Theme` button, cycling through `System`, `Light`, and `Dark`.
|
|
245
254
|
- `Messages` button, opening a modal list of role messages.
|
|
246
255
|
- `Events` button, opening a modal list of runtime UI events for the current task.
|
|
247
256
|
- `Auto orchestration` on/off toggle.
|
|
248
257
|
|
|
258
|
+
The default theme mode is `System`, which follows the OS/browser color-scheme preference. The entire application chrome, sidebar, forms, modals, status badges, and workspace panels must support both light and dark rendering. Embedded terminals keep their terminal-native dark styling.
|
|
259
|
+
|
|
249
260
|
There is no separate `Pause orchestration` or `Resume orchestration` control in the GUI. The current product model is one on/off toggle.
|
|
250
261
|
|
|
251
262
|
`VCM Harness` shows whether VCM managed blocks are installed/up to date in the project rules files and `.gitignore`.
|
|
@@ -253,13 +264,14 @@ There is no separate `Pause orchestration` or `Resume orchestration` control in
|
|
|
253
264
|
`New Task` contains:
|
|
254
265
|
|
|
255
266
|
- `task name`
|
|
256
|
-
- a
|
|
257
|
-
- generated branch preview: `feature/<task-name>`
|
|
258
|
-
- generated worktree preview: `.ai/vcm/worktrees/<task-name>`
|
|
267
|
+
- a `Create worktree and branch` checkbox, selected by default
|
|
268
|
+
- generated branch preview when selected: `feature/<task-name>`
|
|
269
|
+
- generated worktree preview when selected: `.ai/vcm/worktrees/<task-name>`
|
|
270
|
+
- current repository/current branch note when cleared
|
|
259
271
|
|
|
260
272
|
There is no optional title input in the current UI.
|
|
261
273
|
|
|
262
|
-
The worktree/branch path is the
|
|
274
|
+
The worktree/branch path is the recommended VCM task model, but the user may clear the checkbox for an inline task. VCM should not require a separate worktree creation action later.
|
|
263
275
|
|
|
264
276
|
### Task Workspace
|
|
265
277
|
|
|
@@ -367,7 +379,7 @@ For `.gitignore`, VCM uses hash comments:
|
|
|
367
379
|
# VCM:END
|
|
368
380
|
```
|
|
369
381
|
|
|
370
|
-
`.ai/vcm/` is the active VCM local control area
|
|
382
|
+
`.ai/vcm/` is the active VCM local control area. The base repo keeps the task index and nested worktrees; each task runtime repo keeps its own session, message, orchestration, and translation state.
|
|
371
383
|
|
|
372
384
|
VCM must preserve all user-authored content outside the managed block.
|
|
373
385
|
|
|
@@ -468,7 +480,7 @@ Prompt slots:
|
|
|
468
480
|
- `zh-to-en-with-context`
|
|
469
481
|
- `en-to-zh`
|
|
470
482
|
|
|
471
|
-
The settings modal shows
|
|
483
|
+
The settings modal shows all three prompt slots as direct editors. `Reset prompts` restores every prompt to its built-in default. The modal does not include separate enable/output/input-mode switches; opening the role toolbar `Translate` panel is the translation on/off control, and the panel-level `Auto-send` toggle controls whether translated user input is submitted automatically.
|
|
472
484
|
|
|
473
485
|
### Claude Output Translation
|
|
474
486
|
|
|
@@ -482,6 +494,16 @@ VCM tails Claude Code transcript JSONL files under:
|
|
|
482
494
|
|
|
483
495
|
The transcript path is persisted in the role session record. If that path is missing, VCM falls back to resolving by current working directory and then scanning `~/.claude/projects` for the newest file with the session id.
|
|
484
496
|
|
|
497
|
+
VCM owns transcript listening in the backend. Opening the translation panel starts or confirms the backend tailer for the active role session. Closing the panel does not stop that tailer; it keeps collecting Claude output until the role session is stopped/restarted or the task is closed. This keeps translation capture independent from frontend rendering.
|
|
498
|
+
|
|
499
|
+
Backend translation cache lives under:
|
|
500
|
+
|
|
501
|
+
```text
|
|
502
|
+
<taskRepoRoot>/.ai/vcm/translation/<task>/<role>/<session-id>.jsonl
|
|
503
|
+
```
|
|
504
|
+
|
|
505
|
+
The frontend does not subscribe through WebSocket. It polls the backend with a cursor and receives new cached events. The cursor means "next expected seq": `after=18` confirms that seq `1..17` have already been displayed, so the backend can remove those cached events and return seq `18` and later. If the cursor is older than the retained cache, VCM still returns whatever newer events remain; it does not use a snapshot error mode.
|
|
506
|
+
|
|
485
507
|
Transcript event handling:
|
|
486
508
|
|
|
487
509
|
- assistant text -> `prose` -> translated
|
|
@@ -496,9 +518,12 @@ Display behavior:
|
|
|
496
518
|
- `prose` starts by showing the English source.
|
|
497
519
|
- while translating, panel status shows `translating <elapsed>`.
|
|
498
520
|
- when translation succeeds, the English source is replaced by Chinese translated text.
|
|
521
|
+
- `prose` content is rendered as Markdown, including headings, lists, code fences, tables, and links.
|
|
499
522
|
- when translation fails, panel status shows `error` and the entry keeps the visible source plus an error.
|
|
500
523
|
- `tool-output` is dim, one-line, truncated by CSS, and not translated.
|
|
501
524
|
|
|
525
|
+
Long translations do not block capture. Prose entries are pushed to the panel before provider translation starts. `tool_use` and `tool_result` entries are never added to the translation queue; they are displayed immediately.
|
|
526
|
+
|
|
502
527
|
There is no keyword classifier that drops assistant text. A previous design skipped permission-looking or log-looking text; that is removed.
|
|
503
528
|
|
|
504
529
|
### User Input Translation
|
|
@@ -512,7 +537,7 @@ Keyboard behavior:
|
|
|
512
537
|
|
|
513
538
|
After translation succeeds, the English draft replaces the original Chinese text in the same textarea.
|
|
514
539
|
|
|
515
|
-
`Send English`
|
|
540
|
+
`Send English` pastes the current English text into the active role terminal, then sends Enter as a separate terminal input event.
|
|
516
541
|
|
|
517
542
|
Translation panel `Auto-send` is separate from task `Auto orchestration`:
|
|
518
543
|
|
|
@@ -527,13 +552,16 @@ App-level settings:
|
|
|
527
552
|
~/.vcm/settings.json
|
|
528
553
|
```
|
|
529
554
|
|
|
555
|
+
Stored app-level settings include:
|
|
556
|
+
|
|
557
|
+
- UI theme mode: `system`, `light`, or `dark`
|
|
558
|
+
- translation provider settings and API key
|
|
559
|
+
- recent repository paths
|
|
560
|
+
|
|
530
561
|
Repository-level VCM state:
|
|
531
562
|
|
|
532
563
|
```text
|
|
533
564
|
.ai/vcm/tasks/<task>.json
|
|
534
|
-
.ai/vcm/sessions/<task>.json
|
|
535
|
-
.ai/vcm/messages/<task>.jsonl
|
|
536
|
-
.ai/vcm/orchestration/<task>.json
|
|
537
565
|
.ai/vcm/worktrees/<task>/
|
|
538
566
|
```
|
|
539
567
|
|
|
@@ -544,14 +572,20 @@ Project config:
|
|
|
544
572
|
~/.vcm/projects/index.json
|
|
545
573
|
```
|
|
546
574
|
|
|
547
|
-
The base repository's `.ai/vcm/` directory
|
|
575
|
+
The base repository's `.ai/vcm/` directory stores the task index and nested task worktrees. Long-lived project config is stored under `~/.vcm` so it survives outside Git-ignored repo state.
|
|
548
576
|
|
|
549
577
|
Task worktree local files:
|
|
550
578
|
|
|
551
579
|
```text
|
|
580
|
+
.ai/vcm/worktrees/<task>/.ai/vcm/sessions/<task>.json
|
|
581
|
+
.ai/vcm/worktrees/<task>/.ai/vcm/messages/<task>.jsonl
|
|
582
|
+
.ai/vcm/worktrees/<task>/.ai/vcm/orchestration/<task>.json
|
|
583
|
+
.ai/vcm/worktrees/<task>/.ai/vcm/translation/<task>/
|
|
552
584
|
.ai/vcm/worktrees/<task>/.ai/handoffs/<task>/
|
|
553
585
|
```
|
|
554
586
|
|
|
587
|
+
For tasks created without a worktree, the task runtime repo is the connected base repo, so the runtime state resolves under the base repo's `.ai/vcm/`.
|
|
588
|
+
|
|
555
589
|
External Claude transcripts:
|
|
556
590
|
|
|
557
591
|
```text
|
|
@@ -583,8 +617,9 @@ This protects against publishing raw TypeScript bin files or missing frontend as
|
|
|
583
617
|
VCM V1 is successful when:
|
|
584
618
|
|
|
585
619
|
- A user can connect a repo without global Git safe-directory setup.
|
|
586
|
-
- A user can create a task, which creates `feature/<task>` and `.ai/vcm/worktrees/<task>`.
|
|
587
|
-
- A user can
|
|
620
|
+
- A user can create a default task, which creates `feature/<task>` and `.ai/vcm/worktrees/<task>`.
|
|
621
|
+
- A user can clear `Create worktree and branch` and create a task in the connected repo/current branch.
|
|
622
|
+
- A user can start all four role sessions in the task runtime repo.
|
|
588
623
|
- Switching roles never loses the embedded terminal.
|
|
589
624
|
- Restart creates a fresh Claude session; Resume reconnects to the persisted one.
|
|
590
625
|
- Permission modes are reflected in the Claude command.
|
|
@@ -21,7 +21,7 @@ Runtime shape:
|
|
|
21
21
|
```text
|
|
22
22
|
browser
|
|
23
23
|
-> React GUI
|
|
24
|
-
-> HTTP API + WebSocket
|
|
24
|
+
-> HTTP API + terminal WebSocket
|
|
25
25
|
-> Fastify backend
|
|
26
26
|
-> services
|
|
27
27
|
-> node-pty
|
|
@@ -94,9 +94,9 @@ Responsibilities:
|
|
|
94
94
|
- Render repository connect form.
|
|
95
95
|
- Render repository summary.
|
|
96
96
|
- Render workflow panel.
|
|
97
|
-
- Render settings section with Messages, Events, Auto orchestration.
|
|
97
|
+
- Render settings section with Theme, Messages, Events, Auto orchestration.
|
|
98
98
|
- Render harness status/actions.
|
|
99
|
-
- Render task creation form with one task-name field, a
|
|
99
|
+
- Render task creation form with one task-name field, a `Create worktree and branch` checkbox selected by default, and generated branch/path previews when selected.
|
|
100
100
|
- Render task list.
|
|
101
101
|
- Render Messages and Events modals.
|
|
102
102
|
|
|
@@ -140,11 +140,12 @@ File:
|
|
|
140
140
|
Responsibilities:
|
|
141
141
|
|
|
142
142
|
- Load translation settings and prompt previews.
|
|
143
|
-
-
|
|
143
|
+
- Start backend transcript listening for the current terminal runtime session id.
|
|
144
|
+
- Poll backend translation events with a cursor.
|
|
144
145
|
- Render dark translation output panel.
|
|
145
146
|
- Render translation status: `ready`, `translating <elapsed>`, or `error`.
|
|
146
147
|
- Render preserved tool output as dim one-line rows.
|
|
147
|
-
- Render prose source while translating, then translated text after completion.
|
|
148
|
+
- Render prose source while translating, then translated text after completion, using Markdown rendering for prose.
|
|
148
149
|
- Render user composer.
|
|
149
150
|
- Translate on `Enter`; newline on `Shift+Enter`.
|
|
150
151
|
- Replace Chinese input with English draft after translation.
|
|
@@ -186,7 +187,6 @@ Fastify registers:
|
|
|
186
187
|
- message routes
|
|
187
188
|
- translation routes
|
|
188
189
|
- terminal WebSocket
|
|
189
|
-
- translation WebSocket
|
|
190
190
|
|
|
191
191
|
## 5. Repository Connection
|
|
192
192
|
|
|
@@ -224,12 +224,12 @@ VCM does not require global `safe.directory` configuration.
|
|
|
224
224
|
|
|
225
225
|
## 6. Task Worktree Architecture
|
|
226
226
|
|
|
227
|
-
Task-level worktree management is the
|
|
227
|
+
Task-level worktree management is the default architecture for multi-task parallelism.
|
|
228
228
|
|
|
229
229
|
Rule:
|
|
230
230
|
|
|
231
231
|
```text
|
|
232
|
-
|
|
232
|
+
default VCM task = one branch + one git worktree + one handoff directory + one role-session set
|
|
233
233
|
```
|
|
234
234
|
|
|
235
235
|
Branch name:
|
|
@@ -244,7 +244,15 @@ Worktree path:
|
|
|
244
244
|
<baseRepoRoot>/.ai/vcm/worktrees/<taskSlug>
|
|
245
245
|
```
|
|
246
246
|
|
|
247
|
-
VCM does not support switching a task to another branch or worktree after creation. If the user needs a different branch/worktree, they should create a new task.
|
|
247
|
+
VCM does not support switching a task to another branch or worktree mode after creation. If the user needs a different branch/worktree choice, they should create a new task.
|
|
248
|
+
|
|
249
|
+
When `Create worktree and branch` is cleared, the task uses:
|
|
250
|
+
|
|
251
|
+
```text
|
|
252
|
+
branch: current connected-repo branch
|
|
253
|
+
runtime repo root: <baseRepoRoot>
|
|
254
|
+
worktreePath: undefined
|
|
255
|
+
```
|
|
248
256
|
|
|
249
257
|
VCM does not create worktrees by role. All four role sessions for a task share the same task worktree:
|
|
250
258
|
|
|
@@ -265,13 +273,10 @@ VCM distinguishes:
|
|
|
265
273
|
- `branch`: `feature/<taskSlug>`.
|
|
266
274
|
- `worktreePath`: same as `taskRepoRoot`.
|
|
267
275
|
|
|
268
|
-
|
|
276
|
+
Base repo state is only the task index and the container for nested task worktrees:
|
|
269
277
|
|
|
270
278
|
```text
|
|
271
279
|
<baseRepoRoot>/.ai/vcm/tasks/<task>.json
|
|
272
|
-
<baseRepoRoot>/.ai/vcm/sessions/<task>.json
|
|
273
|
-
<baseRepoRoot>/.ai/vcm/messages/<task>.jsonl
|
|
274
|
-
<baseRepoRoot>/.ai/vcm/orchestration/<task>.json
|
|
275
280
|
<baseRepoRoot>/.ai/vcm/worktrees/<task>/
|
|
276
281
|
```
|
|
277
282
|
|
|
@@ -282,13 +287,19 @@ Project configuration is app-local and stored outside the repository:
|
|
|
282
287
|
~/.vcm/projects/index.json
|
|
283
288
|
```
|
|
284
289
|
|
|
285
|
-
Task source changes and handoff artifacts live in the task worktree:
|
|
290
|
+
Task runtime state, source changes, and handoff artifacts live in the task runtime repo. For worktree-backed tasks this is the nested task worktree:
|
|
286
291
|
|
|
287
292
|
```text
|
|
293
|
+
<baseRepoRoot>/.ai/vcm/worktrees/<task>/.ai/vcm/sessions/<task>.json
|
|
294
|
+
<baseRepoRoot>/.ai/vcm/worktrees/<task>/.ai/vcm/messages/<task>.jsonl
|
|
295
|
+
<baseRepoRoot>/.ai/vcm/worktrees/<task>/.ai/vcm/orchestration/<task>.json
|
|
296
|
+
<baseRepoRoot>/.ai/vcm/worktrees/<task>/.ai/vcm/translation/<task>/
|
|
288
297
|
<baseRepoRoot>/.ai/vcm/worktrees/<task>/.ai/handoffs/<task>/
|
|
289
298
|
```
|
|
290
299
|
|
|
291
|
-
|
|
300
|
+
For inline tasks, `taskRepoRoot` is the connected base repo, so these same runtime paths resolve under the connected repo's `.ai/vcm/`.
|
|
301
|
+
|
|
302
|
+
This split lets VCM list tasks from the base repo after worktrees are created, while each task's runtime state follows the same root as the role sessions.
|
|
292
303
|
|
|
293
304
|
### 6.2 Git Ignore Requirement
|
|
294
305
|
|
|
@@ -307,37 +318,36 @@ The VCM harness manages a `.gitignore` block that ignores `.ai/vcm/` before task
|
|
|
307
318
|
```text
|
|
308
319
|
POST /api/tasks
|
|
309
320
|
-> validate taskSlug
|
|
310
|
-
-> compute branch feature/<taskSlug>
|
|
311
|
-
-> compute worktreePath <baseRepoRoot>/.ai/vcm/worktrees/<taskSlug>
|
|
312
|
-
-> assert branch does not already exist
|
|
313
|
-
-> assert worktreePath does not already exist
|
|
314
321
|
-> assert .ai/vcm/ is ignored by Git
|
|
315
|
-
->
|
|
316
|
-
|
|
322
|
+
-> if createWorktree is not false:
|
|
323
|
+
-> compute branch feature/<taskSlug>
|
|
324
|
+
-> compute worktreePath <baseRepoRoot>/.ai/vcm/worktrees/<taskSlug>
|
|
325
|
+
-> assert branch does not already exist
|
|
326
|
+
-> assert worktreePath does not already exist
|
|
327
|
+
-> assert base repo has no uncommitted changes
|
|
328
|
+
-> git worktree add -b feature/<taskSlug> <worktreePath> <baseRef>
|
|
329
|
+
-> otherwise:
|
|
330
|
+
-> read current base repo branch
|
|
331
|
+
-> leave worktreePath undefined
|
|
317
332
|
-> create handoff structure in taskRepoRoot
|
|
318
333
|
-> write central task metadata under baseRepoRoot/.ai/vcm/tasks/<task>.json
|
|
319
334
|
```
|
|
320
335
|
|
|
321
336
|
The default `baseRef` is the connected repo's current `HEAD`.
|
|
322
337
|
|
|
323
|
-
### 6.4 Task
|
|
338
|
+
### 6.4 Task Close Flow
|
|
324
339
|
|
|
325
340
|
```text
|
|
326
341
|
POST /api/tasks/:taskSlug/cleanup
|
|
327
|
-
-> require no running role sessions
|
|
328
342
|
-> load task metadata
|
|
329
|
-
-> verify
|
|
330
|
-
->
|
|
331
|
-
->
|
|
332
|
-
->
|
|
333
|
-
-> delete
|
|
343
|
+
-> when worktreePath exists, verify it belongs under <baseRepoRoot>/.ai/vcm/worktrees/
|
|
344
|
+
-> when worktreePath exists, git worktree remove --force <worktreePath>
|
|
345
|
+
-> when worktreePath exists, delete the task branch by default
|
|
346
|
+
-> delete base task metadata
|
|
347
|
+
-> delete task runtime session/message/orchestration/translation metadata
|
|
334
348
|
```
|
|
335
349
|
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
- Keep `feature/<taskSlug>` by default.
|
|
339
|
-
- Allow branch deletion only with explicit confirmation.
|
|
340
|
-
- Prefer allowing deletion only when the branch has been merged, or when the user force-confirms.
|
|
350
|
+
Close Task is intentionally destructive after user confirmation. It does not preflight running role sessions or uncommitted worktree changes. Tasks created without a worktree remove VCM metadata only because there is no VCM-owned branch/worktree to delete.
|
|
341
351
|
|
|
342
352
|
## 7. Task And Artifact Model
|
|
343
353
|
|
|
@@ -480,7 +490,7 @@ Permission flags:
|
|
|
480
490
|
Session persistence:
|
|
481
491
|
|
|
482
492
|
```text
|
|
483
|
-
<
|
|
493
|
+
<taskRepoRoot>/.ai/vcm/sessions/<task>.json
|
|
484
494
|
```
|
|
485
495
|
|
|
486
496
|
The persisted record includes:
|
|
@@ -545,9 +555,9 @@ Files:
|
|
|
545
555
|
State:
|
|
546
556
|
|
|
547
557
|
```text
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
558
|
+
<taskRepoRoot>/.ai/vcm/messages/<task>.jsonl
|
|
559
|
+
<taskRepoRoot>/.ai/vcm/orchestration/<task>.json
|
|
560
|
+
<taskRepoRoot>/.ai/handoffs/<task>/messages/<message-id>.md
|
|
551
561
|
```
|
|
552
562
|
|
|
553
563
|
Policy:
|
|
@@ -576,11 +586,12 @@ Auto mode:
|
|
|
576
586
|
send -> delivered
|
|
577
587
|
```
|
|
578
588
|
|
|
579
|
-
The backend
|
|
589
|
+
The backend pastes a `[VCM MESSAGE]` envelope into the target terminal, then sends Enter as a separate terminal input event.
|
|
580
590
|
|
|
581
591
|
The backend still exposes pause/resume orchestration API routes and stores `paused` for compatibility. The current GUI only toggles `mode` between `manual` and `auto`.
|
|
582
592
|
|
|
583
|
-
Messages and orchestration snapshots are
|
|
593
|
+
Messages and orchestration snapshots are task runtime state under `taskRepoRoot/.ai/vcm`. Message body markdown also lives in the task worktree handoff directory.
|
|
594
|
+
Messages and orchestration snapshots are task runtime state under `taskRepoRoot/.ai/vcm`. Message body markdown also lives in the task worktree handoff directory.
|
|
584
595
|
|
|
585
596
|
## 12. Role Command Compatibility
|
|
586
597
|
|
|
@@ -608,7 +619,7 @@ The dispatcher:
|
|
|
608
619
|
2. Reads the role command artifact.
|
|
609
620
|
3. Rejects missing, empty, or placeholder role commands.
|
|
610
621
|
4. Resolves primary command path `role-commands/<role>.md`, with legacy fallback `<role>-command.md`.
|
|
611
|
-
5.
|
|
622
|
+
5. Pastes `Please read and execute the role command at: <path>` to the target terminal, then sends Enter as a separate terminal input event.
|
|
612
623
|
|
|
613
624
|
This is a compatibility path. The preferred V1 coordination path is `vcmctl` message bus.
|
|
614
625
|
|
|
@@ -664,7 +675,6 @@ Files:
|
|
|
664
675
|
- `src/backend/services/translation-prompts.ts`
|
|
665
676
|
- `src/backend/services/claude-transcript-service.ts`
|
|
666
677
|
- `src/backend/adapters/translation-provider.ts`
|
|
667
|
-
- `src/backend/ws/translation-ws.ts`
|
|
668
678
|
- `src/backend/api/translation-routes.ts`
|
|
669
679
|
- `src/frontend/components/translation-panel.tsx`
|
|
670
680
|
- `src/frontend/components/translation-settings-modal.tsx`
|
|
@@ -683,6 +693,7 @@ Storage:
|
|
|
683
693
|
|
|
684
694
|
Stored data:
|
|
685
695
|
|
|
696
|
+
- UI theme preference: `system`, `light`, or `dark`
|
|
686
697
|
- translation settings
|
|
687
698
|
- translation secrets
|
|
688
699
|
- recent repository paths, max 5
|
|
@@ -718,8 +729,11 @@ Tailer:
|
|
|
718
729
|
- validates file exists
|
|
719
730
|
- can replay history since session start minus a grace window
|
|
720
731
|
- uses `fs.watch`
|
|
721
|
-
- also polls every
|
|
732
|
+
- also polls every 200ms
|
|
722
733
|
- parses only complete newline-delimited JSON records
|
|
734
|
+
- is owned by the backend translation service, not the frontend panel
|
|
735
|
+
- stays running after the panel closes
|
|
736
|
+
- stops only when the role session is stopped/restarted or the task is closed
|
|
723
737
|
|
|
724
738
|
Parsed transcript events:
|
|
725
739
|
|
|
@@ -736,9 +750,21 @@ Translation service behavior:
|
|
|
736
750
|
- ignores thinking
|
|
737
751
|
- translates text/question/todo/agent as prose
|
|
738
752
|
- preserves tool_use/tool_result as tool-output
|
|
739
|
-
- queues translation per runtime session id
|
|
740
|
-
-
|
|
741
|
-
-
|
|
753
|
+
- queues provider translation per runtime session id
|
|
754
|
+
- pushes prose entries before provider translation starts
|
|
755
|
+
- pushes tool_use/tool_result immediately without entering the translation queue
|
|
756
|
+
- writes translation events to `<taskRepoRoot>/.ai/vcm/translation/<task>/<role>/<session-id>.jsonl`
|
|
757
|
+
- exposes HTTP polling for frontend rendering
|
|
758
|
+
|
|
759
|
+
Polling protocol:
|
|
760
|
+
|
|
761
|
+
- `seq` starts at 1 for each translation session cache.
|
|
762
|
+
- the frontend calls `GET /api/translation/sessions/:sessionId/events?after=<cursor>`.
|
|
763
|
+
- `after` is the next expected seq, not the last displayed seq.
|
|
764
|
+
- `after=18` lets the backend delete cached events with `seq < 18` and return events with `seq >= 18`.
|
|
765
|
+
- if `after` is older than the retained cache, the backend returns whatever newer events still exist.
|
|
766
|
+
- no snapshot mismatch error is used.
|
|
767
|
+
- translated prose replacement is a later `entry` event with the same translation entry id and a newer `seq`.
|
|
742
768
|
|
|
743
769
|
### User Input Path
|
|
744
770
|
|
|
@@ -749,10 +775,10 @@ textarea -> POST translation/input -> provider -> English draft in the same text
|
|
|
749
775
|
Send path:
|
|
750
776
|
|
|
751
777
|
```text
|
|
752
|
-
POST translation/send -> runtime.write(session.id,
|
|
778
|
+
POST translation/send -> bracketed paste English text -> short delay -> runtime.write(session.id, "\r")
|
|
753
779
|
```
|
|
754
780
|
|
|
755
|
-
The backend strips trailing newlines before
|
|
781
|
+
The backend strips trailing newlines before pasting and sends Enter separately. This avoids Claude Code TUI cases where a single large PTY write containing both text and `\r` fills the input line but does not submit it.
|
|
756
782
|
|
|
757
783
|
## 15. API Surface
|
|
758
784
|
|
|
@@ -819,6 +845,13 @@ POST /api/tasks/:taskSlug/orchestration/pause
|
|
|
819
845
|
POST /api/tasks/:taskSlug/orchestration/resume
|
|
820
846
|
```
|
|
821
847
|
|
|
848
|
+
App settings:
|
|
849
|
+
|
|
850
|
+
```text
|
|
851
|
+
GET /api/settings/preferences
|
|
852
|
+
PUT /api/settings/preferences
|
|
853
|
+
```
|
|
854
|
+
|
|
822
855
|
Translation:
|
|
823
856
|
|
|
824
857
|
```text
|
|
@@ -826,6 +859,8 @@ GET /api/translation/settings
|
|
|
826
859
|
PUT /api/translation/settings
|
|
827
860
|
GET /api/translation/prompts
|
|
828
861
|
POST /api/translation/test
|
|
862
|
+
POST /api/tasks/:taskSlug/sessions/:role/translation/start
|
|
863
|
+
GET /api/translation/sessions/:sessionId/events?after=<cursor>&limit=<n>
|
|
829
864
|
POST /api/tasks/:taskSlug/sessions/:role/translation/input
|
|
830
865
|
POST /api/tasks/:taskSlug/sessions/:role/translation/send
|
|
831
866
|
POST /api/translation/sessions/:sessionId/clear
|
|
@@ -836,7 +871,6 @@ WebSockets:
|
|
|
836
871
|
|
|
837
872
|
```text
|
|
838
873
|
/ws/terminal/:sessionId
|
|
839
|
-
/ws/translation/:sessionId
|
|
840
874
|
```
|
|
841
875
|
|
|
842
876
|
## 16. Error Handling
|