vibe-coding-master 0.3.0 → 0.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -7
- package/dist/backend/adapters/claude-adapter.js +4 -1
- package/dist/backend/api/codex-hook-routes.js +9 -0
- package/dist/backend/api/codex-review-routes.js +4 -0
- package/dist/backend/api/translation-routes.js +2 -2
- package/dist/backend/cli/install-vcm-harness.js +14 -1
- package/dist/backend/gateway/gateway-service.js +4 -3
- package/dist/backend/server.js +10 -0
- package/dist/backend/services/app-settings-service.js +12 -4
- package/dist/backend/services/artifact-service.js +2 -1
- package/dist/backend/services/claude-hook-service.js +3 -3
- package/dist/backend/services/codex-hook-service.js +87 -0
- package/dist/backend/services/codex-review-service.js +145 -60
- package/dist/backend/services/harness-service.js +28 -1
- package/dist/backend/services/message-service.js +8 -7
- package/dist/backend/services/project-service.js +2 -2
- package/dist/backend/services/round-service.js +29 -25
- package/dist/backend/services/session-service.js +141 -12
- package/dist/backend/templates/handoff.js +10 -0
- package/dist/backend/templates/harness/architect-agent.js +8 -4
- package/dist/backend/templates/harness/claude-root.js +1 -1
- package/dist/backend/templates/harness/coder-agent.js +1 -1
- package/dist/backend/templates/harness/codex-review.js +41 -6
- package/dist/backend/templates/harness/reviewer-agent.js +1 -0
- package/dist/shared/constants.js +15 -1
- package/dist/shared/types/app-settings.js +4 -3
- package/dist/shared/types/codex-hook.js +1 -0
- package/dist/shared/types/session.js +44 -0
- package/dist/shared/validation/artifact-check.js +1 -0
- package/dist-frontend/assets/index-BavJjWQY.js +92 -0
- package/dist-frontend/assets/index-CR1EOe-w.css +32 -0
- package/dist-frontend/index.html +2 -2
- package/docs/ARCHITECTURE.md +1 -0
- package/docs/TESTING.md +82 -0
- package/docs/cc-best-practices.md +1 -0
- package/docs/codex-review-gates.md +88 -45
- package/docs/full-harness-baseline.md +1 -1
- package/docs/gateway-design.md +5 -4
- package/docs/known-issues.md +1 -0
- package/docs/product-design.md +28 -11
- package/docs/vcm-cc-best-practices.md +15 -5
- package/package.json +1 -1
- package/dist-frontend/assets/index-C9l94uxA.js +0 -92
- package/dist-frontend/assets/index-D6jWo6Jd.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;display:flex;flex-direction:column;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{display:flex;flex:1;min-width:0;min-height:0}.project-dashboard{display:flex;flex:1;flex-direction:column;width:100%;min-height:100%}.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{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,.gateway-panel,.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}.connected-repo-actions{display:flex;align-items:center;gap:8px;margin-top:10px}.connected-repo-actions button{min-height:30px}.gateway-actions{display:grid;gap:8px;margin-top:10px}.gateway-actions button{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:8px;align-items:center;width:100%;text-align:left}.gateway-actions .settings-toggle.is-active{border-color:#2f6f73;background:#e8f1ef}.gateway-qr{display:grid;gap:6px;margin-top:10px}.gateway-qr img{width:100%;max-width:180px;border:1px solid #d3c9b8;border-radius:6px;background:#fff;padding:6px}.gateway-qr code{overflow-wrap:anywhere;font-size:11px}.warnings,.error-banner{border:1px solid #c87b54;background:#fff4ed;color:#6f3218;border-radius:6px;padding:10px 12px}.flow-pause-alert-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:100;display:grid;place-items:center;background:#1f242b85;padding:20px}.flow-pause-alert{display:grid;gap:12px;width:min(460px,100%);border:1px solid #2f6f73;border-radius:8px;background:#e8f4f2;color:#123f43;box-shadow:0 28px 72px #1f242b47;padding:22px}.flow-pause-alert-kicker{margin:0;color:#2f6f73;font-size:12px;font-weight:700;text-transform:uppercase}.flow-pause-alert h2{margin:0;font-size:24px;line-height:1.15}.flow-pause-alert p{margin:0;font-size:14px;line-height:1.5}.flow-pause-alert-hint{color:#49666a}.flow-pause-alert button{justify-self:end;min-width:110px;border:1px solid #2f6f73;background:#2f6f73;color:#fffdf8}.flow-pause-alert button:hover{background:#245c60}.warnings{margin:12px 0 0;padding-left:26px;font-size:13px}.harness-panel{display:grid;gap:10px}.harness-stage{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-title{margin:0;font-size:12px}.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}.harness-bootstrap-session{display:grid;gap:8px;border:1px solid #e0d6c7;border-radius:6px;padding:8px;background:#f8f7f2;font-size:12px}.harness-bootstrap-session>div:first-child{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:8px;align-items:center}.harness-bootstrap-session span:first-child{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.harness-bootstrap-modal{position:fixed;top:0;right:0;bottom:0;left:0;z-index:80;display:grid;grid-template-columns:minmax(0,1fr);grid-template-rows:minmax(0,1fr);background:#1f242b94;padding:14px}.harness-bootstrap-modal-surface{min-width:0;min-height:0;display:grid;grid-template-rows:auto minmax(0,1fr);gap:10px;border:1px solid #b9b0a1;border-radius:8px;background:#fffdf8;box-shadow:0 22px 64px #1f242b47;padding:10px}.harness-bootstrap-modal-header{display:flex;gap:12px;align-items:center;justify-content:space-between;min-width:0}.harness-bootstrap-modal-header p{max-width:min(720px,70vw);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.harness-bootstrap-modal-actions{display:flex;flex-wrap:wrap;gap:8px;align-items:center;justify-content:flex-end}.harness-bootstrap-terminal{min-width:0;min-height:0;display:grid}.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}.settings-select-row{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:8px;align-items:center;width:100%;font-size:13px;color:#5f6a6c}.settings-select-row select{min-height:30px;border:1px solid #b9b0a1;border-radius:6px;background:#fffdf8;color:#202326}.task-status-dock{display:grid;gap:10px;margin-top:auto;border-top:1px solid #d3c9b8;padding-top:10px}.task-status-dock-title,.current-round-title{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:8px;align-items:center}.task-status-dock-title strong{overflow:hidden;font-size:13px;line-height:1.25;text-overflow:ellipsis;white-space:nowrap}.task-status-stats{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:6px;margin:0}.task-status-stats div,.current-round-status{min-width:0;border:1px solid #e0d6c7;border-radius:6px;background:#fffdfa}.task-status-stats div{padding:6px 7px}.task-status-stats dt{color:#6c6255;font-size:10px;font-weight:700;text-transform:uppercase}.task-status-stats dd{margin:0;overflow:hidden;color:#1f242b;font-size:12px;font-weight:750;text-overflow:ellipsis;white-space:nowrap}.current-round-status{display:grid;gap:8px;padding:8px}.current-round-title span:first-child{color:#3a4647;font-size:12px;font-weight:750}.workspace-header{display:grid;grid-template-columns:minmax(120px,max-content) minmax(420px,1fr) auto;gap:10px;align-items:center;margin-bottom:6px}.workspace-title-line{display:flex;min-width:0}.workspace-title-line h1{margin-bottom:0;font-size:18px;line-height:1.15}.workspace-header-actions{display:flex;gap:8px;align-items:center;justify-content:flex-end;min-width:max-content}.role-tabs{display:grid;grid-template-columns:repeat(auto-fit,minmax(120px,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:flex-start;margin:0 0 8px}.session-option-field{display:grid;grid-template-columns:auto minmax(180px,260px);gap:8px;align-items:center;width:fit-content;max-width:100%}.model-field{grid-template-columns:auto minmax(190px,260px)}.effort-field{grid-template-columns:auto minmax(120px,160px)}.session-option-field span{color:#5f6a6c;font-size:13px;font-weight:650}.session-option-field small{display:block;color:#7b8587;font-size:11px;font-weight:500;line-height:1.2}.session-option-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;margin-left:auto;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-conversation-boundary{display:grid;grid-template-columns:minmax(18px,1fr) auto auto auto minmax(18px,1fr);gap:8px;align-items:center;color:#8b949e;font-family:Menlo,Monaco,Consolas,monospace;font-size:12px;line-height:1.4;white-space:nowrap}.translation-boundary-dash{min-width:0;border-top:1px dashed #3a4149}.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}.gateway-qr-modal{display:grid;grid-template-rows:auto minmax(0,1fr) auto;gap:14px;width:min(520px,100%);max-height:min(720px,92vh);overflow:auto;border:1px solid #d6d0c6;border-radius:8px;background:#fffdf8;padding:16px}.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,.gateway-qr-modal header,.message-modal header,.event-modal header,.translation-settings-modal footer,.gateway-qr-modal footer{display:flex;gap:8px;align-items:center;justify-content:space-between}.gateway-qr-modal h2,.gateway-qr-modal p{margin-bottom:0}.gateway-qr-modal-body{display:grid;gap:14px;justify-items:center}.gateway-qr-code-frame{display:grid;place-items:center;width:min(360px,100%);aspect-ratio:1;border:1px solid #d6d0c6;border-radius:8px;background:#fff;padding:18px}.gateway-qr-code-frame img{display:block;width:100%;height:auto}.gateway-qr-placeholder{color:#667071;text-align:center}.gateway-qr-meta{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px;width:100%;margin:0}.gateway-qr-meta div{min-width:0;border:1px solid #ece5d9;border-radius:6px;padding:8px}.gateway-qr-meta dt{color:#6c6255;font-size:11px;font-weight:700;text-transform:uppercase}.gateway-qr-meta dd{margin:0;overflow-wrap:anywhere;font-size:13px}.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-active,.status-running,.status-ok{border-color:#6ea77e;background:#e6f3e9;color:#245334}.status-created,.status-idle,.status-disabled{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-stopped,.status-resumable,.status-skipped,.status-overridden,.status-not_required{border-color:#7b98b8;background:#e9f0f8;color:#2e4e70}.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}.session-option-field{grid-template-columns:1fr;width:100%}}.harness-bootstrap-terminal .terminal-frame{height:100%;min-height:0}: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] .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] .gateway-qr-modal,:root[data-theme=dark] .message-modal,:root[data-theme=dark] .event-modal{border-color:#30363d;background:#11161d}:root[data-theme=dark] .gateway-qr-code-frame,:root[data-theme=dark] .gateway-qr-meta div{border-color:#30363d;background:#0d1117}:root[data-theme=dark] .gateway-qr-code-frame{background:#f6f8fa}:root[data-theme=dark] .gateway-qr-meta dt,:root[data-theme=dark] .gateway-qr-placeholder{color:#8b949e}: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] .session-option-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] .session-option-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] .flow-pause-alert-backdrop{background:#010409b8}:root[data-theme=dark] .flow-pause-alert{border-color:#56d4dd;background:#10262b;color:#d6fbff;box-shadow:0 28px 72px #0104099e}:root[data-theme=dark] .flow-pause-alert-kicker,:root[data-theme=dark] .flow-pause-alert-hint{color:#9debf2}:root[data-theme=dark] .flow-pause-alert button{border-color:#56d4dd;background:#56d4dd;color:#061114}:root[data-theme=dark] .flow-pause-alert button:hover{background:#84f3fa}:root[data-theme=dark] .harness-file-list li,:root[data-theme=dark] .harness-changes,:root[data-theme=dark] .harness-result,:root[data-theme=dark] .harness-bootstrap-session,:root[data-theme=dark] .gateway-qr img,:root[data-theme=dark] .task-create-preview,:root[data-theme=dark] .task-status-stats div,:root[data-theme=dark] .current-round-status,:root[data-theme=dark] .message-item{border-color:#30363d;background:#0d1117}:root[data-theme=dark] .harness-bootstrap-modal{background:#010409b8}:root[data-theme=dark] .harness-bootstrap-modal-surface{border-color:#30363d;background:#0d1117;box-shadow:0 22px 64px #0104099e}:root[data-theme=dark] .task-create-option{color:#e6edf3}:root[data-theme=dark] .task-status-dock{border-color:#30363d}:root[data-theme=dark] .task-create-preview span{color:#7ee787}:root[data-theme=dark] .task-status-stats dt{color:#8b949e}:root[data-theme=dark] .task-status-stats dd,:root[data-theme=dark] .current-round-title span:first-child{color:#e6edf3}:root[data-theme=dark] .message-sequence{color:#f0f6fc}: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] .gateway-actions .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] .session-option-field select,:root[data-theme=dark] .settings-select-row 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] .settings-select-row{color:#b7c0ca}: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-active,:root[data-theme=dark] .status-running,:root[data-theme=dark] .status-ok{border-color:#3fb950;background:#12261a;color:#aff5b4}:root[data-theme=dark] .status-created,:root[data-theme=dark] .status-idle,:root[data-theme=dark] .status-disabled{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-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-stopped,:root[data-theme=dark] .status-resumable,:root[data-theme=dark] .status-skipped,:root[data-theme=dark] .status-overridden,:root[data-theme=dark] .status-not_required,: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-BavJjWQY.js"></script>
|
|
8
|
+
<link rel="stylesheet" crossorigin href="/assets/index-CR1EOe-w.css">
|
|
9
9
|
</head>
|
|
10
10
|
<body>
|
|
11
11
|
<div id="root"></div>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# Architecture
|
package/docs/TESTING.md
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# Testing
|
|
2
|
+
|
|
3
|
+
Validation strategy for `vibe-coding-master` (TypeScript/Node app). Reviewer-owned.
|
|
4
|
+
|
|
5
|
+
## Validation Levels & Commands
|
|
6
|
+
|
|
7
|
+
| Level | Scope | Command |
|
|
8
|
+
| --- | --- | --- |
|
|
9
|
+
| L0 | format / typecheck | `npm run typecheck` (`tsc -p tsconfig.json --noEmit && tsc -p tsconfig.node.json --noEmit`) |
|
|
10
|
+
| L1/L2 | unit + module/integration tests | `npm run test` (vitest, runs `tests/unit/**` and `tests/integration/**`) |
|
|
11
|
+
| L3 | smoke / E2E (browser) | `npm run e2e` (Playwright) |
|
|
12
|
+
| L4 | full regression / release | `npm run prepack` (build + `verify:package`) + full `npm run test` + `npm run e2e` |
|
|
13
|
+
|
|
14
|
+
Targeted run: `npx vitest run <path/to/test.ts>`.
|
|
15
|
+
|
|
16
|
+
### Test environment note
|
|
17
|
+
|
|
18
|
+
`vitest.config.ts` runs in `environment: "node"` (no jsdom). Frontend tests are
|
|
19
|
+
therefore either pure-helper tests or component tests rendered with
|
|
20
|
+
`react-dom/server` `renderToStaticMarkup` (static HTML assertions), not DOM/event
|
|
21
|
+
tests. Component modules that load browser globals at import time (e.g. the
|
|
22
|
+
xterm-backed `terminal/xterm-view`) must be stubbed with `vi.mock` before the
|
|
23
|
+
component under test is imported.
|
|
24
|
+
|
|
25
|
+
## Required prerequisite: build before full `npm run test`
|
|
26
|
+
|
|
27
|
+
`tests/unit/backend/harness-templates-sync.test.ts` spawns the real harness
|
|
28
|
+
installer (`scripts/install-vcm-harness.mjs`), which runs the compiled CLI at
|
|
29
|
+
`dist/backend/cli/install-vcm-harness.js`, falling back to the TypeScript source
|
|
30
|
+
only when the `tsx` binary is present. In a clean checkout with no `dist/` and no
|
|
31
|
+
`node_modules/.bin/tsx`, the installer exits with
|
|
32
|
+
`compiled CLI not found. Run npm run build first.` and this single test fails.
|
|
33
|
+
|
|
34
|
+
**Run `npm run build` before a full `npm run test`** (or before final acceptance).
|
|
35
|
+
All other unit tests run without a build. This is a documented prerequisite, not a
|
|
36
|
+
product defect or known issue.
|
|
37
|
+
|
|
38
|
+
## Final-validation cleanup
|
|
39
|
+
|
|
40
|
+
`npm run build` first runs `npm run clean` (`scripts/clean-build.mjs`), removing
|
|
41
|
+
`dist/` and `dist-frontend/`. Final acceptance therefore runs from a clean state via:
|
|
42
|
+
|
|
43
|
+
```
|
|
44
|
+
npm run build && npm run test
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Do not treat any pre-cleanup test result as final acceptance evidence.
|
|
48
|
+
|
|
49
|
+
## Harness "Fixed install" three-state UI cases
|
|
50
|
+
|
|
51
|
+
Backend derivation — `tests/unit/backend/harness-service.test.ts`:
|
|
52
|
+
|
|
53
|
+
| ID | Scenario | Proves |
|
|
54
|
+
| --- | --- | --- |
|
|
55
|
+
| B1 | fresh repo, all harness files missing | `initialized === false`, `needsApply === true` |
|
|
56
|
+
| B2 | after `applyHarness` | `initialized === true`, `needsApply === false` |
|
|
57
|
+
| B3 | pre-existing non-VCM `CLAUDE.md` (action `insert`) | `initialized === false` |
|
|
58
|
+
| B4 | pre-existing `.claude/settings.json` without VCM hooks (action `update`) | `initialized === false` |
|
|
59
|
+
| B5 | drifted managed block (version 0) | `initialized === true`, `needsApply === true` |
|
|
60
|
+
|
|
61
|
+
Frontend render — `tests/unit/frontend/harness-panel.test.ts`
|
|
62
|
+
(entry: `HarnessPanel`, rendered via `renderToStaticMarkup`, `xterm-view` mocked):
|
|
63
|
+
|
|
64
|
+
| ID | State | Entry / input | Key assertions |
|
|
65
|
+
| --- | --- | --- | --- |
|
|
66
|
+
| F1 | A — not initialized | `initialized:false, needsApply:true` | subtitle "Not initialized"; only `Initialize` button; no Refresh/Update; no "Files to update" list |
|
|
67
|
+
| F2 | B — has updates | `initialized:true, needsApply:true, plannedChanges:[..]` | subtitle "N pending updates"; "Files to update" list with paths; `Update` + `Refresh`; no `Initialize` |
|
|
68
|
+
| F3 | C — up to date | `initialized:true, needsApply:false` | subtitle "Up to date"; `Refresh` only; no `Update`/`Initialize`; no list |
|
|
69
|
+
| F4 | busy | each state with `busy:true` | every fixed-install action button rendered `disabled` |
|
|
70
|
+
|
|
71
|
+
Run: `npx vitest run tests/unit/backend/harness-service.test.ts tests/unit/frontend/harness-panel.test.ts`.
|
|
72
|
+
|
|
73
|
+
## Known testing gaps
|
|
74
|
+
|
|
75
|
+
- No DOM/interaction (click) tests for the frontend: the node test environment uses
|
|
76
|
+
static-markup rendering, so button `onClick` wiring is verified by code review and
|
|
77
|
+
by the backend status-reload behavior, not by simulated events. A jsdom +
|
|
78
|
+
`@testing-library/react` setup would be needed for true interaction coverage and is
|
|
79
|
+
not currently configured.
|
|
80
|
+
- No L3 Playwright smoke was run for this task (UI conditional-rendering change with
|
|
81
|
+
full backend + frontend unit coverage). Reserve E2E for release-level or
|
|
82
|
+
cross-cutting flow changes.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Codex Review Gates
|
|
2
2
|
|
|
3
|
-
Last updated: 2026-06-
|
|
3
|
+
Last updated: 2026-06-14
|
|
4
4
|
|
|
5
5
|
This document defines the Codex Review Gates feature for VCM.
|
|
6
6
|
|
|
@@ -41,7 +41,7 @@ The product outcome is higher task accuracy through earlier detection of:
|
|
|
41
41
|
|
|
42
42
|
The first version should not:
|
|
43
43
|
|
|
44
|
-
- require
|
|
44
|
+
- require every task to start Codex Reviewer manually
|
|
45
45
|
- let Codex edit repository files directly
|
|
46
46
|
- automatically accept, reject, route, or replan a task
|
|
47
47
|
- replace human approval for high-risk decisions
|
|
@@ -85,9 +85,12 @@ review state and asks VCM to start a review when the gate is enabled, required,
|
|
|
85
85
|
and not already approved for the current input.
|
|
86
86
|
|
|
87
87
|
VCM owns execution. When review starts, the VCM flow remains running and enters
|
|
88
|
-
a Codex review stage. VCM
|
|
89
|
-
|
|
90
|
-
and
|
|
88
|
+
a Codex review stage. VCM ensures the long-lived `codex-reviewer` embedded
|
|
89
|
+
terminal session is running, sends the gate prompt into that session, records
|
|
90
|
+
state, validates the report shape, and calls PM back when review finishes. PM
|
|
91
|
+
then reads the report and continues or routes by gate type. The same Codex
|
|
92
|
+
Reviewer terminal remains available after the gate so the user or PM can
|
|
93
|
+
continue discussing, challenging, or confirming the review result in context.
|
|
91
94
|
Codex execution failure is VCM/tool failure, not `request_changes`; VCM offers
|
|
92
95
|
retry, skip, or override and records the chosen exception state.
|
|
93
96
|
|
|
@@ -97,6 +100,7 @@ PM reaches gate trigger
|
|
|
97
100
|
-> skill checks VCM Codex gate state
|
|
98
101
|
-> skill requests VCM start review
|
|
99
102
|
-> VCM state = codex-review:running
|
|
103
|
+
-> VCM sends gate prompt to Codex Reviewer terminal
|
|
100
104
|
-> Codex Reviewer writes report
|
|
101
105
|
-> VCM records completed / failed / skipped / overridden
|
|
102
106
|
-> VCM emits Codex review callback to PM
|
|
@@ -119,6 +123,7 @@ Recommended inputs:
|
|
|
119
123
|
- original user request
|
|
120
124
|
- project-manager route message or durable task plan when present
|
|
121
125
|
- architecture plan
|
|
126
|
+
- Scaffold Manifest and any architect-created scaffold diff
|
|
122
127
|
- relevant durable architecture docs
|
|
123
128
|
- `docs/TESTING.md` when the plan depends on validation strategy
|
|
124
129
|
- changed file list when architect created scaffolding
|
|
@@ -128,6 +133,8 @@ Codex should review whether:
|
|
|
128
133
|
- the plan matches the user request
|
|
129
134
|
- the architecture boundaries are clear and compatible with the existing repo
|
|
130
135
|
- file responsibilities and public contracts are specific enough for coder
|
|
136
|
+
- the Scaffold Manifest carries task-specific context and coder guidance instead
|
|
137
|
+
of putting that information in source-code comments
|
|
131
138
|
- the plan avoids unnecessary scope expansion
|
|
132
139
|
- risks, dependencies, migrations, permissions, data, and error paths are named
|
|
133
140
|
- acceptance and validation evidence can be produced
|
|
@@ -211,6 +218,8 @@ Codex should review whether:
|
|
|
211
218
|
- the final diff satisfies the user request
|
|
212
219
|
- the implementation contains correctness bugs or behavior regressions
|
|
213
220
|
- the code follows existing project conventions
|
|
221
|
+
- source and test comments contain no task-specific process notes, phase notes,
|
|
222
|
+
current-task rationale, or coder instructions
|
|
214
223
|
- tests and implementation remain aligned
|
|
215
224
|
- durable docs and generated artifacts are consistent with the diff
|
|
216
225
|
- files outside the expected scope are explained
|
|
@@ -308,6 +317,8 @@ role. It should contain:
|
|
|
308
317
|
```text
|
|
309
318
|
.ai/codex/AGENTS.md
|
|
310
319
|
.ai/codex/config.toml
|
|
320
|
+
.ai/codex/.codex/config.toml
|
|
321
|
+
.ai/codex/.codex/hooks.json
|
|
311
322
|
.ai/codex/prompts/architecture-plan-gate.md
|
|
312
323
|
.ai/codex/prompts/validation-adequacy-gate.md
|
|
313
324
|
.ai/codex/prompts/final-diff-gate.md
|
|
@@ -336,6 +347,22 @@ natively discover arbitrary `.ai/codex/config.toml` files the way it discovers
|
|
|
336
347
|
so the VCM Codex adapter reads this file and maps supported keys to the Codex
|
|
337
348
|
CLI invocation.
|
|
338
349
|
|
|
350
|
+
`.ai/codex/.codex/config.toml` and `.ai/codex/.codex/hooks.json` are the
|
|
351
|
+
Codex CLI project-level hook configuration. Because VCM starts Codex with
|
|
352
|
+
`.ai/codex` as the current Codex project, this nested `.codex` directory is
|
|
353
|
+
discovered by the interactive Codex CLI. The config enables hooks, and the
|
|
354
|
+
hooks post `UserPromptSubmit` and `Stop` events to VCM:
|
|
355
|
+
|
|
356
|
+
```text
|
|
357
|
+
POST /api/hooks/codex-reviewer
|
|
358
|
+
POST /api/hooks/codex-reviewer/stop
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
The hook payload records Codex's own session id, transcript path, cwd, and hook
|
|
362
|
+
event name. VCM stores those events on the `codex-reviewer` role session and in
|
|
363
|
+
the shared Round state, so a Codex review keeps the VCM flow running until the
|
|
364
|
+
Codex `Stop` event is observed and the normal settle timer completes.
|
|
365
|
+
|
|
339
366
|
VCM should start Codex from `.ai/codex` so that `.ai/codex/AGENTS.md` is
|
|
340
367
|
discovered naturally. Because the current session root is then `.ai/codex`, the
|
|
341
368
|
permission profile must add the task repository as a profile-defined workspace
|
|
@@ -378,19 +405,25 @@ Implemented files:
|
|
|
378
405
|
|
|
379
406
|
```text
|
|
380
407
|
src/shared/types/codex-review.ts
|
|
408
|
+
src/shared/types/codex-hook.ts
|
|
381
409
|
src/backend/services/codex-review-service.ts
|
|
410
|
+
src/backend/services/codex-hook-service.ts
|
|
382
411
|
src/backend/api/codex-review-routes.ts
|
|
412
|
+
src/backend/api/codex-hook-routes.ts
|
|
383
413
|
```
|
|
384
414
|
|
|
385
415
|
Implemented API:
|
|
386
416
|
|
|
387
417
|
```text
|
|
388
418
|
GET /api/tasks/:taskSlug/codex-review
|
|
419
|
+
PUT /api/tasks/:taskSlug/codex-review/settings
|
|
389
420
|
POST /api/tasks/:taskSlug/codex-review/:gate/request
|
|
390
421
|
POST /api/tasks/:taskSlug/codex-review/:gate/retry
|
|
391
422
|
POST /api/tasks/:taskSlug/codex-review/:gate/skip
|
|
392
423
|
POST /api/tasks/:taskSlug/codex-review/:gate/override
|
|
393
424
|
GET /api/tasks/:taskSlug/codex-review/:gate/report
|
|
425
|
+
POST /api/hooks/codex-reviewer
|
|
426
|
+
POST /api/hooks/codex-reviewer/stop
|
|
394
427
|
```
|
|
395
428
|
|
|
396
429
|
Provider implementations should be swappable:
|
|
@@ -410,52 +443,60 @@ When a review starts, VCM keeps the task flow running in a Codex review stage.
|
|
|
410
443
|
When the provider finishes, VCM emits a Codex review callback to PM with gate,
|
|
411
444
|
status, decision, report path, and any failure or exception metadata.
|
|
412
445
|
|
|
413
|
-
The Codex CLI provider
|
|
414
|
-
|
|
446
|
+
The Codex CLI provider uses the long-lived embedded terminal session, not
|
|
447
|
+
`codex exec`, because VCM needs Codex `UserPromptSubmit` and `Stop` hook events
|
|
448
|
+
and the user may continue discussing the review after the report is written.
|
|
449
|
+
Current implementation shape for a fresh terminal:
|
|
415
450
|
|
|
416
451
|
```bash
|
|
417
|
-
codex
|
|
452
|
+
codex \
|
|
418
453
|
--cd <taskRepoRoot>/.ai/codex \
|
|
419
454
|
--add-dir <taskRepoRoot>/.ai/vcm/codex-reviews \
|
|
420
455
|
--sandbox workspace-write \
|
|
421
456
|
--ask-for-approval never \
|
|
422
|
-
--
|
|
423
|
-
--output-last-message <taskRepoRoot>/.ai/vcm/codex-reviews/logs/<request-id>.last-message.txt \
|
|
457
|
+
--dangerously-bypass-hook-trust \
|
|
424
458
|
--model <model-from-.ai/codex/config.toml> \
|
|
425
|
-
"<
|
|
459
|
+
--config model_reasoning_effort="<effort-from-.ai/codex/config.toml>"
|
|
426
460
|
```
|
|
427
461
|
|
|
428
462
|
Starting from `.ai/codex` causes Codex to load `.ai/codex/AGENTS.md` through
|
|
429
|
-
its normal `AGENTS.md` discovery path
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
463
|
+
its normal `AGENTS.md` discovery path and `.ai/codex/.codex/hooks.json` through
|
|
464
|
+
the Codex project hook path. VCM sends the gate prompt into this terminal,
|
|
465
|
+
validates the report path, request id, and decision before marking a gate
|
|
466
|
+
completed, then callbacks PM. `--ask-for-approval never` and the VCM-owned hook
|
|
467
|
+
trust bypass prevent Codex from pausing at permission or hook trust prompts;
|
|
468
|
+
execution failures are recorded as `failed` so the user can retry, skip, or
|
|
469
|
+
override.
|
|
433
470
|
|
|
434
471
|
## 10. UI Shape
|
|
435
472
|
|
|
436
|
-
Add a `Review Gates`
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
Codex
|
|
458
|
-
|
|
473
|
+
Add a `Codex Review Gates` group to the left sidebar. It is visible for the
|
|
474
|
+
connected active task and contains three independent toggles:
|
|
475
|
+
|
|
476
|
+
- Architecture Plan
|
|
477
|
+
- Validation Adequacy
|
|
478
|
+
- Final Diff
|
|
479
|
+
|
|
480
|
+
All three toggles default to `off`. Turning on any gate writes it into
|
|
481
|
+
`.ai/codex/config.toml` under `[vcm.codex_review].required_gates` and sets
|
|
482
|
+
`enabled = true`. Turning all gates off writes `enabled = false` and
|
|
483
|
+
`required_gates = []`.
|
|
484
|
+
|
|
485
|
+
The task workspace must not show a separate Codex Review Gates panel. The UI
|
|
486
|
+
does not expose manual `Run`, `Run Again`, `Retry`, `Skip`, or `Override`
|
|
487
|
+
buttons for gates; PM triggers reviews through the `vcm-codex-review-gate`
|
|
488
|
+
skill, and VCM handles execution failures through its managed retry / skip /
|
|
489
|
+
override path.
|
|
490
|
+
|
|
491
|
+
When at least one gate toggle is on, or when the task already has a saved Codex
|
|
492
|
+
Reviewer session, the task workspace role tabs include a fifth role, `Codex
|
|
493
|
+
Reviewer`. It uses the same embedded terminal surface as the Claude Code roles,
|
|
494
|
+
but starts Codex CLI from `.ai/codex`, uses Codex model and effort selectors,
|
|
495
|
+
and is not part of PM message routing, auto orchestration, or translation. The
|
|
496
|
+
saved launch template still stores the four Claude Code role settings; when a
|
|
497
|
+
Codex gate is enabled and no task sessions exist yet, One-click start launches
|
|
498
|
+
those four Claude Code roles plus `codex-reviewer` with the Codex Reviewer
|
|
499
|
+
defaults.
|
|
459
500
|
|
|
460
501
|
## 11. Project-Manager Rules
|
|
461
502
|
|
|
@@ -484,16 +525,18 @@ Rules:
|
|
|
484
525
|
|
|
485
526
|
The first implementation is intentionally small:
|
|
486
527
|
|
|
487
|
-
1. Add `.ai/codex/AGENTS.md
|
|
488
|
-
reviewer runtime files.
|
|
528
|
+
1. Add `.ai/codex/AGENTS.md`, `.ai/codex/config.toml`, and
|
|
529
|
+
`.ai/codex/.codex/*` as VCM-managed Codex reviewer runtime files.
|
|
489
530
|
2. Add `vcm-codex-review-gate` as the PM-facing skill / protocol entry.
|
|
490
|
-
3. Add backend APIs to request, run, retry, skip, override, list,
|
|
491
|
-
reports.
|
|
492
|
-
4. Add
|
|
531
|
+
3. Add backend APIs to configure, request, run, retry, skip, override, list,
|
|
532
|
+
and read gate reports.
|
|
533
|
+
4. Add sidebar toggles for the three gate enablement options.
|
|
493
534
|
5. Add project-manager and final-acceptance harness rules that require checking
|
|
494
535
|
Codex gate reports for complex tasks.
|
|
495
|
-
6.
|
|
496
|
-
|
|
536
|
+
6. Add Codex hook endpoints so the fifth role participates in VCM session and
|
|
537
|
+
Round state.
|
|
538
|
+
7. Keep gate triggering PM-driven at first.
|
|
539
|
+
8. Do not automatically route roles from Codex findings in the first version.
|
|
497
540
|
|
|
498
541
|
Later versions can add automatic PM routing, provider selection, stricter
|
|
499
542
|
provider-level read/write policies where supported by Codex CLI, and risk-based
|
|
@@ -81,7 +81,7 @@ These entries match the current `example/rust-layered/.ai/vcm-harness-manifest.j
|
|
|
81
81
|
| Claude settings | `.claude/settings.json` | json-merge | Long-term | VCM owns hook entries matching VCM command markers. |
|
|
82
82
|
| Agent directory | `.claude/agents/` | VCM-created directory | Long-term | Contains the four core VCM role agents. |
|
|
83
83
|
| Core agent | `.claude/agents/project-manager.md` | managed-block | Long-term | Project-manager role rules. |
|
|
84
|
-
| Core agent | `.claude/agents/architect.md` | managed-block | Long-term | Architect role rules: plan document, code scaffolding, Debug Mode, docs sync. |
|
|
84
|
+
| Core agent | `.claude/agents/architect.md` | managed-block | Long-term | Architect role rules: plan document, Scaffold Manifest, code scaffolding, Debug Mode, docs sync. |
|
|
85
85
|
| Core agent | `.claude/agents/coder.md` | managed-block | Long-term | Coder role rules: scaffold implementation, coding standards, baseline unit checks. |
|
|
86
86
|
| Core agent | `.claude/agents/reviewer.md` | managed-block | Long-term | Reviewer role rules: independent validation, TESTING.md strategy, integration/E2E case lists. |
|
|
87
87
|
| Skill directory | `.claude/skills/` | VCM-created directory | Conditional long-term | Keep while repo-local VCM skills are installed. |
|
package/docs/gateway-design.md
CHANGED
|
@@ -163,7 +163,8 @@ Task lifecycle commands:
|
|
|
163
163
|
selects it as the mobile current task, applies the saved launch template, and
|
|
164
164
|
starts the four role sessions (`project-manager`, `architect`, `coder`,
|
|
165
165
|
`reviewer`) through the same one-click-start path as the desktop UI. The saved
|
|
166
|
-
template controls permission mode, model, auto orchestration, and
|
|
166
|
+
template controls permission mode, model, effort, auto orchestration, and
|
|
167
|
+
translation.
|
|
167
168
|
If no template has been saved, VCM uses the default launch template.
|
|
168
169
|
- `/close-task` starts a destructive confirmation flow for the current task.
|
|
169
170
|
Gateway replies with the exact confirmation command.
|
|
@@ -249,7 +250,7 @@ Rules:
|
|
|
249
250
|
-> load saved launch template from app preferences
|
|
250
251
|
-> set orchestration from template
|
|
251
252
|
-> set gateway/desktop translation state from template
|
|
252
|
-
-> start four role sessions with template permission/model
|
|
253
|
+
-> start four role sessions with template permission/model/effort
|
|
253
254
|
-> switch mobile current role to project-manager
|
|
254
255
|
-> reply with task slug, branch, worktree, template summary, and session status
|
|
255
256
|
```
|
|
@@ -584,8 +585,8 @@ Service dependencies:
|
|
|
584
585
|
Task cleanup.
|
|
585
586
|
- `SessionService`: PM session state, Claude session metadata, and role session
|
|
586
587
|
start for launch-template initialization.
|
|
587
|
-
- `AppSettingsService`: saved launch template with permission mode, model,
|
|
588
|
-
orchestration, and translation defaults.
|
|
588
|
+
- `AppSettingsService`: saved launch template with permission mode, model,
|
|
589
|
+
effort, auto orchestration, and translation defaults.
|
|
589
590
|
- `MessageService` / orchestration state service: set the newly created task to
|
|
590
591
|
template auto/manual orchestration mode.
|
|
591
592
|
- `TerminalRuntime`: controlled PM terminal submission.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# Known Issues
|
package/docs/product-design.md
CHANGED
|
@@ -75,7 +75,7 @@ Recommended flow:
|
|
|
75
75
|
|
|
76
76
|
```text
|
|
77
77
|
project-manager
|
|
78
|
-
-> architect architecture plan and code scaffolding
|
|
78
|
+
-> architect architecture plan, Scaffold Manifest, and code scaffolding
|
|
79
79
|
-> coder implementation and baseline unit checks
|
|
80
80
|
-> reviewer independent validation
|
|
81
81
|
-> architect docs sync / architecture drift check
|
|
@@ -101,8 +101,17 @@ final task diff
|
|
|
101
101
|
|
|
102
102
|
Each gate returns `approve` or `request_changes`. PM triggers gates through the
|
|
103
103
|
`vcm-codex-review-gate` skill at the three workflow points; VCM owns the Codex
|
|
104
|
-
Review
|
|
105
|
-
review completes. Codex writes reports under
|
|
104
|
+
Review sidebar toggles, gate state, Codex CLI / adapter execution, and PM
|
|
105
|
+
callback after review completes. Codex writes reports under
|
|
106
|
+
`.ai/vcm/codex-reviews/`. All three gate toggles default to off.
|
|
107
|
+
When any gate is on, or when a Codex Reviewer session already exists, the task
|
|
108
|
+
workspace shows `Codex Reviewer` as a fifth terminal role with Codex model and
|
|
109
|
+
effort selection. VCM sends gate prompts into this long-lived terminal session
|
|
110
|
+
so the review can be challenged or clarified afterward; the role remains
|
|
111
|
+
outside PM routing and Claude Code auto orchestration. Codex Reviewer
|
|
112
|
+
`UserPromptSubmit` and `Stop` hooks post back to VCM from
|
|
113
|
+
`.ai/codex/.codex/hooks.json`, so the fifth role participates in session and
|
|
114
|
+
Round state while a gate is running.
|
|
106
115
|
Architecture-plan findings return to architect, validation-adequacy findings
|
|
107
116
|
return to reviewer, and final-diff findings go to architect first for
|
|
108
117
|
assessment. Codex reviewer role configuration lives under `.ai/codex/`,
|
|
@@ -210,6 +219,7 @@ The project manager must not become the architect, coder, reviewer, or debugger
|
|
|
210
219
|
The architect owns:
|
|
211
220
|
|
|
212
221
|
- architecture plan
|
|
222
|
+
- Scaffold Manifest for task-specific file context and coder guidance
|
|
213
223
|
- module boundaries
|
|
214
224
|
- file responsibilities
|
|
215
225
|
- cross-file callable surfaces and contract comments
|
|
@@ -279,7 +289,7 @@ Sections:
|
|
|
279
289
|
- `New Task`
|
|
280
290
|
- `Tasks`
|
|
281
291
|
|
|
282
|
-
The connected active task also has a bottom status dock. It is not a collapsible sidebar section. It stays at the bottom of the sidebar and shows the active VCM Session title, task status, Session start time, total elapsed time, total Round count, and
|
|
292
|
+
The connected active task also has a bottom status dock. It is not a collapsible sidebar section. It stays at the bottom of the sidebar and shows the active VCM Session title, task status, Session start time, total elapsed time, total Round count, and role active runtime. When the current Round is running, it also shows the Current Round start time, total elapsed time, role active runtime, and Turn count.
|
|
283
293
|
|
|
284
294
|
`Repository Path` layout:
|
|
285
295
|
|
|
@@ -392,13 +402,13 @@ The split should stay close to 50/50 width. Both panes expand vertically to fill
|
|
|
392
402
|
|
|
393
403
|
## 8. Flow Pause Detection
|
|
394
404
|
|
|
395
|
-
VCM detects flow pauses from
|
|
405
|
+
VCM detects flow pauses from role hook events, not from terminal silence, message history, or pending route files. Claude Code roles report through `.claude/settings.json`; Codex Reviewer reports through `.ai/codex/.codex/hooks.json`.
|
|
396
406
|
|
|
397
407
|
Backend role state:
|
|
398
408
|
|
|
399
409
|
- VCM terminal submit: role becomes `running`.
|
|
400
410
|
- `Stop`: role becomes `idle` and records `lastTurnEndedAt`.
|
|
401
|
-
- The role tab and flow pause state both react to Claude Code hook events.
|
|
411
|
+
- The role tab and flow pause state both react to Claude Code and Codex Reviewer hook events.
|
|
402
412
|
|
|
403
413
|
Task-level Round state:
|
|
404
414
|
|
|
@@ -409,8 +419,8 @@ Task-level Round state:
|
|
|
409
419
|
- If no new prompt is accepted before the deadline, the Round becomes `stopped`.
|
|
410
420
|
- The stop transition is timer-driven from the `Stop` event. Round-state reads do not end a Round.
|
|
411
421
|
- Before stopping, VCM checks `.ai/vcm/handoffs/messages`; if a pending route message exists and can be delivered, VCM retries delivery and extends the stop window instead of alerting.
|
|
412
|
-
- The same Round state stores total Round count, Turn count, completed Turn count, and
|
|
413
|
-
- The Current Round dock shows both wall-clock Round duration and
|
|
422
|
+
- The same Round state stores total Round count, Turn count, completed Turn count, and role active runtime. Active runtime is measured only between `UserPromptSubmit` and `Stop`, not during the stop window.
|
|
423
|
+
- The Current Round dock shows both wall-clock Round duration and role active runtime. `Total` is `now - Round.startedAt`; `Role runtime` is the accumulated active runtime across Turns in that Round; `Turn count` is the number of accepted prompts in the Round.
|
|
414
424
|
|
|
415
425
|
The frontend polls this task-level Round state and deduplicates each stopped Round so the same stopped state does not alert on every poll. Flow duration is measured from the first `UserPromptSubmit` to `stoppedAt`, falling back to the last `Stop` when needed. Runs under 2 minutes trigger the weak 3-chime reminder at 1.4 second intervals. Runs at or above 2 minutes trigger the strong alert dialog and repeating sound until confirmation.
|
|
416
426
|
|
|
@@ -550,11 +560,11 @@ Default route policy:
|
|
|
550
560
|
- Peer routes such as `coder-reviewer.md` may exist for explicit task designs, but VCM still serializes delivery per target role.
|
|
551
561
|
- `user` talks to `project-manager` through the normal active terminal or translation composer, not through a route file.
|
|
552
562
|
|
|
553
|
-
Stop-triggered scan:
|
|
563
|
+
Claude Stop-triggered scan:
|
|
554
564
|
|
|
555
565
|
- VCM injects Claude Code `UserPromptSubmit`, `Stop`, and `PermissionRequest` hooks into `.claude/settings.json`.
|
|
556
566
|
- The hooks do not call `vcmctl`; they POST directly to the local VCM backend.
|
|
557
|
-
- When
|
|
567
|
+
- When a Claude Code role stops, VCM marks that role idle, then scans pending route files.
|
|
558
568
|
- 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.
|
|
559
569
|
- VCM reads only stable, non-empty files and ignores blank files.
|
|
560
570
|
- VCM delivers at most one message to a target role per scan.
|
|
@@ -590,11 +600,18 @@ VCM Harness injects Claude Code hooks into `.claude/settings.json`:
|
|
|
590
600
|
|
|
591
601
|
VCM uses `UserPromptSubmit` as the Claude Code acceptance signal. A successful PTY write only proves VCM delivered text to the embedded terminal; `UserPromptSubmit` proves Claude Code accepted the prompt.
|
|
592
602
|
|
|
603
|
+
VCM Harness also injects Codex Reviewer hooks into `.ai/codex/.codex/hooks.json`:
|
|
604
|
+
|
|
605
|
+
- `UserPromptSubmit`: posts directly to `/api/hooks/codex-reviewer`, marks the fifth role running, and starts or continues the shared Round state
|
|
606
|
+
- `Stop`: posts directly to `/api/hooks/codex-reviewer/stop`, marks the fifth role idle, and lets the Round settle normally
|
|
607
|
+
|
|
608
|
+
Codex Reviewer hooks do not dispatch route files. PM receives Codex review completion through the Codex Review Gate callback managed by VCM.
|
|
609
|
+
|
|
593
610
|
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 should use `.claude/skills/vcm-route-message/SKILL.md` to author route files. Roles must not poll files, start shell loops, keep the turn open waiting for another role to answer, paste directly into another role terminal, or use Claude Code Task/Subagent for VCM role delegation.
|
|
594
611
|
|
|
595
612
|
Roles must not run background Bash; a `PreToolUse` hook (`.ai/tools/vcm-bash-guard`) denies `run_in_background`, `nohup`, `setsid`, `disown`, and trailing `&`. The only sanctioned long-running mechanism is `.ai/tools/run-long-check` plus `.ai/tools/watch-job` through `vcm-long-running-validation`: the detached job worker enforces the 60 minute ceiling and a supervision lease that kills unwatched jobs, `watch-job` renews the lease in foreground windows of up to 8 minutes (exit `125` means call it again in the same turn), and the VCM backend blocks a role's turn-end while one of its validation jobs is still running.
|
|
596
613
|
|
|
597
|
-
There is no `vcmctl` in the target design. Hook entrypoints are direct HTTP from Claude Code hooks to the local VCM backend.
|
|
614
|
+
There is no `vcmctl` in the target design. Hook entrypoints are direct HTTP from Claude Code and Codex Reviewer hooks to the local VCM backend.
|
|
598
615
|
|
|
599
616
|
## 13. Translation
|
|
600
617
|
|