@bridge_gpt/mcp-server 0.2.24 → 0.2.26
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 +98 -28
- package/build/agents.generated.js +1 -1
- package/build/bridge-api-urls.js +31 -0
- package/build/commands.generated.js +5 -5
- package/build/conductor/epic-reconcile.js +7 -1
- package/build/conductor/epic-runtime.js +5 -0
- package/build/conductor-bundle-artifacts.js +802 -0
- package/build/conductor-bundle-cli.js +256 -0
- package/build/connect-github-api.js +365 -0
- package/build/connect-github.js +415 -0
- package/build/decision-page-schema.js +34 -5
- package/build/decision-page-template.js +117 -35
- package/build/docs.generated.js +2 -1
- package/build/doctor.js +148 -1
- package/build/env-flags.js +31 -0
- package/build/index.js +3467 -498
- package/build/init.js +7 -3
- package/build/install-bridge.js +624 -38
- package/build/install-doctor.js +64 -0
- package/build/mcp-host-config.js +521 -0
- package/build/mcp-host-targets.js +194 -0
- package/build/mcp-install-state.js +175 -0
- package/build/pipelines.generated.js +127 -132
- package/build/readme.generated.js +1 -1
- package/build/start-tickets.js +166 -18
- package/build/tool-surface-gating.js +396 -0
- package/build/version.generated.js +1 -1
- package/docs/install/github-app.md +80 -17
- package/docs/install/mcp-tool-integrations.md +2 -2
- package/package.json +5 -5
- package/pipelines/learn-repository.json +111 -119
- package/public/css/main.min.css +258 -65
- package/public/css/main.min.css.map +1 -1
- package/public/js/main.min.js +188 -92
- package/public/js/main.min.js.map +1 -1
- package/smoke-test/SMOKE-TEST.md +4 -4
package/public/js/main.min.js
CHANGED
|
@@ -1842,6 +1842,10 @@ const GITHUB_CONNECT_MESSAGES = {
|
|
|
1842
1842
|
'already-consumed': 'This GitHub connection link has already been used. Please start the connection again.',
|
|
1843
1843
|
'unresolved': 'GitHub returned without completing the connection. Please try again.',
|
|
1844
1844
|
'no-repositories': 'The GitHub App installation did not include any repositories Bridge can access.',
|
|
1845
|
+
// Honest about the dead end (BAPI-631): GitHub sends the org owner an approval
|
|
1846
|
+
// request out-of-band, and their approval does not redirect back here. Waiting on
|
|
1847
|
+
// this page accomplishes nothing, so say so and point at the fallback that works.
|
|
1848
|
+
'awaiting-organization-approval': 'Your request to install the GitHub App was sent to an organization owner for approval. Approval happens on GitHub and will not return you to this page, so waiting here will not finish the connection. Once an owner approves the install, use the manual fallback below to finish connecting.',
|
|
1845
1849
|
'already-linked': 'This GitHub installation is already connected to a different Bridge account. If this is unexpected, contact support.',
|
|
1846
1850
|
'binding-failed': 'GitHub was verified, but Bridge could not finish linking the repository. Use the manual fallback below.',
|
|
1847
1851
|
pickerLoading: 'Loading the repositories from your GitHub installation…',
|
|
@@ -1850,10 +1854,33 @@ const GITHUB_CONNECT_MESSAGES = {
|
|
|
1850
1854
|
connectedTitle: 'GitHub connected',
|
|
1851
1855
|
};
|
|
1852
1856
|
|
|
1857
|
+
// User-facing copy for the optional editor/MCP section and the install-key
|
|
1858
|
+
// outcomes (BAPI-630). GitHub-specific feedback stays in the sanitized
|
|
1859
|
+
// GITHUB_CONNECT_MESSAGES map above — these two surfaces are deliberately
|
|
1860
|
+
// separate so MCP failure copy can never claim the GitHub task failed.
|
|
1861
|
+
const UI_STRINGS = {
|
|
1862
|
+
// Scopes an install-instructions failure to the optional section. Prefixed
|
|
1863
|
+
// onto the detail resolved by getApiErrorMessage() so the user learns which
|
|
1864
|
+
// area failed and that the primary GitHub task is unaffected.
|
|
1865
|
+
mcpErrorScope: 'Editor and MCP setup instructions could not be loaded. Connecting GitHub above is unaffected and still available.',
|
|
1866
|
+
mcpMissingProject: 'Missing projectId — please navigate here from your project dashboard.',
|
|
1867
|
+
installKeyInserted: 'Admin install key generated and inserted into the snippets.',
|
|
1868
|
+
// Zero snippet slots: report the limitation truthfully rather than claiming
|
|
1869
|
+
// an insertion that did not happen (BAPI-630 / CI-2).
|
|
1870
|
+
installKeyNoSlots: 'Admin install key generated, but no editor snippets were available for automatic insertion. Copy the key below, or retry loading the optional editor and MCP instructions.',
|
|
1871
|
+
};
|
|
1872
|
+
|
|
1853
1873
|
// Holds the plaintext minted key for the current page lifetime ONLY. Never
|
|
1854
1874
|
// persisted to storage, cookies, URLs, datasets, or sent back to the server.
|
|
1855
1875
|
let generatedInstallKey = null;
|
|
1856
1876
|
|
|
1877
|
+
// The project's repository name, initialized once from the server-rendered
|
|
1878
|
+
// container dataset and thereafter kept in module state. Both the GitHub
|
|
1879
|
+
// connect and install-key actions read it from here, so neither re-reads the
|
|
1880
|
+
// dataset per action and the install-instructions response never has to write
|
|
1881
|
+
// a value back into the DOM.
|
|
1882
|
+
let currentRepoName = '';
|
|
1883
|
+
|
|
1857
1884
|
// ============================================================
|
|
1858
1885
|
// Clipboard helper
|
|
1859
1886
|
// ============================================================
|
|
@@ -2303,6 +2330,26 @@ function renderInstallStatus(installStatus, projectId) {
|
|
|
2303
2330
|
// Data loading
|
|
2304
2331
|
// ============================================================
|
|
2305
2332
|
|
|
2333
|
+
// Reveal an optional-section error. The error region lives inside the MCP
|
|
2334
|
+
// drawer, which is collapsed by default — so expanding the drawer through the
|
|
2335
|
+
// shared utility is what actually makes the message visible. Without this the
|
|
2336
|
+
// failure would be silent, which is the exact mode BAPI-630 removes. Only the
|
|
2337
|
+
// MCP drawer is touched; no GitHub control or status region is involved.
|
|
2338
|
+
function showMcpError(message) {
|
|
2339
|
+
const errorEl = document.getElementById('get-started-error');
|
|
2340
|
+
const msgEl = document.getElementById('get-started-error-msg');
|
|
2341
|
+
if (msgEl) msgEl.textContent = message;
|
|
2342
|
+
if (errorEl) errorEl.classList.remove('hidden');
|
|
2343
|
+
|
|
2344
|
+
const drawer = document.querySelector('#get-started-container .get-started-mcp-drawer');
|
|
2345
|
+
if (drawer) (0,_utils_js__WEBPACK_IMPORTED_MODULE_1__.setDrawerExpanded)(drawer, true);
|
|
2346
|
+
}
|
|
2347
|
+
|
|
2348
|
+
// Loads the OPTIONAL editor/MCP instructions. Scope discipline (BAPI-630): this
|
|
2349
|
+
// function may only touch #get-started-loading, #get-started-error, and
|
|
2350
|
+
// #get-started-content. It must never hide, reveal, or gate any GitHub control,
|
|
2351
|
+
// status, result, picker, or fallback region — a failure here is not a failure
|
|
2352
|
+
// of the page's primary task.
|
|
2306
2353
|
async function loadInstallInstructions(projectId) {
|
|
2307
2354
|
const loadingEl = document.getElementById('get-started-loading');
|
|
2308
2355
|
const errorEl = document.getElementById('get-started-error');
|
|
@@ -2323,12 +2370,12 @@ async function loadInstallInstructions(projectId) {
|
|
|
2323
2370
|
|
|
2324
2371
|
if (loadingEl) loadingEl.classList.add('hidden');
|
|
2325
2372
|
|
|
2326
|
-
//
|
|
2327
|
-
//
|
|
2328
|
-
//
|
|
2329
|
-
const
|
|
2330
|
-
if (
|
|
2331
|
-
|
|
2373
|
+
// Keep the shared repo-name state authoritative from the payload, but
|
|
2374
|
+
// never let an empty/whitespace response erase a valid server-rendered
|
|
2375
|
+
// value. Held in module state — not written back into the dataset.
|
|
2376
|
+
const responseRepoName = (data.repo_name || '').trim();
|
|
2377
|
+
if (responseRepoName) {
|
|
2378
|
+
currentRepoName = responseRepoName;
|
|
2332
2379
|
}
|
|
2333
2380
|
|
|
2334
2381
|
const repoLabel = document.getElementById('get-started-repo-label');
|
|
@@ -2341,19 +2388,15 @@ async function loadInstallInstructions(projectId) {
|
|
|
2341
2388
|
renderInstallStatus(data.install_status, projectId);
|
|
2342
2389
|
|
|
2343
2390
|
if (contentEl) contentEl.classList.remove('hidden');
|
|
2344
|
-
|
|
2345
|
-
// Render any GitHub connection return-state now that the repo dataset is
|
|
2346
|
-
// synchronized from the install-instructions payload (BAPI-506).
|
|
2347
|
-
renderGitHubConnectionReturnState();
|
|
2348
2391
|
} catch (error) {
|
|
2349
2392
|
if (loadingEl) loadingEl.classList.add('hidden');
|
|
2350
2393
|
if (contentEl) contentEl.classList.add('hidden');
|
|
2351
2394
|
|
|
2352
|
-
|
|
2353
|
-
|
|
2354
|
-
|
|
2355
|
-
|
|
2356
|
-
|
|
2395
|
+
// The scoped sentence is the message; the shared sanitizer's detail rides
|
|
2396
|
+
// along parenthetically as a diagnostic aside so it reads as an aside
|
|
2397
|
+
// rather than a dangling fragment of the sentence before it.
|
|
2398
|
+
const detail = (0,_utils_js__WEBPACK_IMPORTED_MODULE_1__.getApiErrorMessage)(error, 'Failed to load install instructions.');
|
|
2399
|
+
showMcpError(`${UI_STRINGS.mcpErrorScope} (${detail})`);
|
|
2357
2400
|
}
|
|
2358
2401
|
}
|
|
2359
2402
|
|
|
@@ -2379,11 +2422,18 @@ function setInstallKeyLoading(loading) {
|
|
|
2379
2422
|
const btn = document.getElementById('generate-install-key-btn');
|
|
2380
2423
|
const panel = document.getElementById('install-key-panel');
|
|
2381
2424
|
const errorEl = document.getElementById('install-key-error');
|
|
2425
|
+
const statusEl = document.getElementById('install-key-status');
|
|
2382
2426
|
if (loading) {
|
|
2383
2427
|
if (errorEl) {
|
|
2384
2428
|
errorEl.textContent = '';
|
|
2385
2429
|
errorEl.classList.add('hidden');
|
|
2386
2430
|
}
|
|
2431
|
+
// Drop any prior success/warning styling so a new attempt cannot inherit
|
|
2432
|
+
// the semantics of the last one. Never logs or exposes the key itself.
|
|
2433
|
+
if (statusEl) {
|
|
2434
|
+
statusEl.classList.remove('install-key-status--success', 'install-key-status--warning');
|
|
2435
|
+
statusEl.textContent = 'Generating the admin install key…';
|
|
2436
|
+
}
|
|
2387
2437
|
if (btn) {
|
|
2388
2438
|
btn.disabled = true;
|
|
2389
2439
|
btn.textContent = 'Generating…';
|
|
@@ -2419,7 +2469,7 @@ async function handleGenerateInstallKeyClick() {
|
|
|
2419
2469
|
// Security page, so we accept this over reusing/auto-revoking prior keys.
|
|
2420
2470
|
if (generatedInstallKey) return;
|
|
2421
2471
|
|
|
2422
|
-
const repoName =
|
|
2472
|
+
const repoName = getGitHubRepoName();
|
|
2423
2473
|
if (!repoName) {
|
|
2424
2474
|
showInstallKeyError('Could not generate the install key. Please try again.');
|
|
2425
2475
|
return;
|
|
@@ -2478,10 +2528,21 @@ async function handleGenerateInstallKeyClick() {
|
|
|
2478
2528
|
const resultEl = document.getElementById('install-key-result');
|
|
2479
2529
|
if (resultEl) resultEl.classList.remove('hidden');
|
|
2480
2530
|
|
|
2481
|
-
injectInstallKeyIntoSnippets
|
|
2531
|
+
// Report what actually happened. injectInstallKeyIntoSnippets returns the
|
|
2532
|
+
// number of slots it filled; zero means the snippets were never rendered
|
|
2533
|
+
// (e.g. the optional MCP fetch failed), so claiming insertion would be a
|
|
2534
|
+
// lie the user cannot verify (BAPI-630 / CI-2).
|
|
2535
|
+
const insertedSlotCount = injectInstallKeyIntoSnippets(apiKey);
|
|
2482
2536
|
|
|
2483
2537
|
const statusEl = document.getElementById('install-key-status');
|
|
2484
|
-
if (statusEl)
|
|
2538
|
+
if (statusEl) {
|
|
2539
|
+
const inserted = insertedSlotCount > 0;
|
|
2540
|
+
statusEl.textContent = inserted
|
|
2541
|
+
? UI_STRINGS.installKeyInserted
|
|
2542
|
+
: UI_STRINGS.installKeyNoSlots;
|
|
2543
|
+
statusEl.classList.toggle('install-key-status--success', inserted);
|
|
2544
|
+
statusEl.classList.toggle('install-key-status--warning', !inserted);
|
|
2545
|
+
}
|
|
2485
2546
|
|
|
2486
2547
|
// Permanently disable the button after success to avoid repeated minting.
|
|
2487
2548
|
const btn = document.getElementById('generate-install-key-btn');
|
|
@@ -2536,9 +2597,7 @@ function initializeInstallKeyGeneration(container) {
|
|
|
2536
2597
|
// ============================================================
|
|
2537
2598
|
|
|
2538
2599
|
function getGitHubRepoName() {
|
|
2539
|
-
|
|
2540
|
-
const repoName = container && container.dataset ? container.dataset.repoName : '';
|
|
2541
|
-
return (repoName || '').trim();
|
|
2600
|
+
return currentRepoName;
|
|
2542
2601
|
}
|
|
2543
2602
|
|
|
2544
2603
|
function setGitHubConnectLoading(loading) {
|
|
@@ -2756,6 +2815,11 @@ function init() {
|
|
|
2756
2815
|
const container = document.getElementById('get-started-container');
|
|
2757
2816
|
if (!container) return;
|
|
2758
2817
|
|
|
2818
|
+
// Seed the shared repo-name state once from the server-rendered dataset.
|
|
2819
|
+
// Every later read goes through module state, so the GitHub button works on
|
|
2820
|
+
// first paint without waiting for the optional MCP fetch (BAPI-630).
|
|
2821
|
+
currentRepoName = ((container.dataset && container.dataset.repoName) || '').trim();
|
|
2822
|
+
|
|
2759
2823
|
(0,_modal_js__WEBPACK_IMPORTED_MODULE_0__.initModal)();
|
|
2760
2824
|
|
|
2761
2825
|
// Click-driven install-key generation; does not mint a key on page load.
|
|
@@ -2764,6 +2828,11 @@ function init() {
|
|
|
2764
2828
|
// Wire the "Connect GitHub" launch button (BAPI-506).
|
|
2765
2829
|
initializeGitHubConnect();
|
|
2766
2830
|
|
|
2831
|
+
// Render any ?githubConnection=<status> return state here — NOT from the
|
|
2832
|
+
// install-instructions success path. A user coming back from GitHub must
|
|
2833
|
+
// see the outcome even when the optional MCP fetch fails (BAPI-630 / R1).
|
|
2834
|
+
renderGitHubConnectionReturnState();
|
|
2835
|
+
|
|
2767
2836
|
// Bind keyboard navigation once — renderSnippetTabs may run multiple times (retry),
|
|
2768
2837
|
// so binding here prevents the listener from stacking on the tabList element.
|
|
2769
2838
|
const tabList = document.getElementById('editor-tabs');
|
|
@@ -2809,11 +2878,8 @@ function init() {
|
|
|
2809
2878
|
|
|
2810
2879
|
if (!projectId) {
|
|
2811
2880
|
const loadingEl = document.getElementById('get-started-loading');
|
|
2812
|
-
const errorEl = document.getElementById('get-started-error');
|
|
2813
|
-
const msgEl = document.getElementById('get-started-error-msg');
|
|
2814
2881
|
if (loadingEl) loadingEl.classList.add('hidden');
|
|
2815
|
-
|
|
2816
|
-
if (errorEl) errorEl.classList.remove('hidden');
|
|
2882
|
+
showMcpError(UI_STRINGS.mcpMissingProject);
|
|
2817
2883
|
return;
|
|
2818
2884
|
}
|
|
2819
2885
|
|
|
@@ -5108,10 +5174,12 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
5108
5174
|
/* harmony export */ resetProjectDetailBaseline: () => (/* binding */ resetProjectDetailBaseline),
|
|
5109
5175
|
/* harmony export */ setupConditionalVisibilityListeners: () => (/* binding */ setupConditionalVisibilityListeners),
|
|
5110
5176
|
/* harmony export */ setupValidationListeners: () => (/* binding */ setupValidationListeners),
|
|
5177
|
+
/* harmony export */ shouldWarnForBlankCriticalPriorities: () => (/* binding */ shouldWarnForBlankCriticalPriorities),
|
|
5111
5178
|
/* harmony export */ toggleCiFollowupControlsVisibility: () => (/* binding */ toggleCiFollowupControlsVisibility),
|
|
5112
5179
|
/* harmony export */ toggleDeepResearchTimeoutVisibility: () => (/* binding */ toggleDeepResearchTimeoutVisibility),
|
|
5113
5180
|
/* harmony export */ toggleStoryPointsFieldVisibility: () => (/* binding */ toggleStoryPointsFieldVisibility),
|
|
5114
5181
|
/* harmony export */ updateCiFollowupInstructionsByteCounter: () => (/* binding */ updateCiFollowupInstructionsByteCounter),
|
|
5182
|
+
/* harmony export */ updateCriticalPrioritiesWarning: () => (/* binding */ updateCriticalPrioritiesWarning),
|
|
5115
5183
|
/* harmony export */ validateInput: () => (/* binding */ validateInput),
|
|
5116
5184
|
/* harmony export */ validateReviewPolicyOverrides: () => (/* binding */ validateReviewPolicyOverrides)
|
|
5117
5185
|
/* harmony export */ });
|
|
@@ -5142,6 +5210,44 @@ const estimateScaleJsonErrorDiv = document.getElementById('estimate_scale-error'
|
|
|
5142
5210
|
// are sent to the backend.
|
|
5143
5211
|
let projectDetailBaseline = null;
|
|
5144
5212
|
|
|
5213
|
+
// --- BAPI-590: critical-priorities blank-configuration warning ---
|
|
5214
|
+
// Non-blocking signal shown when the critical-priorities check is enabled but no
|
|
5215
|
+
// priorities are configured (the check is silently skipped). Defined once at
|
|
5216
|
+
// module scope so the client- and route-side copies stay identical.
|
|
5217
|
+
const CRITICAL_PRIORITIES_BLANK_WARNING =
|
|
5218
|
+
'Critical-priorities checking is enabled, but no priorities are configured; this check will be skipped.';
|
|
5219
|
+
|
|
5220
|
+
/**
|
|
5221
|
+
* Whether the blank-priorities warning condition holds: the check is enabled and
|
|
5222
|
+
* the priorities textarea is empty after trimming whitespace. Reads the checkbox
|
|
5223
|
+
* and textarea directly from the DOM and is safe to call when either control is
|
|
5224
|
+
* absent (returns false).
|
|
5225
|
+
* @returns {boolean}
|
|
5226
|
+
*/
|
|
5227
|
+
function shouldWarnForBlankCriticalPriorities() {
|
|
5228
|
+
const toggle = document.getElementById('check_critical_priorities');
|
|
5229
|
+
const textarea = document.getElementById('critical_priorities');
|
|
5230
|
+
if (!toggle || !textarea) return false;
|
|
5231
|
+
return !!toggle.checked && (textarea.value || '').trim() === '';
|
|
5232
|
+
}
|
|
5233
|
+
|
|
5234
|
+
/**
|
|
5235
|
+
* Show or hide the dedicated critical-priorities warning container from the
|
|
5236
|
+
* current control state. Guards every DOM lookup, sets text via textContent, and
|
|
5237
|
+
* toggles only the `.hidden` class on the warning node (never inline display).
|
|
5238
|
+
*/
|
|
5239
|
+
function updateCriticalPrioritiesWarning() {
|
|
5240
|
+
const warningEl = document.getElementById('critical_priorities-warning');
|
|
5241
|
+
if (!warningEl) return;
|
|
5242
|
+
if (shouldWarnForBlankCriticalPriorities()) {
|
|
5243
|
+
warningEl.textContent = CRITICAL_PRIORITIES_BLANK_WARNING;
|
|
5244
|
+
warningEl.classList.remove('hidden');
|
|
5245
|
+
} else {
|
|
5246
|
+
warningEl.textContent = '';
|
|
5247
|
+
warningEl.classList.add('hidden');
|
|
5248
|
+
}
|
|
5249
|
+
}
|
|
5250
|
+
|
|
5145
5251
|
// --- Custom DOM value readers for fields the shared diff util cannot read by id ---
|
|
5146
5252
|
|
|
5147
5253
|
/**
|
|
@@ -5952,10 +6058,22 @@ function setupConditionalVisibilityListeners() {
|
|
|
5952
6058
|
reviewPolicyResetAll.addEventListener('click', handleReviewPolicyResetAll);
|
|
5953
6059
|
}
|
|
5954
6060
|
|
|
5955
|
-
//
|
|
6061
|
+
// BAPI-590: refresh the non-blocking critical-priorities warning whenever the
|
|
6062
|
+
// check is toggled or the priorities text changes.
|
|
6063
|
+
const checkCriticalPriorities = document.getElementById('check_critical_priorities');
|
|
6064
|
+
if (checkCriticalPriorities) {
|
|
6065
|
+
checkCriticalPriorities.addEventListener('change', updateCriticalPrioritiesWarning);
|
|
6066
|
+
}
|
|
6067
|
+
const criticalPriorities = document.getElementById('critical_priorities');
|
|
6068
|
+
if (criticalPriorities) {
|
|
6069
|
+
criticalPriorities.addEventListener('input', updateCriticalPrioritiesWarning);
|
|
6070
|
+
}
|
|
6071
|
+
|
|
6072
|
+
// Apply initial state for all dependent regions before baseline capture.
|
|
5956
6073
|
toggleDeepResearchTimeoutVisibility();
|
|
5957
6074
|
toggleStoryPointsFieldVisibility();
|
|
5958
6075
|
toggleCiFollowupControlsVisibility();
|
|
6076
|
+
updateCriticalPrioritiesWarning();
|
|
5959
6077
|
}
|
|
5960
6078
|
|
|
5961
6079
|
// Canonical descriptor list driving baseline capture, sparse diffing, section
|
|
@@ -6009,21 +6127,13 @@ const PROJECT_DETAIL_FIELD_DESCRIPTORS = [
|
|
|
6009
6127
|
{ field: 'backend_correctness_standards', type: 'text', id: 'backend_correctness_standards' },
|
|
6010
6128
|
{ field: 'template_correctness_standards', type: 'text', id: 'template_correctness_standards' },
|
|
6011
6129
|
{ field: 'style_correctness_standards', type: 'text', id: 'style_correctness_standards' },
|
|
6012
|
-
|
|
6013
|
-
|
|
6014
|
-
|
|
6015
|
-
|
|
6016
|
-
{ field: 'backend_styleguide', type: 'text', id: 'backend_styleguide' },
|
|
6017
|
-
{ field: 'css_styleguide', type: 'text', id: 'css_styleguide' },
|
|
6018
|
-
{ field: 'review_correctness', type: 'boolean', id: 'review_correctness' },
|
|
6019
|
-
{ field: 'review_style', type: 'boolean', id: 'review_style' },
|
|
6130
|
+
// BAPI-590: the simplified two-check reviewer surface (requirements check +
|
|
6131
|
+
// critical-priorities check/text). The legacy reviewer controls (style guides,
|
|
6132
|
+
// file types, include/exclude paths, correctness/style/architecture toggles,
|
|
6133
|
+
// test/doc generation, documentation standards, score threshold) were removed.
|
|
6020
6134
|
{ field: 'review_requirements', type: 'boolean', id: 'review_requirements' },
|
|
6021
|
-
{ field: '
|
|
6022
|
-
{ field: '
|
|
6023
|
-
{ field: 'create_documentation', type: 'boolean', id: 'create_documentation' },
|
|
6024
|
-
{ field: 'documentation_standards', type: 'text', id: 'documentation_standards' },
|
|
6025
|
-
{ field: 'score_threshold_for_review', type: 'text', id: 'score_threshold_for_review' },
|
|
6026
|
-
{ field: 'no_comment_on_passing_score', type: 'boolean', id: 'no_comment_on_passing_score' },
|
|
6135
|
+
{ field: 'check_critical_priorities', type: 'boolean', id: 'check_critical_priorities' },
|
|
6136
|
+
{ field: 'critical_priorities', type: 'text', id: 'critical_priorities' },
|
|
6027
6137
|
];
|
|
6028
6138
|
|
|
6029
6139
|
// Maps each descriptor field to exactly one backend payload section. The four
|
|
@@ -6067,21 +6177,9 @@ const FIELD_TO_SECTION = {
|
|
|
6067
6177
|
backend_correctness_standards: 'code_reviewer',
|
|
6068
6178
|
template_correctness_standards: 'code_reviewer',
|
|
6069
6179
|
style_correctness_standards: 'code_reviewer',
|
|
6070
|
-
reviewable_file_types: 'code_reviewer',
|
|
6071
|
-
include_path: 'code_reviewer',
|
|
6072
|
-
exclude_path: 'code_reviewer',
|
|
6073
|
-
frontend_styleguide: 'code_reviewer',
|
|
6074
|
-
backend_styleguide: 'code_reviewer',
|
|
6075
|
-
css_styleguide: 'code_reviewer',
|
|
6076
|
-
review_correctness: 'code_reviewer',
|
|
6077
|
-
review_style: 'code_reviewer',
|
|
6078
6180
|
review_requirements: 'code_reviewer',
|
|
6079
|
-
|
|
6080
|
-
|
|
6081
|
-
create_documentation: 'code_reviewer',
|
|
6082
|
-
documentation_standards: 'code_reviewer',
|
|
6083
|
-
score_threshold_for_review: 'code_reviewer',
|
|
6084
|
-
no_comment_on_passing_score: 'code_reviewer',
|
|
6181
|
+
check_critical_priorities: 'code_reviewer',
|
|
6182
|
+
critical_priorities: 'code_reviewer',
|
|
6085
6183
|
};
|
|
6086
6184
|
|
|
6087
6185
|
/**
|
|
@@ -6113,8 +6211,7 @@ function getChangedFieldEntries() {
|
|
|
6113
6211
|
|
|
6114
6212
|
/**
|
|
6115
6213
|
* Final payload value for a changed field. Most fields use their normalized diff
|
|
6116
|
-
* value as-is; estimate_scale
|
|
6117
|
-
* save shaping.
|
|
6214
|
+
* value as-is; estimate_scale keeps its existing save shaping.
|
|
6118
6215
|
* @param {string} fieldName
|
|
6119
6216
|
* @param {*} changedValue - normalized value from the diff result
|
|
6120
6217
|
* @param {string|null} estimateScaleValue - validated estimate-scale string
|
|
@@ -6124,9 +6221,6 @@ function getPayloadValueForField(fieldName, changedValue, estimateScaleValue = n
|
|
|
6124
6221
|
if (fieldName === 'estimate_scale') {
|
|
6125
6222
|
return estimateScaleValue;
|
|
6126
6223
|
}
|
|
6127
|
-
if (fieldName === 'score_threshold_for_review') {
|
|
6128
|
-
return parseInt(changedValue, 10) || 85;
|
|
6129
|
-
}
|
|
6130
6224
|
if (fieldName === 'deep_research_stall_timeout_minutes') {
|
|
6131
6225
|
return changedValue === '' ? null : parseInt(changedValue, 10);
|
|
6132
6226
|
}
|
|
@@ -6208,23 +6302,11 @@ const EXPLANATION_TEXTS = {
|
|
|
6208
6302
|
'pwa_overrides_directories': 'Specify the directories that contain your PWA Kit template overrides. Enter one directory path per line (e.g., `overrides`, `app/templates`, `custom-overrides`). These directories will be given special consideration when the AI generates or modifies code.',
|
|
6209
6303
|
'frontend_correctness_standards': 'Describe how the AI should review frontend Javascript. Consider project standards, error handling, data validation, etc. Required.',
|
|
6210
6304
|
'backend_correctness_standards': 'Describe how the AI should review backend code. Consider project standards, error handling, data validation, security, best practices',
|
|
6211
|
-
'reviewable_file_types': 'List the file suffixes (e.g., `js, isml, scss`) the AI should review. Required.',
|
|
6212
|
-
'include_path': 'Specify directory paths (one per line) to include in reviews. Prevents reviewing third-party code. Recommended.',
|
|
6213
|
-
'exclude_path': 'Specify directory paths (one per line) to exclude from reviews, even if they are within an included path. Recommended.',
|
|
6214
6305
|
'template_correctness_standards': 'Define standards for reviewing template code (e.g., HTML, ISML), focusing on issues like accessibility. Recommended. If blank, template correctness is skipped.',
|
|
6215
6306
|
'style_correctness_standards': 'Define standards for reviewing CSS/SASS/LESS code. Optional. If blank, style correctness for these files is skipped.',
|
|
6216
|
-
'
|
|
6217
|
-
'
|
|
6218
|
-
'
|
|
6219
|
-
'review_correctness': 'Enable/disable checking code for bugs and errors. Defaults to true. Optional.',
|
|
6220
|
-
'review_style': 'Enable/disable checking code for style guide adherence. Defaults to true. Optional.',
|
|
6221
|
-
'review_requirements': 'Enable/disable checking if the PR fulfills ticket requirements (requires ticket ID in branch/commit). Best for initial commits. Defaults to true. Optional.',
|
|
6222
|
-
'review_architecture': 'Enable/disable checking for integration errors and correctness (if correctness review is off). Defaults to true. Optional.',
|
|
6223
|
-
'create_tests': 'Enable/disable AI generation of unit/integration tests for the PR. Defaults to false. Optional.',
|
|
6224
|
-
'create_documentation': 'Enable/disable AI generation of documentation for the PR. Defaults to false. Optional.',
|
|
6225
|
-
'documentation_standards': 'If `Create Documentation` is enabled, describe the desired documentation format and standards here. Optional.',
|
|
6226
|
-
'score_threshold_for_review': 'Set a score (0-100) below which the AI will perform a review. Files scoring at or above this threshold are considered passing. Defaults to 85. Optional.',
|
|
6227
|
-
'no_comment_on_passing_score': 'If enabled, the AI will not leave a comment on files with a passing score. If disabled, it leaves a positive comment (e.g., "Looks good!"). Defaults to true (no comment). Optional.',
|
|
6307
|
+
'review_requirements': 'When enabled, the code reviewer checks whether the pull request actually covers the ticket\'s stated requirements (requires a ticket ID in the branch or commit). Best for initial commits. Defaults to enabled.',
|
|
6308
|
+
'check_critical_priorities': 'When enabled, the code reviewer additionally checks each pull request against the Critical Priorities you configure below. If this check is on but no priorities are configured, the check is skipped.',
|
|
6309
|
+
'critical_priorities': 'The critical priorities the code reviewer holds every pull request to (e.g., "Never log secrets or PII", "All DB writes must be repo-scoped"). Leave blank to skip the critical-priorities check even when it is enabled.',
|
|
6228
6310
|
'schedule_interval': 'How frequently should the repository parsing job run? This is measured in days (e.g., every 1 day, 2 days, etc.).',
|
|
6229
6311
|
'schedule_timezone': 'The timezone for scheduling repository parsing jobs. We will run this job daily at 1:00 AM according to the timezone you select.',
|
|
6230
6312
|
'deep_research_enabled': 'Enable or disable AI deep research for this project. When enabled, the MCP tool can perform in-depth web research on technical topics using the default Deep Research provider. Defaults to enabled.',
|
|
@@ -6513,24 +6595,18 @@ function populateProjectForms(data) {
|
|
|
6513
6595
|
if (el) el.value = reviewer[field] || '';
|
|
6514
6596
|
});
|
|
6515
6597
|
|
|
6516
|
-
// Code Reviewer Form (
|
|
6598
|
+
// Code Reviewer Form (BAPI-590: simplified two-check surface). The legacy
|
|
6599
|
+
// reviewer controls were removed, so only the requirements check and the
|
|
6600
|
+
// critical-priorities check/text are populated here.
|
|
6517
6601
|
if (codeReviewForm) {
|
|
6518
|
-
codeReviewForm.elements.reviewable_file_types.value = (0,_utils_js__WEBPACK_IMPORTED_MODULE_1__.arrayToString)(reviewer.reviewable_file_types || []);
|
|
6519
|
-
codeReviewForm.elements.include_path.value = (reviewer.include_path || []).join('\n');
|
|
6520
|
-
codeReviewForm.elements.exclude_path.value = (reviewer.exclude_path || []).join('\n');
|
|
6521
|
-
codeReviewForm.elements.frontend_styleguide.value = reviewer.frontend_styleguide || '';
|
|
6522
|
-
codeReviewForm.elements.backend_styleguide.value = reviewer.backend_styleguide || '';
|
|
6523
|
-
codeReviewForm.elements.css_styleguide.value = reviewer.css_styleguide || '';
|
|
6524
|
-
codeReviewForm.elements.review_correctness.checked = reviewer.review_correctness !== undefined ? reviewer.review_correctness : true;
|
|
6525
|
-
codeReviewForm.elements.review_style.checked = reviewer.review_style !== undefined ? reviewer.review_style : true;
|
|
6526
6602
|
codeReviewForm.elements.review_requirements.checked = reviewer.review_requirements !== undefined ? reviewer.review_requirements : true;
|
|
6527
|
-
codeReviewForm.elements.
|
|
6528
|
-
codeReviewForm.elements.
|
|
6529
|
-
codeReviewForm.elements.create_documentation.checked = reviewer.create_documentation || false;
|
|
6530
|
-
codeReviewForm.elements.documentation_standards.value = reviewer.documentation_standards || '';
|
|
6531
|
-
codeReviewForm.elements.score_threshold_for_review.value = reviewer.score_threshold_for_review !== undefined ? reviewer.score_threshold_for_review : 85;
|
|
6532
|
-
codeReviewForm.elements.no_comment_on_passing_score.checked = reviewer.no_comment_on_passing_score !== undefined ? reviewer.no_comment_on_passing_score : true;
|
|
6603
|
+
codeReviewForm.elements.check_critical_priorities.checked = !!reviewer.check_critical_priorities;
|
|
6604
|
+
codeReviewForm.elements.critical_priorities.value = reviewer.critical_priorities || '';
|
|
6533
6605
|
}
|
|
6606
|
+
|
|
6607
|
+
// Surface an already-invalid persisted state (check enabled, priorities blank)
|
|
6608
|
+
// immediately after applying the returned reviewer values.
|
|
6609
|
+
updateCriticalPrioritiesWarning();
|
|
6534
6610
|
}
|
|
6535
6611
|
|
|
6536
6612
|
/**
|
|
@@ -6611,9 +6687,18 @@ async function handleSaveProject() {
|
|
|
6611
6687
|
const response = await (0,_utils_js__WEBPACK_IMPORTED_MODULE_1__.apiCall)(`/setup/project-detail/${currentProjectId}`, 'PUT', projectData);
|
|
6612
6688
|
|
|
6613
6689
|
if (response) {
|
|
6614
|
-
|
|
6615
|
-
//
|
|
6616
|
-
//
|
|
6690
|
+
// BAPI-590: keep the adjacent priorities warning visible after save, and
|
|
6691
|
+
// surface the route's optional warning as a saved-with-warning result
|
|
6692
|
+
// rather than presenting the (successful) save as a failure.
|
|
6693
|
+
updateCriticalPrioritiesWarning();
|
|
6694
|
+
const savedWarning = typeof response.warning === 'string' ? response.warning.trim() : '';
|
|
6695
|
+
if (savedWarning) {
|
|
6696
|
+
(0,_modal_js__WEBPACK_IMPORTED_MODULE_0__.showModal)('Saved with warning', `Project configuration saved.\n\n${savedWarning}`);
|
|
6697
|
+
} else {
|
|
6698
|
+
(0,_modal_js__WEBPACK_IMPORTED_MODULE_0__.showModal)('Success', 'Project configuration saved successfully!');
|
|
6699
|
+
}
|
|
6700
|
+
// Re-snapshot from the saved values (the route-level warning accompanies a
|
|
6701
|
+
// successful persist) so an immediate second save with no edits is clean.
|
|
6617
6702
|
resetProjectDetailBaseline();
|
|
6618
6703
|
}
|
|
6619
6704
|
// A null response is the centralized 401 redirect (handled by apiCall);
|
|
@@ -6768,6 +6853,11 @@ function validateAllForms() {
|
|
|
6768
6853
|
allValid = false;
|
|
6769
6854
|
}
|
|
6770
6855
|
|
|
6856
|
+
// BAPI-590: refresh the blank-priorities warning during pre-save validation.
|
|
6857
|
+
// This is a non-blocking signal only — it never sets custom validity, adds
|
|
6858
|
+
// `.input-error`, or flips `allValid`.
|
|
6859
|
+
updateCriticalPrioritiesWarning();
|
|
6860
|
+
|
|
6771
6861
|
return allValid;
|
|
6772
6862
|
}
|
|
6773
6863
|
|
|
@@ -6808,6 +6898,12 @@ function handleInputClearError(event) {
|
|
|
6808
6898
|
if (element.id === 'ci_followup_instructions') {
|
|
6809
6899
|
updateCiFollowupInstructionsByteCounter();
|
|
6810
6900
|
}
|
|
6901
|
+
// BAPI-590: the priorities warning lives in its own container (not the
|
|
6902
|
+
// `-error` node), so clearing a genuine field error never erases it; refresh
|
|
6903
|
+
// it here so live edits keep the warning state accurate.
|
|
6904
|
+
if (element.id === 'critical_priorities') {
|
|
6905
|
+
updateCriticalPrioritiesWarning();
|
|
6906
|
+
}
|
|
6811
6907
|
}
|
|
6812
6908
|
|
|
6813
6909
|
/**
|