vibe-coding-master 0.0.13 → 0.0.15
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 +36 -36
- package/dist/backend/api/claude-hook-routes.js +5 -0
- package/dist/backend/api/message-routes.js +8 -36
- package/dist/backend/server.js +12 -26
- package/dist/backend/services/artifact-service.js +27 -2
- package/dist/backend/services/claude-hook-service.js +67 -0
- package/dist/backend/services/harness-service.js +112 -0
- package/dist/backend/services/message-service.js +283 -175
- package/dist/backend/services/round-service.js +17 -127
- package/dist/backend/services/session-service.js +55 -2
- package/dist/backend/services/status-service.js +0 -76
- package/dist/backend/templates/handoff.js +3 -0
- package/dist/backend/templates/harness/architect-agent.js +5 -0
- package/dist/backend/templates/harness/claude-root.js +6 -2
- package/dist/backend/templates/harness/coder-agent.js +5 -0
- package/dist/backend/templates/harness/project-manager-agent.js +7 -3
- package/dist/backend/templates/harness/reviewer-agent.js +5 -0
- package/dist/backend/templates/message-envelope.js +7 -1
- package/dist/shared/types/claude-hook.js +1 -0
- package/dist-frontend/assets/{index-CyJrJge9.js → index-QhzvzTMZ.js} +43 -42
- package/dist-frontend/assets/index-jEkUTnIY.css +32 -0
- package/dist-frontend/index.html +2 -2
- package/docs/cc-best-practices.md +13 -4
- package/docs/product-design.md +74 -47
- package/docs/v1-architecture-design.md +53 -53
- package/docs/v1-implementation-plan.md +94 -61
- package/package.json +2 -3
- package/scripts/verify-package.mjs +0 -3
- package/dist/cli/vcmctl.js +0 -141
- package/dist-frontend/assets/index-N5DA0uE9.css +0 -32
|
@@ -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}.round-notice{position:fixed;right:20px;bottom:20px;z-index:30;display:grid;gap:2px;min-width:220px;max-width:min(360px,calc(100vw - 40px));border:1px solid #2f6f73;border-radius:8px;background:#e8f4f2;color:#123f43;box-shadow:0 14px 32px #1f242b29;padding:10px 12px}.round-notice strong{font-size:13px}.round-notice span{font-size: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}.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-console-actions{display:flex;flex-wrap:wrap;gap:8px;align-items:center;justify-content:flex-end}.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.is-user-input{border-top:4px solid #3a4149;margin-top:14px;padding-top:14px}.translation-entry.is-user-input:first-child{margin-top: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,.modal-actions,.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-reason,.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-reason,.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-idle{border-color:#9aa3a8;background:#edf0f1;color:#465056}.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-delivering,.status-submitted,.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-delivery_failed,.status-response_ready_missing_result,.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))}.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-reason,: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{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] .round-notice{border-color:#56d4dd;background:#10262b;color:#d6fbff;box-shadow:0 14px 32px #0104097a}: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] .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] .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] .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] .status-idle{border-color:#69717d;background:#20262f;color:#d6deeb}: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-delivery_failed,:root[data-theme=dark] .status-response_ready_missing_result,: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-delivering,:root[data-theme=dark] .status-submitted,: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-QhzvzTMZ.js"></script>
|
|
8
|
+
<link rel="stylesheet" crossorigin href="/assets/index-jEkUTnIY.css">
|
|
9
9
|
</head>
|
|
10
10
|
<body>
|
|
11
11
|
<div id="root"></div>
|
|
@@ -214,7 +214,11 @@ Role-specific behavior lives in `.claude/agents/`.
|
|
|
214
214
|
- Do not let one coding session own architecture/plan decisions, implementation, final testing responsibility, and review.
|
|
215
215
|
- Role outputs are exchanged through `.ai/vcm/handoffs/`, not through chat history.
|
|
216
216
|
- Role messaging is turn-based. Keep at most one active message to the same target role.
|
|
217
|
-
-
|
|
217
|
+
- Send role messages by writing or updating the fixed route file under `.ai/vcm/handoffs/messages/<from-role>-<to-role>.md`.
|
|
218
|
+
- For a given target role, update the same route file instead of creating multiple fragmented messages.
|
|
219
|
+
- After writing or updating a role message file, end the current Claude Code turn. Treat the file write as the final coordination action of that turn.
|
|
220
|
+
- Do not poll message files, start shell loops, or keep the turn open waiting for another role's answer. VCM dispatches pending route files after Claude Code `Stop`.
|
|
221
|
+
- Do not use Claude Code Task/Subagent for VCM role delegation; VCM owns the four long-running role sessions.
|
|
218
222
|
- If new information appears while a role is still processing, update the handoff artifact or wait instead of sending fragmented follow-up messages.
|
|
219
223
|
- When the required role route includes `architect`, coding must not start until the architecture and plan artifact exists.
|
|
220
224
|
- If the current session was not started with the required role, stop and ask the user to restart with `claude --agent <role>`; do not pretend to be that role inside the wrong session.
|
|
@@ -562,7 +566,7 @@ Do not include:
|
|
|
562
566
|
|
|
563
567
|
For large projects, the default execution model should be explicit role-based sessions, not dynamic role routing inside one generic Claude conversation.
|
|
564
568
|
|
|
565
|
-
The user-facing task should start with a `project-manager` role session. The project manager owns user communication,
|
|
569
|
+
The user-facing task should start with a `project-manager` role session. The project manager owns user communication, route-file message preparation, severity classification, role routing, progress tracking, and process verification. It does not own architecture, coding, and independent review for the same non-trivial task.
|
|
566
570
|
|
|
567
571
|
Do not make one generic Claude session own architecture, planning, coding, final testing, and review for non-trivial work. That blurs responsibility and makes acceptance weak.
|
|
568
572
|
|
|
@@ -716,7 +720,7 @@ Role responsibilities:
|
|
|
716
720
|
|
|
717
721
|
```text
|
|
718
722
|
project-manager
|
|
719
|
-
owns user communication, task clarification, task specs, role routing, and
|
|
723
|
+
owns user communication, task clarification, task specs, role routing, and route-file message preparation
|
|
720
724
|
turns user input into an engineering task when needed
|
|
721
725
|
summarizes role outputs back to the user
|
|
722
726
|
creates and verifies handoff artifacts
|
|
@@ -1362,6 +1366,10 @@ Do not rely on `CLAUDE.md` for constraints that can be automated.
|
|
|
1362
1366
|
Recommended hooks:
|
|
1363
1367
|
|
|
1364
1368
|
```text
|
|
1369
|
+
Stop:
|
|
1370
|
+
notify VCM that a role turn ended
|
|
1371
|
+
trigger VCM to scan .ai/vcm/handoffs/messages/ for pending route files
|
|
1372
|
+
|
|
1365
1373
|
PreToolUse:
|
|
1366
1374
|
block protected files
|
|
1367
1375
|
block destructive commands
|
|
@@ -1376,6 +1384,7 @@ PostToolUse:
|
|
|
1376
1384
|
run cheap lint
|
|
1377
1385
|
|
|
1378
1386
|
Stop:
|
|
1387
|
+
switch the role activity state to idle
|
|
1379
1388
|
check project manager did not bypass required role route
|
|
1380
1389
|
check task severity and required role route
|
|
1381
1390
|
check required handoff artifacts exist
|
|
@@ -2150,7 +2159,7 @@ Monthly review:
|
|
|
2150
2159
|
If you can only enforce 16 rules, enforce these:
|
|
2151
2160
|
|
|
2152
2161
|
1. User-facing tasks start with `claude --agent project-manager`; untagged sessions are not implicit project managers.
|
|
2153
|
-
2. The `project-manager` agent owns user communication, task clarification, and precise
|
|
2162
|
+
2. The `project-manager` agent owns user communication, task clarification, and precise route-file message preparation.
|
|
2154
2163
|
3. Complex tasks use explicit role sessions, handoff artifacts, and plan first; do not edit directly.
|
|
2155
2164
|
4. One task uses one branch, one worktree, one handoff directory, and one PR by default.
|
|
2156
2165
|
5. Role sessions for the same task work in the same task worktree sequentially; parallel write work uses separate task or sub-task worktrees.
|
package/docs/product-design.md
CHANGED
|
@@ -62,8 +62,6 @@ project-manager
|
|
|
62
62
|
-> project-manager final acceptance, commit, and PR
|
|
63
63
|
```
|
|
64
64
|
|
|
65
|
-
The workflow is a soft guide in V1. VCM computes readiness from handoff artifact checks and session state, then shows the result in the sidebar. It does not block the user from manually starting a role out of order.
|
|
66
|
-
|
|
67
65
|
### 4.1 Task Worktree Model
|
|
68
66
|
|
|
69
67
|
Task-level worktree management is the recommended default model for multi-task parallelism:
|
|
@@ -221,7 +219,6 @@ Sections:
|
|
|
221
219
|
|
|
222
220
|
- `Repository Path`
|
|
223
221
|
- `Repository`
|
|
224
|
-
- `Workflow`
|
|
225
222
|
- `Settings`
|
|
226
223
|
- `VCM Harness`
|
|
227
224
|
- `New Task`
|
|
@@ -243,24 +240,18 @@ Repository Path
|
|
|
243
240
|
|
|
244
241
|
The old `Dirty: yes/no` label is not used. The UI uses `Working tree: clean` or `Working tree: uncommitted changes`.
|
|
245
242
|
|
|
246
|
-
`Workflow` shows the five soft workflow gates:
|
|
247
|
-
|
|
248
|
-
- Architecture
|
|
249
|
-
- Implementation
|
|
250
|
-
- Review
|
|
251
|
-
- Docs Sync
|
|
252
|
-
- PM Final
|
|
253
|
-
|
|
254
243
|
`Settings` contains:
|
|
255
244
|
|
|
256
245
|
- `Theme` button, cycling through `System`, `Light`, and `Dark`.
|
|
257
246
|
- `Round alert` button, on by default, controlling the completion prompt and sound.
|
|
247
|
+
- `Try alert` button, firing the same completion prompt and sound for local verification.
|
|
258
248
|
- `Messages` button, opening a modal list of role messages.
|
|
259
249
|
- `Events` button, opening a modal list of runtime UI events for the current task.
|
|
260
250
|
|
|
261
251
|
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.
|
|
262
252
|
|
|
263
253
|
When `Round alert` is on, VCM shows a compact in-app prompt and plays a short local sound after a full conversation round truly ends.
|
|
254
|
+
`Try alert` must work even when no conversation has just completed so the user can verify browser sound and notification behavior.
|
|
264
255
|
|
|
265
256
|
There is no separate `Pause orchestration` or `Resume orchestration` control in the GUI. The current product model is one on/off toggle in the active role toolbar, immediately to the left of `Translate`.
|
|
266
257
|
|
|
@@ -288,7 +279,7 @@ TASK WORKSPACE <task> <branch> <worktree> [Project Manager] [Architect] [Co
|
|
|
288
279
|
|
|
289
280
|
Role tabs show the session status for each role.
|
|
290
281
|
|
|
291
|
-
The main task workspace only renders the active role console. Messages
|
|
282
|
+
The main task workspace only renders the active role console. Messages and Events are opened from the sidebar.
|
|
292
283
|
|
|
293
284
|
## 7. Role Console
|
|
294
285
|
|
|
@@ -325,22 +316,20 @@ The split should stay close to 50/50 width. Both panes expand vertically to fill
|
|
|
325
316
|
|
|
326
317
|
## 8. Round Completion Detection
|
|
327
318
|
|
|
328
|
-
VCM detects answer completion from
|
|
319
|
+
VCM detects answer completion from VCM's hook-driven role activity state, not from terminal silence.
|
|
329
320
|
|
|
330
321
|
Backend role state:
|
|
331
322
|
|
|
332
|
-
-
|
|
333
|
-
- `
|
|
334
|
-
-
|
|
335
|
-
- assistant text with `stop_reason === "end_turn"`: candidate answer end.
|
|
336
|
-
- candidate answer end becomes idle only after no pending tools remain and a short debounce passes.
|
|
323
|
+
- VCM terminal submit: role becomes `running`.
|
|
324
|
+
- `Stop`: role becomes `idle` and records `lastStopAt`.
|
|
325
|
+
- The role tab and Round alert use the same activity state source.
|
|
337
326
|
|
|
338
327
|
Task-level round state:
|
|
339
328
|
|
|
340
|
-
- If VCM role messages exist, the latest
|
|
341
|
-
- A PM -> Coder -> PM chain completes only when the latest target role, PM, reaches
|
|
329
|
+
- If VCM role messages exist, the latest active `submitted` message defines the current target role.
|
|
330
|
+
- A PM -> Coder -> PM chain completes only when the latest target role, PM, reaches hook `Stop`.
|
|
342
331
|
- Queued or pending messages prevent completion because more role work is waiting.
|
|
343
|
-
- If no VCM role message is involved, the latest direct role
|
|
332
|
+
- If no VCM role message is involved, the latest direct role `Stop` can complete the round.
|
|
344
333
|
|
|
345
334
|
The frontend polls this task-level round state. It deduplicates `completionId`, then shows the prompt and plays the sound only once per completed round.
|
|
346
335
|
|
|
@@ -435,52 +424,90 @@ Each task creates:
|
|
|
435
424
|
review-report.md
|
|
436
425
|
docs-sync-report.md
|
|
437
426
|
messages/
|
|
438
|
-
|
|
427
|
+
project-manager-architect.md
|
|
428
|
+
project-manager-coder.md
|
|
429
|
+
project-manager-reviewer.md
|
|
430
|
+
architect-project-manager.md
|
|
431
|
+
coder-project-manager.md
|
|
432
|
+
reviewer-project-manager.md
|
|
433
|
+
<optional-peer-route>.md
|
|
439
434
|
```
|
|
440
435
|
|
|
441
436
|
The product treats handoff files as task-local coordination facts. The terminal is useful for live interaction, but handoff files and message history are the source of truth during a task. They live under `.ai/vcm/`, are ignored by Git, and are removed by `Close Task`; final decisions that should survive must be copied into normal project docs, source, commit messages, or PR text.
|
|
442
437
|
|
|
443
|
-
The main UI no longer has a dedicated artifact panel. Artifact APIs still exist for status checks
|
|
438
|
+
The main UI no longer has a dedicated artifact panel. Artifact APIs still exist for status checks and future UI work.
|
|
444
439
|
|
|
445
440
|
## 12. Message Bus
|
|
446
441
|
|
|
447
|
-
VCM messaging is
|
|
442
|
+
VCM messaging is file-driven and dispatched by VCM after Claude Code turn completion. Roles do not call a VCM CLI to send messages.
|
|
448
443
|
|
|
449
444
|
```text
|
|
450
445
|
role terminal
|
|
451
|
-
->
|
|
452
|
-
->
|
|
453
|
-
->
|
|
454
|
-
->
|
|
455
|
-
->
|
|
446
|
+
-> writes/updates one route file under .ai/vcm/handoffs/messages/
|
|
447
|
+
-> ends the Claude Code turn
|
|
448
|
+
-> Claude Code Stop hook calls VCM backend directly
|
|
449
|
+
-> VCM scans pending route files
|
|
450
|
+
-> VCM validates, snapshots, and dispatches one allowed message per idle target role
|
|
456
451
|
```
|
|
457
452
|
|
|
458
|
-
|
|
453
|
+
Route files:
|
|
454
|
+
|
|
455
|
+
- File name format is `<from-role>-<to-role>.md`.
|
|
456
|
+
- Role names use VCM role slugs, for example `project-manager-coder.md`.
|
|
457
|
+
- The file path determines `from` and `to`; frontmatter cannot override the route.
|
|
458
|
+
- The file body is Markdown.
|
|
459
|
+
- Optional YAML frontmatter may provide `type`, `severity`, `title`, or `related_artifact`.
|
|
460
|
+
- Blank or whitespace-only files mean "no pending message".
|
|
461
|
+
- Non-empty files mean "pending message waiting for VCM dispatch".
|
|
462
|
+
|
|
463
|
+
The important product rule is one file per directed route. If role A decides several times during one turn that it needs to call role B, it must edit the same `A-B.md` file instead of creating multiple messages. This turns duplicate sends into a single latest pending instruction.
|
|
464
|
+
|
|
465
|
+
Default route policy:
|
|
459
466
|
|
|
460
|
-
- `project-manager` to `architect
|
|
461
|
-
- `architect
|
|
462
|
-
-
|
|
467
|
+
- `project-manager` may send to `architect`, `coder`, and `reviewer`.
|
|
468
|
+
- `architect`, `coder`, and `reviewer` may send to `project-manager`.
|
|
469
|
+
- Peer routes such as `coder-reviewer.md` may exist for explicit task designs, but VCM still serializes delivery per target role.
|
|
470
|
+
- `user` talks to `project-manager` through the normal active terminal or translation composer, not through a route file.
|
|
471
|
+
|
|
472
|
+
Stop-triggered scan:
|
|
473
|
+
|
|
474
|
+
- VCM injects a Claude Code `Stop` hook into `.claude/settings.json`.
|
|
475
|
+
- The hook does not call `vcmctl`; it POSTs directly to the local VCM backend.
|
|
476
|
+
- When any role stops, VCM marks that role idle, then scans pending route files.
|
|
477
|
+
- VCM scans the stopped role's outgoing files and also any pending files targeting newly idle roles, so messages that were blocked by a busy target can be delivered after that target stops.
|
|
478
|
+
- VCM reads only stable, non-empty files and ignores blank files.
|
|
479
|
+
- VCM delivers at most one message to a target role per scan.
|
|
480
|
+
- If multiple pending files target the same idle role, VCM chooses deterministically by oldest modified time, then route name.
|
|
463
481
|
|
|
464
482
|
Manual mode:
|
|
465
483
|
|
|
466
484
|
- message status becomes `pending_approval` when the target role is running
|
|
467
485
|
- user opens `Messages`
|
|
468
486
|
- message rows show sequence, timestamp, status, body preview, path, and `Copy`
|
|
487
|
+
- `Mark All Done` marks open message records as `acknowledged` after the user manually handled stuck messages
|
|
469
488
|
- user decides whether to copy or manually act on the message
|
|
470
489
|
- VCM does not write to the target terminal or submit Enter
|
|
490
|
+
- VCM does not clear the source route file until the user marks it done or VCM later dispatches it in auto mode
|
|
471
491
|
|
|
472
492
|
Auto mode:
|
|
473
493
|
|
|
474
|
-
- if target role is
|
|
475
|
-
-
|
|
476
|
-
-
|
|
477
|
-
-
|
|
478
|
-
-
|
|
479
|
-
-
|
|
480
|
-
-
|
|
481
|
-
|
|
494
|
+
- if the target role is idle and has no active delivered message, VCM writes a `[VCM MESSAGE]` envelope to that role's embedded terminal and submits Enter
|
|
495
|
+
- terminal write success stores a durable message snapshot and marks the delivery `submitted`
|
|
496
|
+
- after VCM successfully submits the message to Claude Code, VCM archives the body in message history and clears the source route file
|
|
497
|
+
- if the target role is not running, is busy, or terminal submission fails, VCM leaves the route file non-empty so it remains pending
|
|
498
|
+
- when VCM dispatches a message, the GUI switches to the target role tab so the user can watch execution
|
|
499
|
+
- the target role answers by writing its own route file back to the next role and then ending its turn
|
|
500
|
+
- `Mark All Done` is a manual recovery action for stuck orchestration. It marks open message records as `acknowledged` and may clear route files only after the user confirms the pending file contents were manually handled.
|
|
501
|
+
|
|
502
|
+
VCM Harness injects Claude Code hooks into `.claude/settings.json`:
|
|
503
|
+
|
|
504
|
+
- `Stop`: posts directly to the VCM backend, marks the role idle, and triggers pending route-file dispatch
|
|
505
|
+
|
|
506
|
+
VCM does not need `UserPromptSubmit` for message delivery in this design. Role activity becomes running when VCM submits user or message input to the embedded terminal, and returns to idle on `Stop`.
|
|
507
|
+
|
|
508
|
+
The injected role rules require asynchronous file messaging: after writing or updating a route file, the role must end the current Claude Code turn and wait for VCM to deliver a later reply. Roles must not poll files, start shell loops, or keep the turn open waiting for another role to answer, and they must not use Claude Code Task/Subagent for VCM role delegation.
|
|
482
509
|
|
|
483
|
-
|
|
510
|
+
There is no `vcmctl` in the target design. The only hook entrypoint is direct HTTP from Claude Code hooks to the local VCM backend.
|
|
484
511
|
|
|
485
512
|
## 13. Translation
|
|
486
513
|
|
|
@@ -618,6 +645,7 @@ Task worktree local files:
|
|
|
618
645
|
.claude/worktrees/<task>/.ai/vcm/orchestration/<task>.json
|
|
619
646
|
.claude/worktrees/<task>/.ai/vcm/translation/<task>/
|
|
620
647
|
.claude/worktrees/<task>/.ai/vcm/handoffs/
|
|
648
|
+
.claude/worktrees/<task>/.ai/vcm/handoffs/messages/<from-role>-<to-role>.md
|
|
621
649
|
```
|
|
622
650
|
|
|
623
651
|
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/`. Because `.ai/vcm/handoffs/` has no task-name segment, VCM allows only one active inline task in a connected repo.
|
|
@@ -633,7 +661,6 @@ External Claude transcripts:
|
|
|
633
661
|
Published npm packages must include built output:
|
|
634
662
|
|
|
635
663
|
- `dist/main.js`
|
|
636
|
-
- `dist/cli/vcmctl.js`
|
|
637
664
|
- backend route/service/template output in `dist/`
|
|
638
665
|
- frontend static assets in `dist-frontend/`
|
|
639
666
|
- `README.md`
|
|
@@ -659,10 +686,10 @@ VCM V1 is successful when:
|
|
|
659
686
|
- Switching roles never loses the embedded terminal.
|
|
660
687
|
- Restart creates a fresh Claude session; Resume reconnects to the persisted one.
|
|
661
688
|
- Permission modes are reflected in the Claude command.
|
|
662
|
-
-
|
|
663
|
-
- Manual orchestration lets the user inspect
|
|
664
|
-
- Auto orchestration can deliver
|
|
665
|
-
- Auto orchestration switches to the target role tab when a
|
|
689
|
+
- Roles can route messages by writing fixed route files under `.ai/vcm/handoffs/messages/`.
|
|
690
|
+
- Manual orchestration lets the user inspect pending route-file messages without auto-submitting Enter.
|
|
691
|
+
- Auto orchestration can deliver pending route-file messages to idle running target roles.
|
|
692
|
+
- Auto orchestration switches to the target role tab when VCM submits a route-file message.
|
|
666
693
|
- Round completion detection waits for the final role in a chained conversation and can alert with prompt plus sound.
|
|
667
694
|
- Translation settings save to `~/.vcm/settings.json`.
|
|
668
695
|
- Translation reads Claude transcript JSONL reliably after start, resume, and restart.
|
|
@@ -69,7 +69,6 @@ Main state lives in `App`:
|
|
|
69
69
|
- task list
|
|
70
70
|
- active task
|
|
71
71
|
- active role
|
|
72
|
-
- active workflow report
|
|
73
72
|
- active messages
|
|
74
73
|
- active orchestration state
|
|
75
74
|
- task-local event list
|
|
@@ -93,8 +92,7 @@ Responsibilities:
|
|
|
93
92
|
- Render collapsible sidebar sections.
|
|
94
93
|
- Render repository connect form.
|
|
95
94
|
- Render repository summary.
|
|
96
|
-
- Render
|
|
97
|
-
- Render settings section with Theme, Round alert, Messages, and Events.
|
|
95
|
+
- Render settings section with Theme, Round alert, Try alert, Messages, and Events.
|
|
98
96
|
- Render harness status/actions.
|
|
99
97
|
- 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
98
|
- Render task list.
|
|
@@ -115,10 +113,10 @@ Responsibilities:
|
|
|
115
113
|
- Render compact header with task title, branch, immutable worktree path, role tabs, Refresh, and red `Close Task`.
|
|
116
114
|
- Hold per-role permission mode selection.
|
|
117
115
|
- Hold task orchestration state and pass its on/off control to the active role console.
|
|
118
|
-
- Detect newly
|
|
116
|
+
- Detect newly submitted auto-orchestration messages from VCM dispatch and switch the active role tab to the target role.
|
|
119
117
|
- Emit task round state to `App` so completion alerts can be deduplicated and displayed.
|
|
120
118
|
- Render one `SessionConsole` per role but only show the active role.
|
|
121
|
-
- Emit
|
|
119
|
+
- Emit messages/orchestration/events back to `App` so sidebar stays synchronized.
|
|
122
120
|
|
|
123
121
|
### SessionConsole
|
|
124
122
|
|
|
@@ -434,9 +432,9 @@ Artifact checks are simple V1 checks:
|
|
|
434
432
|
- placeholder / incomplete
|
|
435
433
|
- ok
|
|
436
434
|
|
|
437
|
-
They are used for
|
|
435
|
+
They are used for missing/incomplete artifact warnings, not content quality judgment.
|
|
438
436
|
|
|
439
|
-
## 8.
|
|
437
|
+
## 8. Task Status Report
|
|
440
438
|
|
|
441
439
|
File:
|
|
442
440
|
|
|
@@ -448,21 +446,7 @@ Endpoint:
|
|
|
448
446
|
GET /api/tasks/:taskSlug/status
|
|
449
447
|
```
|
|
450
448
|
|
|
451
|
-
The
|
|
452
|
-
|
|
453
|
-
```text
|
|
454
|
-
architecture-plan -> implementation -> review -> docs-sync -> final-acceptance
|
|
455
|
-
```
|
|
456
|
-
|
|
457
|
-
Step readiness:
|
|
458
|
-
|
|
459
|
-
- Architecture is ready until `architecture-plan.md` is ok.
|
|
460
|
-
- Implementation is blocked until architecture is ok.
|
|
461
|
-
- Review is blocked until `implementation-log.md` and `validation-log.md` are ok.
|
|
462
|
-
- Docs Sync is blocked until `review-report.md` is ok.
|
|
463
|
-
- PM Final is blocked until `docs-sync-report.md` is ok.
|
|
464
|
-
|
|
465
|
-
The report is displayed in the sidebar `Workflow` section.
|
|
449
|
+
The status report returns the task record, role sessions, artifact checks, and warnings. VCM no longer computes or renders a Workflow panel; role sequencing is guided by the injected Claude rules and PM-mediated messages.
|
|
466
450
|
|
|
467
451
|
## 9. Session Runtime
|
|
468
452
|
|
|
@@ -569,45 +553,55 @@ Files:
|
|
|
569
553
|
|
|
570
554
|
- `src/backend/services/message-service.ts`
|
|
571
555
|
- `src/backend/templates/message-envelope.ts`
|
|
572
|
-
- `src/cli/vcmctl.ts`
|
|
573
556
|
|
|
574
557
|
State:
|
|
575
558
|
|
|
576
559
|
```text
|
|
577
560
|
<taskRepoRoot>/.ai/vcm/messages/<task>.jsonl
|
|
578
561
|
<taskRepoRoot>/.ai/vcm/orchestration/<task>.json
|
|
579
|
-
<taskRepoRoot>/.ai/vcm/handoffs/messages/<
|
|
562
|
+
<taskRepoRoot>/.ai/vcm/handoffs/messages/<from-role>-<to-role>.md
|
|
580
563
|
```
|
|
581
564
|
|
|
582
565
|
Policy:
|
|
583
566
|
|
|
584
|
-
-
|
|
585
|
-
-
|
|
586
|
-
-
|
|
567
|
+
- Roles never call a VCM CLI to send messages.
|
|
568
|
+
- A role writes or updates exactly one route file for each directed target role.
|
|
569
|
+
- File name format is `<from-role>-<to-role>.md`; the filename is the authoritative route.
|
|
570
|
+
- Blank route files are not pending.
|
|
571
|
+
- Non-empty route files are pending and are dispatched only by VCM.
|
|
572
|
+
- Optional YAML frontmatter may provide message type and metadata, but cannot override the route.
|
|
573
|
+
- PM-to-role and role-to-PM routes are the default policy. Peer route files are supported only when the task design explicitly allows them.
|
|
587
574
|
|
|
588
575
|
Manual mode:
|
|
589
576
|
|
|
590
577
|
```text
|
|
591
|
-
|
|
578
|
+
role writes route file -> Stop hook -> VCM records pending snapshot -> Messages modal -> Copy/manual action
|
|
592
579
|
```
|
|
593
580
|
|
|
594
|
-
The current GUI shows sequence, timestamp, status,
|
|
581
|
+
The current GUI shows sequence, timestamp, status, route file path, body preview, `Copy`, and `Mark All Done`. VCM leaves the route file non-empty until the user confirms the pending content was handled or auto mode later dispatches it.
|
|
595
582
|
|
|
596
583
|
Auto mode:
|
|
597
584
|
|
|
598
585
|
```text
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
target
|
|
586
|
+
role writes route file
|
|
587
|
+
Stop hook -> VCM scans pending route files
|
|
588
|
+
target idle and running -> VCM writes envelope + Enter -> submitted
|
|
589
|
+
submitted -> VCM archives body -> clears source route file
|
|
590
|
+
target busy/unavailable/failure -> source route file remains non-empty
|
|
591
|
+
target Stop hook -> VCM scans again and may deliver next pending route file
|
|
602
592
|
```
|
|
603
593
|
|
|
604
|
-
The backend pastes a `[VCM MESSAGE]` envelope into the target terminal, then sends Enter as a separate terminal input event.
|
|
594
|
+
The backend pastes a `[VCM MESSAGE]` envelope into the target terminal, then sends Enter as a separate terminal input event. A successful terminal submit is the delivery point for this design. VCM snapshots the message body before clearing the source route file so the message history remains auditable. Delivery is serialized per target role; VCM never sends two pending route files into the same target role during one scan.
|
|
595
|
+
|
|
596
|
+
VCM Harness owns Claude Code hook injection through `.claude/settings.json`. The target design injects only `Stop`. The hook posts directly to a local VCM backend endpoint and does not use `vcmctl`. `Stop` switches the role activity badge to `idle` and triggers a pending route-file scan. VCM marks a role `running` when it submits user input or a VCM message to that embedded terminal. VCM does not use Claude Code Subagent hooks for role delegation.
|
|
597
|
+
|
|
598
|
+
`Mark All Done` is a manual recovery action for stuck orchestration. It appends `acknowledged` snapshots for open messages and, after user confirmation, clears pending route files that the user already handled manually.
|
|
605
599
|
|
|
606
600
|
The message service also serializes message mutations per task inside the VCM process so concurrent API calls cannot bypass the per-role in-flight check.
|
|
607
601
|
|
|
608
|
-
The backend
|
|
602
|
+
The backend should not keep compatibility-only message command paths after this migration. Removing `vcmctl` is part of the target simplification.
|
|
609
603
|
|
|
610
|
-
Messages and orchestration snapshots are task runtime state under `taskRepoRoot/.ai/vcm`.
|
|
604
|
+
Messages and orchestration snapshots are task runtime state under `taskRepoRoot/.ai/vcm`. Pending route files live in the task worktree handoff directory and are cleared after successful VCM submission.
|
|
611
605
|
|
|
612
606
|
## 12. Round Completion Architecture
|
|
613
607
|
|
|
@@ -623,28 +617,29 @@ API:
|
|
|
623
617
|
GET /api/tasks/:taskSlug/round
|
|
624
618
|
```
|
|
625
619
|
|
|
626
|
-
The round service
|
|
620
|
+
The round service reads hook-driven role activity from `RoleSessionRecord`. It does not use transcript tailing as the source of truth for round completion.
|
|
627
621
|
|
|
628
622
|
- `unknown`
|
|
629
|
-
- `answering`
|
|
630
|
-
- `using_tools`
|
|
631
|
-
- `waiting_user`
|
|
632
|
-
- `abnormal`
|
|
633
623
|
- `idle`
|
|
624
|
+
- `answering`
|
|
634
625
|
|
|
635
|
-
|
|
626
|
+
Mapping:
|
|
627
|
+
|
|
628
|
+
- VCM terminal submit updates the session to `activityStatus: "running"` and the round role state to `answering`
|
|
629
|
+
- `Stop` updates the session to `activityStatus: "idle"`, records `lastStopAt`, and the round role state becomes `idle`
|
|
636
630
|
|
|
637
631
|
Task-level completion:
|
|
638
632
|
|
|
639
|
-
- If a message is currently `
|
|
640
|
-
- In a PM -> role -> PM chain, completion follows the newest
|
|
633
|
+
- If a message is currently `submitted`, the latest such message defines the round target.
|
|
634
|
+
- In a PM -> role -> PM chain, completion follows the newest active message, so the round completes after PM emits hook `Stop` for the final response.
|
|
641
635
|
- Queued or pending messages prevent completion.
|
|
642
|
-
- If no VCM message is in the round, the latest direct role
|
|
636
|
+
- If no VCM message is in the round, the latest direct role `Stop` can still produce a completion state.
|
|
643
637
|
|
|
644
638
|
Frontend behavior:
|
|
645
639
|
|
|
646
640
|
- `TaskWorkspace` polls the round endpoint with the other task state.
|
|
647
641
|
- `App` stores the sidebar `Round alert` preference in `~/.vcm/settings.json`.
|
|
642
|
+
- `Try alert` is frontend-only and calls the same round completion notice/sound path without persisting any setting.
|
|
648
643
|
- `App` deduplicates `completionId`, then shows a small `Round complete` prompt and plays a short Web Audio tone when alerts are enabled.
|
|
649
644
|
|
|
650
645
|
## 13. Role Command Compatibility
|
|
@@ -675,7 +670,7 @@ The dispatcher:
|
|
|
675
670
|
4. Resolves primary command path `role-commands/<role>.md`, with legacy fallback `<role>-command.md`.
|
|
676
671
|
5. Pastes `Please read and execute the role command at: <path>` to the target terminal, then sends Enter as a separate terminal input event.
|
|
677
672
|
|
|
678
|
-
This is
|
|
673
|
+
This is an obsolete compatibility path and should be removed when route-file messaging lands. The preferred V1 coordination path is VCM-dispatched route files under `.ai/vcm/handoffs/messages/`.
|
|
679
674
|
|
|
680
675
|
## 14. Harness Service
|
|
681
676
|
|
|
@@ -688,6 +683,7 @@ Harness files:
|
|
|
688
683
|
```text
|
|
689
684
|
CLAUDE.md
|
|
690
685
|
.gitignore
|
|
686
|
+
.claude/settings.json
|
|
691
687
|
.claude/agents/project-manager.md
|
|
692
688
|
.claude/agents/architect.md
|
|
693
689
|
.claude/agents/coder.md
|
|
@@ -711,6 +707,8 @@ Managed block:
|
|
|
711
707
|
# VCM:END
|
|
712
708
|
```
|
|
713
709
|
|
|
710
|
+
`.claude/settings.json` is JSON-merged by the harness. VCM preserves existing settings and adds a `Stop` hook that posts directly to the local VCM backend using the session-provided VCM API URL, task slug, role, and Claude session id. The hook must not call `vcmctl`.
|
|
711
|
+
|
|
714
712
|
The service:
|
|
715
713
|
|
|
716
714
|
- checks whether files exist
|
|
@@ -890,14 +888,17 @@ Messages:
|
|
|
890
888
|
|
|
891
889
|
```text
|
|
892
890
|
GET /api/tasks/:taskSlug/messages
|
|
893
|
-
|
|
894
|
-
POST /api/tasks/:taskSlug/messages
|
|
895
|
-
POST /api/tasks/:taskSlug/messages
|
|
896
|
-
POST /api/tasks/:taskSlug/messages/:messageId/reject
|
|
891
|
+
GET /api/tasks/:taskSlug/messages/pending-route-files
|
|
892
|
+
POST /api/tasks/:taskSlug/messages/scan
|
|
893
|
+
POST /api/tasks/:taskSlug/messages/mark-all-done
|
|
897
894
|
GET /api/tasks/:taskSlug/orchestration
|
|
898
895
|
PUT /api/tasks/:taskSlug/orchestration
|
|
899
|
-
|
|
900
|
-
|
|
896
|
+
```
|
|
897
|
+
|
|
898
|
+
Claude Code hooks:
|
|
899
|
+
|
|
900
|
+
```text
|
|
901
|
+
POST /api/hooks/claude-code/stop
|
|
901
902
|
```
|
|
902
903
|
|
|
903
904
|
Round:
|
|
@@ -972,7 +973,6 @@ Fastify error handler returns:
|
|
|
972
973
|
Bins:
|
|
973
974
|
|
|
974
975
|
- `vcm` -> `dist/main.js`
|
|
975
|
-
- `vcmctl` -> `dist/cli/vcmctl.js`
|
|
976
976
|
|
|
977
977
|
Important scripts:
|
|
978
978
|
|
|
@@ -1002,6 +1002,6 @@ Current boundaries:
|
|
|
1002
1002
|
- No branch switching for an existing task.
|
|
1003
1003
|
- No main-page artifact inspector.
|
|
1004
1004
|
- No raw PTY output translation.
|
|
1005
|
-
- No hard
|
|
1005
|
+
- No computed Workflow panel or hard gate enforcement.
|
|
1006
1006
|
- No durable backend event log for the sidebar Events modal; current events are frontend runtime events for the active task.
|
|
1007
1007
|
- No hosted multi-user collaboration.
|