@vypdev/copilot 3.3.0 → 3.5.0

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.
Files changed (86) hide show
  1. package/README.md +33 -5
  2. package/action.yml +85 -109
  3. package/build/api/index.js +4737 -1506
  4. package/build/api/src/api.d.ts +60 -14
  5. package/build/api/src/application/errors/application_error.d.ts +10 -0
  6. package/build/api/src/application/ports/bugbot_context_ports.d.ts +20 -7
  7. package/build/api/src/application/ports/bugbot_finding_publication_ports.d.ts +4 -4
  8. package/build/api/src/application/ports/bugbot_finding_resolution_ports.d.ts +4 -4
  9. package/build/api/src/application/ports/bugbot_issue_read_ports.d.ts +3 -0
  10. package/build/api/src/application/ports/bugbot_issue_write_ports.d.ts +12 -0
  11. package/build/api/src/application/ports/bugbot_pull_request_read_ports.d.ts +3 -17
  12. package/build/api/src/application/ports/bugbot_pull_request_resolution_ports.d.ts +7 -1
  13. package/build/api/src/application/ports/bugbot_pull_request_write_ports.d.ts +6 -1
  14. package/build/api/src/application/ports/bugbot_reconciliation_ports.d.ts +18 -0
  15. package/build/api/src/application/ports/bugbot_review_navigation_ports.d.ts +13 -0
  16. package/build/api/src/application/ports/bugbot_rule_ports.d.ts +1 -1
  17. package/build/api/src/application/ports/bugbot_scm_ports.d.ts +14 -0
  18. package/build/api/src/application/ports/bugbot_telemetry_ports.d.ts +27 -2
  19. package/build/api/src/application/ports/message_catalog_ports.d.ts +17 -0
  20. package/build/api/src/application/ports/pull_request_review_comment_ports.d.ts +31 -2
  21. package/build/api/src/data/model/application_error.d.ts +82 -0
  22. package/build/api/src/data/model/result.d.ts +3 -4
  23. package/build/api/src/domain/agent.d.ts +6 -5
  24. package/build/api/src/domain/branch_sync_validation.d.ts +4 -0
  25. package/build/api/src/domain/bugbot/context.d.ts +68 -0
  26. package/build/api/src/domain/bugbot/finding.d.ts +61 -0
  27. package/build/api/src/domain/bugbot/review_projection.d.ts +33 -0
  28. package/build/api/src/domain/bugbot/review_state.d.ts +29 -0
  29. package/build/api/src/domain/message_catalog.d.ts +35 -0
  30. package/build/api/src/tooling/bugbot_analytics.d.ts +2 -1
  31. package/build/cli/index.js +93317 -71617
  32. package/build/github_action/index.js +79616 -63218
  33. package/build/web/assets/index-2NVaAtP1.js +3 -0
  34. package/build/web/assets/index-FN-aja4Y.css +1 -0
  35. package/build/web/index.html +14 -0
  36. package/package.json +35 -22
  37. package/scripts/install-git-hooks.cjs +38 -14
  38. package/setup/ISSUE_TEMPLATE/hotfix.yml +1 -1
  39. package/setup/ISSUE_TEMPLATE/release.yml +1 -1
  40. package/setup/pull_request_template.md +9 -135
  41. package/setup/source-workflows/copilot_pull_request_approval.yml +55 -0
  42. package/setup/workflows/agent-cli-provisioning.yml +37 -13
  43. package/setup/workflows/copilot_close_inactive_issues.yml +4 -4
  44. package/setup/workflows/copilot_commit.yml +16 -16
  45. package/setup/workflows/copilot_credential_health.yml +0 -20
  46. package/setup/workflows/copilot_deployment_orchestration.yml +91 -0
  47. package/setup/workflows/copilot_issue.yml +15 -19
  48. package/setup/workflows/copilot_issue_comment.yml +17 -19
  49. package/setup/workflows/copilot_pull_request.yml +21 -22
  50. package/setup/workflows/copilot_pull_request_approval.yml +51 -0
  51. package/setup/workflows/copilot_pull_request_comment.yml +17 -19
  52. package/setup/workflows/copilot_pull_request_merge_queue.yml +20 -0
  53. package/setup/workflows/copilot_pull_request_review_state.yml +109 -0
  54. package/setup/workflows/hotfix_workflow.yml +157 -168
  55. package/setup/workflows/release_workflow.yml +157 -168
  56. package/build/api/src/application/usecases/steps/commit/bugbot/types.d.ts +0 -112
  57. package/build/api/src/data/model/agent.d.ts +0 -2
  58. package/build/api/src/data/model/ai.d.ts +0 -28
  59. package/build/api/src/data/model/branch_configuration.d.ts +0 -6
  60. package/build/api/src/data/model/branches.d.ts +0 -12
  61. package/build/api/src/data/model/commit.d.ts +0 -8
  62. package/build/api/src/data/model/config.d.ts +0 -30
  63. package/build/api/src/data/model/emoji.d.ts +0 -5
  64. package/build/api/src/data/model/execution.d.ts +0 -75
  65. package/build/api/src/data/model/execution_components.d.ts +0 -43
  66. package/build/api/src/data/model/execution_inputs.d.ts +0 -94
  67. package/build/api/src/data/model/hotfix.d.ts +0 -7
  68. package/build/api/src/data/model/images.d.ts +0 -27
  69. package/build/api/src/data/model/issue.d.ts +0 -27
  70. package/build/api/src/data/model/issue_types.d.ts +0 -30
  71. package/build/api/src/data/model/labels.d.ts +0 -60
  72. package/build/api/src/data/model/locale.d.ts +0 -6
  73. package/build/api/src/data/model/project_detail.d.ts +0 -15
  74. package/build/api/src/data/model/projects.d.ts +0 -14
  75. package/build/api/src/data/model/pull_request.d.ts +0 -32
  76. package/build/api/src/data/model/recommendation_state.d.ts +0 -6
  77. package/build/api/src/data/model/release.d.ts +0 -6
  78. package/build/api/src/data/model/single_action.d.ts +0 -43
  79. package/build/api/src/data/model/size_threshold.d.ts +0 -6
  80. package/build/api/src/data/model/size_thresholds.d.ts +0 -10
  81. package/build/api/src/data/model/tokens.d.ts +0 -4
  82. package/build/api/src/data/model/welcome.d.ts +0 -5
  83. package/build/api/src/data/model/workflows.d.ts +0 -5
  84. package/build/api/src/domain/bugbot/review_command.d.ts +0 -16
  85. package/build/api/src/domain/copilot_lifecycle.d.ts +0 -42
  86. package/build/api/src/domain/pull_request_description.d.ts +0 -13
@@ -0,0 +1 @@
1
+ :root{--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light dark;--page:#f6f8f7;--side:#102423;--side-line:#31504b;--side-text:#e8f5f0;--surface:#fff;--surface-soft:#f3f7f5;--line:#d7e3df;--control-line:#748b82;--text:#18312c;--muted:#58736b;--accent:#176e5e;--accent-strong:#075743;--accent-tint:#dff4e9;--focus:#966000;--warn:#76510d;--warn-bg:#fff6df;--error:#a73434;--error-bg:#fff0ec;--shadow:0 18px 50px #1e403414;font-family:Inter,ui-sans-serif,-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif}@media (prefers-color-scheme:dark){:root{--lightningcss-light: ;--lightningcss-dark:initial}:root:not([data-theme=light]){--page:#0d1716;--side:#10201d;--side-line:#294a41;--side-text:#eaf7f1;--surface:#182722;--surface-soft:#20342d;--line:#355247;--control-line:#688f7f;--text:#eaf5ee;--muted:#adccbc;--accent:#7ed6ac;--accent-strong:#a4edc2;--accent-tint:#234b38;--focus:#ffca6a;--warn:#ffdd8a;--warn-bg:#463b21;--error:#ffc0b7;--error-bg:#4a2b2a;--shadow:0 18px 50px #00000024}}:root[data-theme=dark]{--page:#0d1716;--side:#10201d;--side-line:#294a41;--side-text:#eaf7f1;--surface:#182722;--surface-soft:#20342d;--line:#355247;--control-line:#688f7f;--text:#eaf5ee;--muted:#adccbc;--accent:#7ed6ac;--accent-strong:#a4edc2;--accent-tint:#234b38;--focus:#ffca6a;--warn:#ffdd8a;--warn-bg:#463b21;--error:#ffc0b7;--error-bg:#4a2b2a;--shadow:0 18px 50px #00000024}:root[data-theme=light]{--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light}:root[data-theme=dark]{--lightningcss-light: ;--lightningcss-dark:initial;color-scheme:dark}*{box-sizing:border-box}body{background:var(--page);color:var(--text);margin:0}button,input,select{font:inherit}button{cursor:pointer}button:disabled{cursor:not-allowed;opacity:.5}:focus-visible{outline:3px solid var(--focus);outline-offset:3px}.visually-hidden{clip:rect(0, 0, 0, 0);white-space:nowrap;border:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}a{color:var(--accent-strong);text-underline-offset:3px}.card,.context-card{background:var(--surface);border:1px solid var(--line);box-shadow:var(--shadow);border-radius:15px}.primary{border:1px solid var(--accent-strong);background:var(--accent-strong);color:var(--side);border-radius:8px;min-height:43px;padding:12px 18px;font-size:12px;font-weight:800}:root[data-theme=light] .primary,:root:not([data-theme=dark]) .primary{color:#fff}@media (prefers-color-scheme:dark){:root:not([data-theme=light]) .primary{color:#0d2419}}.primary span{margin-left:18px}.primary:hover:not(:disabled){filter:brightness(1.1)}.secondary{border:1px solid var(--control-line);color:var(--text);background:var(--surface-soft);border-radius:8px;padding:11px 16px;font-size:12px;font-weight:700}@media (prefers-reduced-motion:reduce){*,:before,:after{scroll-behavior:auto!important;transition-duration:.01ms!important;animation-duration:.01ms!important}}.shell{grid-template-columns:minmax(250px,288px) minmax(0,1fr);min-height:100vh;display:grid}.sidebar{background:var(--side);color:var(--side-text);flex-direction:column;min-height:100vh;padding:34px 28px;display:flex;position:sticky;top:0}.brand{letter-spacing:-.035em;align-items:center;gap:13px;display:flex}.brand-mark{color:#0c3021;background:#75d9a0;border-radius:11px;place-items:center;width:37px;height:37px;font-size:26px;line-height:1;display:grid}.brand strong{font-size:23px;line-height:1;display:block}.brand small{letter-spacing:.23em;color:#aac8bd;margin-top:5px;font-size:9px;font-weight:800;display:block}.rail-caption{color:#9dbab0;letter-spacing:.18em;margin-block:78px 22px;margin-inline-start:7px;font-size:10px;font-weight:800}.sidebar .description{color:#afcabe}.steps{margin:0;padding:0;list-style:none;position:relative}.steps:before{content:"";top:22px;bottom:22px;background:var(--side-line);width:1px;position:absolute;inset-inline-start:19px}.steps li{color:#a6c2b7;border-radius:10px;align-items:center;gap:16px;min-height:55px;padding-block:8px;padding-inline:1px 12px;font-size:13px;font-weight:600;display:flex;position:relative}.steps li.current{color:#fff;background:#25443b}.steps li.completed{color:#dbf2e4}.step-index{border:1px solid var(--side-line);background:var(--side);letter-spacing:.04em;border-radius:50%;flex:0 0 37px;place-items:center;height:37px;font-size:11px;font-weight:800;display:grid}.steps .current .step-index{color:#102b1d;background:#80dba8;border-color:#80dba8}.steps .completed .step-index{color:#b9f8c9;background:#204c37;border-color:#45966b;font-size:15px}.sidebar-note{border:1px solid var(--side-line);background:#ffffff09;border-radius:13px;gap:13px;margin-top:auto;padding:19px 16px;display:flex}.sidebar-note>span{color:#8fe1ae;font-size:20px}.sidebar-note strong{font-size:12px}.sidebar-note p{color:#afcabe;margin:6px 0 0;font-size:11px;line-height:1.6}.main{min-width:0}.topbar{border-bottom:1px solid var(--line);background:var(--surface);flex-wrap:wrap;justify-content:space-between;align-items:center;gap:16px;min-height:80px;padding:20px clamp(24px,4vw,70px);display:flex}.breadcrumb{flex:240px;align-items:center;gap:12px;min-width:0;font-size:12px;display:flex}.breadcrumb span:first-child{color:var(--muted);letter-spacing:.14em;font-size:10px;font-weight:800}.breadcrumb span:nth-child(2){color:var(--muted)}.breadcrumb strong{white-space:normal;overflow-wrap:anywhere;min-width:0;line-height:1.5}.top-actions{flex-shrink:0;align-items:center;gap:18px;display:flex}.local-pill{color:var(--accent-strong);background:var(--accent-tint);letter-spacing:.08em;white-space:nowrap;border-radius:6px;padding:8px 11px;font-size:10px;font-weight:800}.pulse-dot{background:currentColor;border-radius:50%;width:6px;height:6px;margin-right:5px;display:inline-block}.theme-switch{border:1px solid var(--line);background:var(--surface-soft);border-radius:8px;padding:3px;display:flex}.theme-switch button{color:var(--muted);background:0 0;border:0;border-radius:5px;min-width:31px;height:27px;font-size:11px}.theme-switch button.active{background:var(--surface);color:var(--text);font-weight:800;box-shadow:0 1px 4px #0000001f}.content{max-width:1320px;margin:0 auto;padding:52px clamp(24px,4vw,70px) 35px}.eyebrow{color:var(--accent-strong);letter-spacing:.18em;align-items:center;gap:10px;font-size:10px;font-weight:900;display:flex}.eyebrow-line{background:var(--accent);width:21px;height:2px}.eyebrow-count{color:var(--muted);letter-spacing:.09em;margin-inline-start:8px}h1{letter-spacing:-.045em;max-width:860px;margin:15px 0 13px;font-size:clamp(30px,3vw,45px);line-height:1.15}.lede{color:var(--muted);max-width:700px;margin:0 0 30px;font-size:14px;line-height:1.65}.workspace-grid{grid-template-columns:minmax(0,1.65fr) minmax(230px,.8fr);align-items:start;gap:19px;display:grid}.workspace-grid:has(.plan-review){grid-template-columns:1fr}.workspace-grid:has(.plan-review) .context-column{grid-template-columns:repeat(2,minmax(0,1fr))}.context-column{gap:17px;display:grid}.context-card{box-shadow:none;padding:25px}.context-icon{background:var(--accent-tint);width:32px;height:32px;color:var(--accent-strong);border-radius:8px;place-items:center;font-size:19px;display:grid}.context-card h2{letter-spacing:-.015em;margin:17px 0 7px;font-size:14px}.context-card p,.context-card>small{color:var(--muted);margin:0 0 12px;font-size:12px;line-height:1.65;display:block}.context-card code{background:var(--surface-soft);overflow-wrap:anywhere;border-radius:6px;padding:10px;font-size:11px;display:block}.permissions ul{margin:8px 0 13px;padding:0;list-style:none}.permissions li{border-bottom:1px solid var(--line);justify-content:space-between;gap:10px;padding:9px 0;font-size:11px;display:flex}.permissions li small{color:var(--muted);margin-top:3px;display:block}.permissions li strong{color:var(--accent-strong);text-transform:uppercase;font-size:9px}.permission-progress{padding:clamp(20px,4vw,38px)}.permission-progress h2{margin:0 0 8px}.permission-progress p{color:var(--muted);line-height:1.5}.permission-progress ol{margin:20px 0 0;padding:0;list-style:none}.permission-progress li{border-top:1px solid var(--line);align-items:center;gap:14px;padding:12px 0;display:flex}.permission-progress li>span:nth-child(2){flex:1;min-width:0}.permission-progress li small{color:var(--muted);overflow-wrap:anywhere;display:block}.permission-progress-symbol{background:var(--surface-soft);border-radius:50%;flex:none;place-items:center;width:30px;height:30px;display:grid}.permission-progress-done .permission-progress-symbol{color:var(--accent-strong)}.permission-progress-failed .permission-progress-symbol{color:var(--danger,#a33)}.permission-progress-state{text-align:right;max-width:35%;font-size:.8rem;font-weight:600}@media (width<=600px){.permission-progress li{flex-wrap:wrap;align-items:flex-start}.permission-progress-state{text-align:left;max-width:none;margin-left:44px}}footer{color:var(--muted);opacity:.85;letter-spacing:.11em;margin-top:40px;font-size:9px;font-weight:700}footer span{margin:0 8px}[dir=rtl] .context-card code,[dir=rtl] .result-links code,[dir=rtl] .producer-option strong,[dir=rtl] .producer-option small,[dir=rtl] input[type=password]{direction:ltr;unicode-bidi:isolate}.decision-card{min-height:360px;padding:clamp(25px,3vw,40px)}.card-header{justify-content:space-between;align-items:center;gap:12px;margin-bottom:29px;display:flex}.card-kicker{color:var(--accent-strong);letter-spacing:.17em;font-size:10px;font-weight:900}.revision{color:var(--muted);letter-spacing:.08em;font-size:10px}.description{white-space:pre-line;color:var(--muted);margin-top:0;font-size:13px;line-height:1.65}.question-heading{flex-wrap:wrap;justify-content:space-between;align-items:center;gap:10px;margin-bottom:15px;display:flex}.question-heading h2,.decision-card>label{margin:0 0 10px;font-size:15px;font-weight:700;line-height:1.4;display:block}.phase-tag{color:var(--accent-strong);background:var(--accent-tint);letter-spacing:.07em;border-radius:5px;padding:6px 8px;font-size:9px;font-weight:900}input[type=text],input[type=password],input[type=number],select{border:1px solid var(--control-line);background:var(--surface-soft);width:100%;min-height:46px;color:var(--text);border-radius:8px;padding:10px 13px}textarea{resize:vertical;border:1px solid var(--control-line);background:var(--surface-soft);width:100%;min-height:120px;color:var(--text);font:inherit;border-radius:8px;padding:12px 13px;line-height:1.5}.language-switch{color:var(--muted);white-space:nowrap;align-items:center;gap:7px;font-size:11px;font-weight:700;display:flex}.language-switch select{width:auto;max-width:140px;min-height:32px;padding:5px 8px;font-size:11px}.question-details{border:1px solid var(--line);background:var(--surface-soft);border-radius:8px;margin-bottom:20px;padding:13px 15px;font-size:12px}.question-details summary{cursor:pointer;color:var(--accent-strong);font-weight:800}.question-details dl{grid-template-columns:minmax(90px,130px) minmax(0,1fr);gap:10px 14px;margin:14px 0 0;line-height:1.55;display:grid}.question-details dt{color:var(--text);font-weight:750}.question-details dd{color:var(--muted);margin:0}.question-help-link{margin:-12px 0 18px;font-size:12px;font-weight:700}.discovery-actions{flex-wrap:wrap;align-items:center;gap:8px 14px;margin:4px 0 16px;display:flex}.discovery-actions .field-help{margin:0}.secondary-button{border:1px solid var(--control-line);background:var(--surface-soft);color:var(--accent-strong);font:inherit;border-radius:8px;padding:9px 13px;font-size:12px;font-weight:750}.secondary-button:hover:not(:disabled),.secondary-button:focus-visible{border-color:var(--accent);background:var(--accent-tint)}.secondary-button:disabled{opacity:.55;cursor:not-allowed}.status-review-list{color:var(--muted);margin:6px 0 18px;padding-inline-start:20px;font-size:12px;line-height:1.7}.status-review-list strong{color:var(--text)}.producer-grid{margin-bottom:20px;padding:6px}.check-option.producer-option{grid-template-columns:minmax(0,1fr) auto;align-items:start;gap:16px;padding:14px 16px;display:grid}.producer-option>label{cursor:pointer;align-items:flex-start;gap:12px;min-width:0;display:flex}.producer-option>label>input{flex:0 0 17px;margin:3px 0 0}.producer-option>label>span{overflow-wrap:anywhere;gap:5px;min-width:0;display:grid}.producer-option small{color:var(--muted);font-size:10px;line-height:1.5}.producer-option a{font-size:11px;line-height:1.5}.producer-option>a{max-width:140px}.producer-links{gap:8px;max-width:140px;display:grid}.producer-manual-fields{grid-template-columns:repeat(2,minmax(0,1fr));gap:16px;display:grid}.producer-manual-fields>label,.project-manual-field{gap:8px;font-size:12px;font-weight:700;line-height:1.5;display:grid}.producer-manual-fields>label:last-child{grid-column:1/-1}.producer-add{margin-top:16px}.project-manual-field{margin-top:20px}input[type=checkbox]{accent-color:var(--accent);width:17px;height:17px}.field-help{color:var(--muted);margin:14px 0 24px;font-size:12px;line-height:1.6}.segmented{gap:9px;display:flex}.segmented button{border:1px solid var(--control-line);color:var(--text);background:var(--surface-soft);border-radius:8px;flex:1;padding:13px;font-weight:700}.segmented button.selected{border-color:var(--accent);background:var(--accent-tint);color:var(--accent-strong)}.check-grid{gap:10px;display:grid}.check-option{background:var(--surface-soft);border:1px solid var(--control-line);border-radius:7px;align-items:center;gap:10px;padding:10px 13px;font-size:12px;display:flex}.choice-list{gap:9px;display:grid}.choice-card{text-align:left;background:var(--surface-soft);width:100%;min-height:52px;color:var(--text);border:1px solid var(--control-line);border-radius:8px;justify-content:space-between;align-items:center;padding:13px 15px;font-size:13px;font-weight:650;display:flex}.choice-card:hover:not(:disabled){border-color:var(--accent);background:var(--accent-tint)}.github-link{background:var(--accent-tint);border:1px solid var(--accent);border-radius:8px;margin:0 0 12px;padding:14px;font-size:13px;font-weight:800;text-decoration:none;display:block}.github-link span{float:right}.plan-review{gap:24px;font-size:12px;line-height:1.65;display:grid}.plan-review>.description,.plan-review .field-help{margin:0}.plan-sections{grid-template-columns:repeat(2,minmax(0,1fr));align-items:start;gap:16px;display:grid}.plan-decisions,.plan-inventory,.plan-warnings{background:var(--surface-soft);border:1px solid var(--line);border-radius:8px;min-width:0;padding:20px}.plan-decisions h3,.plan-warnings h3{margin:0 0 14px;font-size:13px;line-height:1.5}.plan-decisions p{margin:0 0 16px}.plan-decisions>:last-child{margin-bottom:0}.plan-decisions dl{gap:0;margin:0;display:grid}.plan-decisions dl>div{border-bottom:1px solid var(--line);grid-template-columns:minmax(130px,35%) minmax(0,1fr);gap:20px;padding:12px 0;display:grid}.plan-decisions dl>div:first-child{padding-top:0}.plan-decisions dl>div:last-child{border-bottom:0;padding-bottom:0}.plan-decisions dt{color:var(--muted)}.plan-decisions dd{overflow-wrap:anywhere;min-width:0;margin:0}.plan-decisions .field-help{margin-top:20px}.plan-decisions ul,.plan-inventory ul,.plan-warnings ul{overflow-wrap:anywhere;margin:0;padding-inline-start:20px;font-size:12px;line-height:1.7}.plan-decisions li+li,.plan-inventory li+li,.plan-warnings li+li{margin-top:6px}.plan-inventory summary{cursor:pointer;font-size:13px;font-weight:750}.plan-inventory summary span:last-child{float:right;color:var(--accent-strong);margin-inline-start:12px}.plan-inventory[open] summary{margin-bottom:16px}.plan-warnings{color:var(--warn);background:var(--warn-bg)}.plan-edit{border-top:1px solid var(--line);padding-top:24px}.plan-edit h3{margin:0 0 4px;font-size:14px}.plan-edit-actions{flex-wrap:wrap;gap:10px;margin-top:16px;display:flex}.button-row{flex-wrap:wrap;align-items:center;gap:12px;margin-top:24px;display:flex}.button-row>.primary{margin-left:auto}.plan-review>.button-row{border-top:1px solid var(--line);margin-top:0;padding-top:24px}.review-pass,.banner{white-space:pre-line;border-radius:8px;margin:0 0 20px;padding:14px 18px;font-size:12px;line-height:1.5}.review-pass{color:var(--accent-strong);background:var(--accent-tint);border:1px solid var(--accent)}.review-pass span{margin-inline-end:8px;font-weight:800}.banner{background:var(--surface-soft);border:1px solid var(--line)}.banner p{margin:5px 0 0}.banner.warning{color:var(--warn);background:var(--warn-bg);border-color:var(--warn)}.banner.error{color:var(--error);background:var(--error-bg);border-color:var(--error)}.banner.success{color:var(--accent-strong);background:var(--accent-tint);border-color:var(--accent)}.banner button{margin-top:12px}.cancel-link{color:var(--muted);background:0 0;border:0;margin-top:18px;padding:5px 0;font-size:12px;text-decoration:underline}.result-card,.waiting-card{max-width:750px;padding:36px}.result-icon{background:var(--accent-tint);width:43px;height:43px;color:var(--accent-strong);border-radius:50%;place-items:center;font-size:22px;display:grid}.result-card h2,.waiting-card h2{margin:18px 0 10px;font-size:21px}.result-card p,.waiting-card p{color:var(--muted);font-size:13px;line-height:1.6}.result-facts{border:1px solid var(--line);background:var(--surface-soft);border-radius:8px;margin:24px 0;padding:20px}.result-facts p{margin:8px 0}.result-facts strong{color:var(--text)}.result-effects{border:1px solid var(--line);background:var(--surface-soft);border-radius:8px;margin:20px 0;padding:14px 17px}.result-effects h3{color:var(--text);margin:0 0 10px;font-size:13px}.result-effects ul{margin:0;padding-left:20px}.result-effects li{overflow-wrap:anywhere;padding:3px 0;font-size:12px}.result-links{flex-wrap:wrap;align-items:center;gap:20px;margin:22px 0;font-size:12px;display:flex}.result-links code{background:var(--surface-soft);border-radius:5px;padding:8px}.spinner{border:3px solid var(--line);border-top-color:var(--accent);border-radius:50%;width:25px;height:25px;animation:1s linear infinite spin}@keyframes spin{to{transform:rotate(360deg)}}.result-facts h3{margin:0 0 16px;font-size:15px;line-height:1.5}.result-permissions{margin:20px 0 0;padding-inline-start:20px;font-size:13px;line-height:1.65}.result-permissions li+li{margin-top:16px}.result-permissions p{margin:6px 0 0}@media (width<=1100px){.workspace-grid{grid-template-columns:1fr}.context-column{grid-template-columns:repeat(2,minmax(0,1fr))}}@media (width<=780px){.shell{display:block}.sidebar{min-height:0;padding:16px 20px;position:static}.rail-caption,.sidebar-note{display:none}.steps{flex-wrap:wrap;gap:4px;margin-top:18px;display:flex}.steps:before{display:none}.steps li{flex:none;gap:6px;min-height:37px;padding:4px 7px;font-size:11px}.step-index{flex-basis:26px;width:26px;height:26px}.topbar{flex-wrap:wrap;height:auto;min-height:65px;padding:12px 20px}.content{padding:28px 20px}}@media (width<=540px){.context-column,.plan-sections{grid-template-columns:1fr}.workspace-grid:has(.plan-review) .context-column{grid-template-columns:1fr}.top-actions{flex-wrap:wrap;justify-content:space-between;gap:12px;width:100%;min-width:0}.decision-card{padding:22px}.breadcrumb{max-width:100%}h1{font-size:29px}.plan-decisions dl>div{grid-template-columns:1fr;gap:2px}.question-details dl{grid-template-columns:1fr;gap:3px}.question-details dd{margin-bottom:9px}.language-switch{margin-inline-start:auto}}@media (width<=640px){.check-option.producer-option{grid-template-columns:minmax(0,1fr);gap:12px}.producer-option>a,.producer-links{max-width:none;margin-inline-start:29px}.producer-manual-fields{grid-template-columns:minmax(0,1fr)}}.management-status{color:var(--accent-strong);font-weight:750}.management-actions{flex-wrap:wrap;gap:12px;margin-block:24px 32px;display:flex}.management-section{border-top:1px solid var(--line);padding-block:26px}.management-section h2{margin-top:0}.management-section summary{cursor:pointer;color:var(--accent-strong);font-weight:700}.management-settings{grid-template-columns:repeat(2,minmax(0,1fr));gap:16px;display:grid}.management-setting{border:1px solid var(--line);background:var(--surface-soft);border-radius:10px;justify-content:space-between;align-items:center;gap:16px;padding:18px;display:flex}.management-setting h3{margin:0 0 8px;font-size:14px}.management-setting p{color:var(--muted);overflow-wrap:anywhere;margin:0}.management-setting .button{flex-shrink:0}.management-values{gap:8px;display:grid}.management-values dt{overflow-wrap:anywhere;margin-top:12px;font-weight:650}.management-values dd{white-space:pre-wrap;overflow-wrap:anywhere;color:var(--muted);margin:0;line-height:1.6}.management-workflow{padding-block:16px}:is(.workspace-grid:has(.management-settings),.workspace-grid:has(.management-status)){grid-template-columns:1fr}.workspace-grid:has(.management-status) .context-column{display:none}@media (width<=800px){.management-settings{grid-template-columns:1fr}}@media (width<=420px){.management-setting{flex-direction:column;align-items:stretch}.management-setting .button{align-self:flex-end}}
@@ -0,0 +1,14 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <meta name="color-scheme" content="light dark" />
7
+ <title>Copilot · Setup studio</title>
8
+ <script type="module" crossorigin src="./assets/index-2NVaAtP1.js"></script>
9
+ <link rel="stylesheet" crossorigin href="./assets/index-FN-aja4Y.css">
10
+ </head>
11
+ <body>
12
+ <div id="app"></div>
13
+ </body>
14
+ </html>
package/package.json CHANGED
@@ -1,7 +1,17 @@
1
1
  {
2
2
  "name": "@vypdev/copilot",
3
- "version": "3.3.0",
3
+ "version": "3.5.0",
4
4
  "packageManager": "pnpm@10.12.4",
5
+ "pnpm": {
6
+ "overrides": {
7
+ "js-yaml@>=3.0.0 <3.15.2": "3.15.2",
8
+ "handlebars@>=4.0.0 <=4.7.9": "4.7.10",
9
+ "source-map-js@>=1.0.0 <1.2.2": "1.2.2",
10
+ "brace-expansion@>=2.0.0 <2.1.7": "2.1.7",
11
+ "brace-expansion@>=5.0.0 <5.0.12": "5.0.12",
12
+ "@istanbuljs/load-nyc-config>js-yaml": "4.3.2"
13
+ }
14
+ },
5
15
  "description": "Automates branch management, GitHub project linking, and issue/PR tracking with Git-Flow methodology.",
6
16
  "homepage": "https://github.com/vypdev/copilot",
7
17
  "repository": {
@@ -25,11 +35,13 @@
25
35
  "files": [
26
36
  "action.yml",
27
37
  "build/cli/index.js",
38
+ "build/web/",
28
39
  "build/github_action/index.js",
29
40
  "build/api/index.js",
30
41
  "build/api/src/",
31
42
  "setup/ISSUE_TEMPLATE/",
32
43
  "setup/workflows/",
44
+ "setup/source-workflows/",
33
45
  "setup/pull_request_template.md",
34
46
  "scripts/install-git-hooks.cjs",
35
47
  "README.md",
@@ -42,13 +54,15 @@
42
54
  "node": ">=24"
43
55
  },
44
56
  "scripts": {
45
- "build": "node scripts/clean-generated-bundles.cjs && ncc build src/actions/github_action.ts -o build/github_action && ncc build src/cli.ts -o build/cli && ncc build src/api.ts -o build/api && node scripts/prepare-generated-bundles.cjs && chmod +x build/cli/index.js",
57
+ "build": "node scripts/clean-generated-bundles.cjs && pnpm run build:web && ncc build src/actions/github_action.ts -o build/github_action && ncc build src/cli.ts -o build/cli && ncc build src/api.ts -o build/api && node scripts/prepare-generated-bundles.cjs && node scripts/set-cli-executable.cjs",
58
+ "build:web": "vite build --config web/vite.config.mts",
59
+ "check:web": "svelte-check --tsconfig web/tsconfig.json && vite build --config web/vite.config.mts",
46
60
  "validate:build": "node scripts/validate-build.cjs",
47
61
  "validate:npm-package": "node scripts/validate-npm-package.cjs",
48
62
  "smoke:npm-package": "node scripts/smoke-test-npm-package.cjs",
49
63
  "test": "jest",
50
64
  "test:watch": "jest --watch",
51
- "test:coverage": "jest --coverage",
65
+ "test:coverage": "jest --coverage --json --outputFile=coverage/setup-acceptance-jest.json && node scripts/validate-coverage-budgets.cjs && node scripts/validate-setup-assistant-acceptance.cjs coverage/setup-acceptance-jest.json",
52
66
  "eval:bugbot": "jest src/tooling/__tests__/bugbot_quality_eval.test.ts src/tooling/__tests__/bugbot_benchmark.test.ts --runInBand",
53
67
  "typecheck": "tsc --noEmit",
54
68
  "metrics:architecture": "node scripts/collect-architecture-metrics.cjs",
@@ -57,6 +71,9 @@
57
71
  "validate:docs-page": "node scripts/validate-docs-page-assets.cjs",
58
72
  "validate:documentation": "node scripts/validate-documentation-contract.cjs",
59
73
  "validate:workflows": "node scripts/validate-workflow-contract.cjs",
74
+ "generate:specifications": "node scripts/validate-specification-catalog.cjs --write && node scripts/validate-github-communication-test-budget.cjs",
75
+ "validate:specifications": "node scripts/validate-specification-catalog.cjs && node scripts/validate-github-communication-test-budget.cjs",
76
+ "validate:setup-acceptance": "node scripts/validate-setup-assistant-acceptance.cjs",
60
77
  "lint:fix": "eslint src --fix",
61
78
  "postinstall": "node scripts/install-git-hooks.cjs"
62
79
  },
@@ -64,33 +81,29 @@
64
81
  "author": "Efra Espada",
65
82
  "license": "MIT",
66
83
  "dependencies": {
67
- "@actions/cache": "^4.1.0",
68
- "@actions/core": "^1.11.1",
69
- "@actions/exec": "^1.1.1",
70
- "@actions/github": "^6.0.1",
71
- "@types/axios": "^0.14.4",
72
- "@types/chance": "^1.1.6",
73
- "@types/js-yaml": "^4.0.9",
74
- "axios": "^1.8.4",
84
+ "@actions/core": "^2.0.3",
85
+ "@actions/exec": "^2.0.0",
86
+ "@actions/github": "^8.0.1",
75
87
  "boxen": "^8.0.1",
76
88
  "chalk": "^5.4.1",
77
- "chance": "^1.1.12",
78
89
  "commander": "^12.0.0",
79
- "dockerode": "^4.0.5",
80
- "js-yaml": "^4.1.0",
81
- "shell-quote": "^1.8.3",
82
- "tweetnacl": "^1.0.3"
90
+ "js-yaml": "^5.4.1",
91
+ "libsodium-wrappers": "^0.8.4",
92
+ "shell-quote": "^1.12.0"
83
93
  },
84
94
  "devDependencies": {
85
- "@eslint/js": "^9.15.0",
86
- "@types/dockerode": "^3.3.37",
95
+ "@eslint/js": "^10.0.1",
96
+ "@sveltejs/vite-plugin-svelte": "^7.3.1",
87
97
  "@types/jest": "^30.0.0",
88
98
  "@types/node": "^22.9.1",
89
99
  "@vercel/ncc": "^0.36.1",
90
- "eslint": "^9.15.0",
91
- "jest": "^30.2.0",
100
+ "eslint": "^10.10.0",
101
+ "jest": "^30.5.1",
102
+ "svelte": "^5.57.1",
103
+ "svelte-check": "^4.7.6",
92
104
  "ts-jest": "^29.4.5",
93
105
  "typescript": "^5.2.2",
94
- "typescript-eslint": "^8.15.0"
106
+ "typescript-eslint": "^8.70.0",
107
+ "vite": "^8.3.1"
95
108
  }
96
- }
109
+ }
@@ -1,36 +1,60 @@
1
1
  /**
2
- * Installs git hooks from scripts/git-hooks/ into .git/hooks/.
2
+ * Installs repository hooks into normal and linked-worktree Git metadata.
3
3
  * Cross-platform: Windows, macOS, Linux.
4
4
  * Run automatically on pnpm install, or: node scripts/install-git-hooks.cjs
5
5
  */
6
6
 
7
7
  const fs = require('fs');
8
8
  const path = require('path');
9
+ const { spawnSync } = require('node:child_process');
9
10
 
10
11
  const root = path.resolve(__dirname, '..');
11
12
  const hooksSrc = path.join(root, 'scripts', 'git-hooks');
12
- const hooksDst = path.join(root, '.git', 'hooks');
13
-
14
- if (!fs.existsSync(path.join(root, '.git')) || !fs.statSync(path.join(root, '.git')).isDirectory()) {
15
- process.exit(0);
16
- }
13
+ const metadata = path.join(root, '.git');
14
+ if (!fs.existsSync(metadata)) process.exit(0);
17
15
  if (!fs.existsSync(hooksSrc) || !fs.statSync(hooksSrc).isDirectory()) {
18
16
  process.exit(0);
19
17
  }
20
- if (!fs.existsSync(hooksDst) || !fs.statSync(hooksDst).isDirectory()) {
21
- process.exit(0);
18
+ let metadataDirectories;
19
+ if (fs.statSync(metadata).isDirectory()) {
20
+ const hooks = path.join(metadata, 'hooks');
21
+ if (!fs.existsSync(hooks) || !fs.statSync(hooks).isDirectory()) process.exit(0);
22
+ metadataDirectories = [metadata];
23
+ } else {
24
+ const readMetadata = flag => {
25
+ const result = spawnSync('git', ['rev-parse', flag], {
26
+ cwd: root, encoding: 'utf8', timeout: 10000, maxBuffer: 16384,
27
+ stdio: ['ignore', 'pipe', 'pipe'],
28
+ });
29
+ const value = result.status === 0 && typeof result.stdout === 'string' ? result.stdout.trim() : '';
30
+ if (!value || /[\r\n\0]/u.test(value)) return undefined;
31
+ const directory = path.resolve(root, value);
32
+ return fs.existsSync(directory) && fs.statSync(directory).isDirectory() ? directory : undefined;
33
+ };
34
+ const local = readMetadata('--git-dir');
35
+ const common = readMetadata('--git-common-dir');
36
+ if (!local || !common) {
37
+ console.warn('Git metadata could not be resolved; repository hooks were not installed.');
38
+ process.exit(0);
39
+ }
40
+ // Git's default uses shared hooks; hook-chain wrappers can use the worktree's own metadata.
41
+ metadataDirectories = [...new Set([local, common])];
22
42
  }
23
43
 
24
44
  const files = fs.readdirSync(hooksSrc);
25
45
  for (const name of files) {
26
46
  const src = path.join(hooksSrc, name);
27
47
  if (!fs.statSync(src).isFile()) continue;
28
- const dst = path.join(hooksDst, name);
29
- fs.copyFileSync(src, dst);
30
- try {
31
- fs.chmodSync(dst, 0o755);
32
- } catch (_) {
33
- // Windows: chmod may not support execute; Git for Windows still runs the hook
48
+ for (const directory of metadataDirectories) {
49
+ const hooksDst = path.join(directory, 'hooks');
50
+ fs.mkdirSync(hooksDst, { recursive: true });
51
+ const dst = path.join(hooksDst, name);
52
+ fs.copyFileSync(src, dst);
53
+ try {
54
+ fs.chmodSync(dst, 0o755);
55
+ } catch (_) {
56
+ // Windows: chmod may not support execute; Git for Windows still runs the hook.
57
+ }
34
58
  }
35
59
  console.log('Installed hook: ' + name);
36
60
  }
@@ -2,7 +2,7 @@ name: 🔥 Hotfix Issue
2
2
 
3
3
  description: Request a new hotfix for copilot (only team members)
4
4
  title: "<YOUR TITLE HERE>"
5
- labels: [ "hotfix", "branched", "priority: high" ]
5
+ labels: [ "hotfix", "priority: high" ]
6
6
  body:
7
7
  - type: markdown
8
8
  attributes:
@@ -1,7 +1,7 @@
1
1
  name: 🚀 Release Issue
2
2
  description: Request a new release for copilot (only team members)
3
3
  title: "<YOUR TITLE HERE>"
4
- labels: ["release", "branched", "priority: medium"]
4
+ labels: ["release", "priority: medium"]
5
5
  body:
6
6
  - type: markdown
7
7
  attributes:
@@ -1,144 +1,18 @@
1
1
  <!--
2
- Thank you for opening a Pull Request 🚀
3
- Please fill out this template as completely as possible.
4
- Clear PRs = faster reviews = better software.
2
+ Lead with one to three sentences that explain the outcome and why it matters.
3
+ Keep the body concise and remove any section that has no useful content.
5
4
  -->
6
5
 
7
- # 📌 Summary
8
- <!--
9
- Briefly explain what this PR does and why it is needed.
10
- Focus on the intent, not the implementation details.
11
- -->
12
-
13
- ---
14
-
15
- ## 🎯 Related Issues / Tickets
16
- <!--
17
- Link any related issues, tickets, or discussions.
18
- Use GitHub keywords to auto-close issues when merged.
19
- -->
20
- - Closes #
21
- - Related to #
22
-
23
- ---
6
+ ## What changed
24
7
 
25
- ## 🧩 Scope of Changes
26
- <!--
27
- Describe the scope and nature of the changes at a high level.
28
- -->
29
- - Added:
30
- - Updated:
31
- - Removed:
32
- - Refactored:
33
-
34
- ---
35
-
36
- ## 🛠️ Technical Details
37
- <!--
38
- Explain important technical decisions, trade-offs, or architecture changes.
39
- Include anything that may not be obvious from reading the code.
40
- -->
41
-
42
- ---
43
-
44
- ## 🔍 How to Test
45
- <!--
46
- Provide clear, step-by-step instructions to test this change.
47
- Assume the reviewer is unfamiliar with the context.
48
- -->
49
- 1.
50
- 2.
51
- 3.
52
-
53
- ---
54
-
55
- ## 🧪 Test Coverage
56
- <!--
57
- Indicate what types of tests were added or updated.
58
- -->
59
- - [ ] Unit tests
60
- - [ ] Integration tests
61
- - [ ] End-to-end (E2E) tests
62
- - [ ] Manual testing only (explain why)
63
-
64
- ---
65
-
66
- ## 📸 Screenshots / Recordings (UI changes only)
67
- <!--
68
- Include before/after screenshots or short videos if this PR affects the UI.
69
- -->
8
+ -
70
9
 
71
- ---
72
-
73
- ## ⚠️ Breaking Changes
74
- <!--
75
- List any breaking changes and required migration steps.
76
- If none, state "None".
77
- -->
78
- - None
79
-
80
- ---
81
-
82
- ## 🚀 Deployment Notes
83
- <!--
84
- Anything required or important during deployment:
85
- - environment variables
86
- - database migrations
87
- - feature flags
88
- - deployment order
89
- -->
90
- - [ ] Requires database migration
91
- - [ ] Requires environment variable changes
92
- - [ ] Requires feature flag toggle
93
- - [ ] No special deployment steps
94
-
95
- Details:
96
-
97
- ---
98
-
99
- ## 🔒 Security Considerations
100
- <!--
101
- Mention any security-related implications or validations.
102
- -->
103
- - [ ] No security impact
104
- - [ ] Input validation changes
105
- - [ ] Authentication / authorization changes
106
- - [ ] Sensitive data handling changes
107
-
108
- ---
109
-
110
- ## 📈 Performance Impact
111
- <!--
112
- Describe any performance considerations, improvements, or regressions.
113
- -->
114
- - [ ] No performance impact
115
- - [ ] Improves performance
116
- - [ ] Potential performance regression (explain)
117
-
118
- ---
119
-
120
- ## 📝 Notes for Reviewers
121
- <!--
122
- Highlight areas that need special attention or context for reviewers.
123
- -->
124
-
125
- ---
126
-
127
- ## ✅ Checklist
128
- <!--
129
- Confirm all items before requesting review.
130
- -->
131
- - [ ] I have self-reviewed my code
132
- - [ ] Code follows project standards and conventions
133
- - [ ] Tests have been added or updated
134
- - [ ] Documentation has been updated (if applicable)
135
- - [ ] No new warnings or lint errors
136
- - [ ] Changes are backward compatible or breaking changes are documented
10
+ ## Validation
137
11
 
138
- ---
12
+ -
139
13
 
140
- ## 📚 Additional Context
141
14
  <!--
142
- Any extra information that may help reviewers understand this PR.
143
- Links, references, or follow-up work.
15
+ Add "## Review notes" only for material risks, migrations, rollout details,
16
+ compatibility concerns, or manual verification that a reviewer must know.
17
+ Add a valid closing reference only when this PR resolves a separate issue.
144
18
  -->
@@ -0,0 +1,55 @@
1
+ name: Copilot - Pull Request Approval
2
+ run-name: Copilot approval · ${{ github.event_name }}
3
+
4
+ on:
5
+ workflow_run:
6
+ workflows: ['Copilot - Pull Request', 'CI Check']
7
+ types: [completed]
8
+ workflow_dispatch:
9
+ inputs:
10
+ pr:
11
+ description: Positive pull-request number to recheck
12
+ required: true
13
+ type: number
14
+
15
+ jobs:
16
+ observe-approval:
17
+ name: Copilot - Pull Request Approval
18
+ runs-on: [self-hosted, codex, Linux]
19
+ timeout-minutes: 15
20
+ concurrency:
21
+ group: copilot-approval-${{ github.repository }}
22
+ cancel-in-progress: false
23
+ permissions:
24
+ actions: read
25
+ checks: write
26
+ contents: read
27
+ pull-requests: read
28
+ steps:
29
+ # workflow_run's github.sha is the trusted default-branch revision, never
30
+ # the PR head. This source-repository workflow can test unreleased code.
31
+ - name: Checkout trusted default-branch revision
32
+ uses: actions/checkout@v5
33
+ with:
34
+ ref: ${{ github.sha }}
35
+ persist-credentials: false
36
+ - name: Observe current PR evidence without checking out PR code
37
+ uses: ./
38
+ with:
39
+ pr-approval-observer: 'true'
40
+ pr-approval-pr-number: ${{ github.event.inputs.pr || '' }}
41
+ pr-approval-policy: ${{ vars.PR_APPROVAL_POLICY || '' }}
42
+ main-branch: ${{ vars.MAIN_BRANCH || 'master' }}
43
+ development-branch: ${{ vars.DEVELOPMENT_BRANCH || 'develop' }}
44
+ feature-tree: ${{ vars.FEATURE_TREE || 'feature' }}
45
+ bugfix-tree: ${{ vars.BUGFIX_TREE || 'bugfix' }}
46
+ docs-tree: ${{ vars.DOCS_TREE || 'docs' }}
47
+ chore-tree: ${{ vars.CHORE_TREE || 'chore' }}
48
+ bugbot-severity: ${{ vars.BUGBOT_SEVERITY || 'low' }}
49
+ bugbot-dry-run: ${{ vars.BUGBOT_DRY_RUN || 'false' }}
50
+ ai-ignore-files: ${{ vars.AI_IGNORE_FILES || 'build/*' }}
51
+ repository-locale: ${{ vars.REPOSITORY_LOCALE || 'en-US' }}
52
+ pull-requests-locale: ${{ vars.PULL_REQUESTS_LOCALE || '' }}
53
+ token: ${{ secrets.PAT }}
54
+ env:
55
+ COPILOT_APPROVAL_CHECK_TOKEN: ${{ github.token }}
@@ -26,28 +26,52 @@ jobs:
26
26
  PLANNER_PROVIDER: ${{ vars.PLANNER_PROVIDER }}
27
27
  REVIEWER_PROVIDER: ${{ vars.REVIEWER_PROVIDER }}
28
28
  TESTER_PROVIDER: ${{ vars.TESTER_PROVIDER }}
29
- AGENT_COMMAND: ${{ vars.AGENT_COMMAND }}
29
+ AGENT_EXECUTABLE: ${{ vars.AGENT_EXECUTABLE }}
30
+ FINDINGS_EXECUTABLE: ${{ vars.FINDINGS_EXECUTABLE }}
31
+ FIXER_EXECUTABLE: ${{ vars.FIXER_EXECUTABLE }}
32
+ PLANNER_EXECUTABLE: ${{ vars.PLANNER_EXECUTABLE }}
33
+ REVIEWER_EXECUTABLE: ${{ vars.REVIEWER_EXECUTABLE }}
34
+ TESTER_EXECUTABLE: ${{ vars.TESTER_EXECUTABLE }}
30
35
  run: |
31
36
  set -euo pipefail
32
37
 
33
38
  providers=("$AGENT_PROVIDER" "$FINDINGS_PROVIDER" "$FIXER_PROVIDER" "$PLANNER_PROVIDER" "$REVIEWER_PROVIDER" "$TESTER_PROVIDER")
39
+ executables=("$AGENT_EXECUTABLE" "$FINDINGS_EXECUTABLE" "$FIXER_EXECUTABLE" "$PLANNER_EXECUTABLE" "$REVIEWER_EXECUTABLE" "$TESTER_EXECUTABLE")
34
40
  checked=""
35
- for provider in "${providers[@]}"; do
41
+ for index in "${!providers[@]}"; do
42
+ provider="${providers[$index]}"
36
43
  [[ -z "${provider// }" ]] && continue
37
- [[ " $checked " == *" $provider "* ]] && continue
38
- checked="$checked $provider"
39
- if [[ -n "${AGENT_COMMAND// }" && "$provider" == "$AGENT_PROVIDER" ]]; then
40
- read -r executable _ <<< "$AGENT_COMMAND"
41
- command -v "$executable"
42
- echo "Configured agent command: $executable"
43
- continue
44
- fi
45
44
  case "$provider" in
46
- opencode) command -v opencode; opencode --version >/dev/null; opencode run --help >/dev/null ;;
47
- codex) command -v codex; codex --version >/dev/null; codex exec --help >/dev/null ;;
48
- cursor) command -v agent; agent --version >/dev/null; agent --help >/dev/null ;;
45
+ opencode) expected_executable=opencode ;;
46
+ codex) expected_executable=codex ;;
47
+ cursor) expected_executable=agent ;;
49
48
  *) echo "Unsupported agent provider: $provider" >&2; exit 1 ;;
50
49
  esac
50
+ executable="${executables[$index]:-${AGENT_EXECUTABLE:-$expected_executable}}"
51
+ [[ "${executable##*/}" == "$expected_executable" ]] || { echo "Invalid $provider executable basename." >&2; exit 1; }
52
+ if ! command -v "$executable" >/dev/null 2>&1; then
53
+ [[ "$executable" == "$expected_executable" ]] || { echo "Configured executable is missing: $executable" >&2; exit 1; }
54
+ install_home="$RUNNER_TEMP/copilot-agent-$provider-$GITHUB_RUN_ID-$GITHUB_RUN_ATTEMPT"
55
+ mkdir -p "$install_home"
56
+ case "$provider" in
57
+ codex)
58
+ curl -fsSL https://chatgpt.com/codex/install.sh | env HOME="$install_home" CODEX_HOME="$install_home/.codex" CODEX_INSTALL_DIR="$install_home/bin" CODEX_NON_INTERACTIVE=1 sh
59
+ export PATH="$install_home/bin:$PATH"
60
+ ;;
61
+ opencode)
62
+ curl -fsSL https://opencode.ai/install | env HOME="$install_home" bash -s -- --no-modify-path
63
+ export PATH="$install_home/.opencode/bin:$PATH"
64
+ ;;
65
+ cursor)
66
+ curl -fsSL https://cursor.com/install | env HOME="$install_home" bash
67
+ export PATH="$install_home/.local/bin:$PATH"
68
+ ;;
69
+ esac
70
+ fi
71
+ actual_version="$($executable --version | head -n 1)"
72
+ [[ -n "${actual_version// }" ]] || { echo "$provider returned empty version output" >&2; exit 1; }
73
+ "$executable" --help >/dev/null
74
+ [[ " $checked " == *" $provider "* ]] || checked="$checked $provider"
51
75
  done
52
76
 
53
77
  echo "Agent CLI contract passed for: $checked."
@@ -33,17 +33,17 @@ jobs:
33
33
  inactivity-threshold-hours: ${{ inputs.inactivity_threshold_hours || vars.INACTIVITY_THRESHOLD_HOURS || '168' }}
34
34
  agent-provider: ${{ vars.AGENT_PROVIDER || 'codex' }}
35
35
  agent-model-provider: ${{ vars.AGENT_MODEL_PROVIDER || 'openai' }}
36
- agent-model: ${{ vars.AGENT_MODEL || 'gpt-5.6-luna' }}
36
+ agent-model: ${{ vars.AGENT_MODEL || 'gpt-6-luna' }}
37
37
  agent-effort: ${{ vars.AGENT_EFFORT }}
38
- agent-command: ${{ vars.AGENT_COMMAND }}
38
+ agent-executable: ${{ vars.AGENT_EXECUTABLE }}
39
39
  findings-provider: ${{ vars.FINDINGS_PROVIDER }}
40
40
  findings-model-provider: ${{ vars.FINDINGS_MODEL_PROVIDER }}
41
41
  findings-model: ${{ vars.FINDINGS_MODEL }}
42
42
  findings-effort: ${{ vars.FINDINGS_EFFORT }}
43
- findings-command: ${{ vars.FINDINGS_COMMAND }}
43
+ findings-executable: ${{ vars.FINDINGS_EXECUTABLE }}
44
44
  fixer-provider: ${{ vars.FIXER_PROVIDER }}
45
45
  fixer-model-provider: ${{ vars.FIXER_MODEL_PROVIDER }}
46
46
  fixer-model: ${{ vars.FIXER_MODEL }}
47
47
  fixer-effort: ${{ vars.FIXER_EFFORT }}
48
- fixer-command: ${{ vars.FIXER_COMMAND }}
48
+ fixer-executable: ${{ vars.FIXER_EXECUTABLE }}
49
49
  token: ${{ secrets.PAT }}