@resolveio/server-lib 22.3.235 → 22.3.237
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/methods/ai-terminal.js +342 -206
- package/methods/ai-terminal.js.map +1 -1
- package/package.json +1 -1
- package/util/ai-qa-policy.js +21 -88
- package/util/ai-qa-policy.js.map +1 -1
- package/util/ai-run-evidence-adapters.js +236 -256
- package/util/ai-run-evidence-adapters.js.map +1 -1
- package/util/ai-run-evidence.js +30 -15
- package/util/ai-run-evidence.js.map +1 -1
- package/util/ai-runner-qa-tools.js +103 -2064
- package/util/ai-runner-qa-tools.js.map +1 -1
- package/util/support-runner-v5.d.ts +38 -13
- package/util/support-runner-v5.js +423 -735
- package/util/support-runner-v5.js.map +1 -1
package/package.json
CHANGED
package/util/ai-qa-policy.js
CHANGED
|
@@ -128,7 +128,7 @@ function buildResolveIOQaPolicyRules(options) {
|
|
|
128
128
|
var policy = normalizeResolveIOQaPolicyOptions(options);
|
|
129
129
|
var rules = [];
|
|
130
130
|
if (policy.includeDevServerRules) {
|
|
131
|
-
rules.push('When browser/localhost QA needs long-running commands like `npm run server`, `npm run client`, `npm run dev`, `ng serve`, `vite`, or `nodemon`, start them as managed background processes with log files and PIDs; do not leave foreground dev-server commands as the active shell tool.', 'Before localhost/browser QA, source `.resolveio-support-tools/env.sh` or `.resolveio-ai-runner-tools/env.sh` when present. It supplies shared EC2 browser cache settings, `PUPPETEER_EXECUTABLE_PATH`/`CHROME_BIN`, Mongo wrappers, and non-conflicting localhost QA ports/URLs.', 'For ResolveIO app login during browser QA, use the shared AI-runner auth bootstrap when staged: `node ./.resolveio-support-tools/qa-auth-bootstrap.js <project-root> /target-route`, `node ./.resolveio-ai-runner-tools/qa-auth-bootstrap.js <project-root> /target-route`, or the same command from an app root with `../`. It must use the exact localhost client origin, log out/clear stale browser credentials first, call `/login` then `/accessToken`, seed auth storage, repair the local QA user settings/tour flags if the app forces the post-login settings/tour gate, verify the browser reached the requested target route, and emit `qa-artifacts/auth-bootstrap-result.json`, `qa-artifacts/auth-bootstrap-storage-state.json`, plus a screenshot. For support-ticket QA, use Puppeteer first when `PUPPETEER_EXECUTABLE_PATH` or `CHROME_BIN` is set; `PLAYWRIGHT_MISSING` is not a blocker while that Puppeteer env exists. For every fresh Puppeteer/Playwright page, open the localhost origin, set localStorage from `auth-bootstrap-storage-state.json`, then navigate to the target route. The storage artifact may expose top-level object `localStorage`, array `localStorageEntries`, or Playwright-style `origins[].localStorage`; normalize all three shapes before setting storage (`Object.entries` for objects, `{key,value}` or `{name,value}` for arrays). Never run `for...of` directly on top-level `localStorage` unless it is already an array. A login-shell screenshot after bootstrap means the QA script failed to seed auth and must rerun the same row with storage seeded before returning needs-fix.', 'For support-ticket QA, run the browser as the ticket reporter whenever possible; if the ticket or latest customer response names another affected user, run as that affected user instead. Use `qa-live-data-seed-result.json.selected.qa_user_context` and `auth-bootstrap-result.json.user` to record the chosen user. Generic admin/dev QA is acceptable only when no reporter/affected user can be identified or copied into localhost QA; in that case the matrix must say why.', 'For ResolveIO browser checks, do not use Puppeteer/Playwright `networkidle0` or `networkidle2` as the page-ready condition; ResolveIO pages can keep background API/socket/polling activity open. Navigate with `domcontentloaded`, then wait for concrete route/workflow DOM text, buttons, table rows, dialogs, saved records, or persisted data assertions before screenshots.', 'Use browser API compatibility helpers instead of version-fragile calls: every row-level Puppeteer script must declare `const delay = ms => new Promise(resolve => setTimeout(resolve, ms));` before navigation and use `await delay(...)` for fixed waits. Do not use `page.$x`, `page.waitForTimeout`, `networkidle0`, or `networkidle2`. Use `page.evaluateHandle`/DOM traversal or Playwright `locator` when definitely using Playwright. If a browser helper call throws because the current runtime lacks that API, fix the QA script and rerun the same matrix row before marking it failed.', 'Browser click targeting must prefer exact interactive controls: `button`, `a[href]`, `[role="button"]`, `input[type="button"]`, `input[type="submit"]`, `select`, option/combobox controls, and app-specific clickable elements with a small visible bounding box. Do not include broad `div`, `span`, `body`, or `*` elements in click-by-text helpers; they often match whole-page containers and produce false progress. If a text match has a huge bounding box or contains unrelated page/navigation text, skip it and find a smaller descendant/control.', 'For QA row probes, use broad DOM text scans only for read-only diagnostics. Do not drive workflow clicks from broad `document.querySelectorAll("*")` or generic container matches. After at most two focused selector attempts on the seeded route/data, either capture the blocker screenshot and return `needs-fix`, or switch to persisted data assertions if the row can be proven without another UI click.', 'When launching Puppeteer on workers, pass `executablePath: process.env.PUPPETEER_EXECUTABLE_PATH || process.env.CHROME_BIN` if either env var is set. If either env var points to an executable, do not run `npx puppeteer browsers install`, `puppeteer browsers install`, Playwright install, or any browser download. Do not connect to `localhost:9223`, `/json/version`, or any Chrome remote-debug endpoint unless `RESOLVEIO_SUPPORT_QA_BROWSER_URL` or `RESOLVEIO_RUNNER_QA_BROWSER_URL` is explicitly set after sourcing the staged env and the endpoint responds; otherwise launch a scoped Puppeteer browser from the staged executable. If Playwright is missing but Puppeteer env exists, continue with Puppeteer instead of returning `PLAYWRIGHT_MISSING`. If the staged browser is missing or not executable, return one precise dependency blocker instead of downloading inside the QA owner turn.', 'Do not scan broad roots such as `/var/app/resolveio-ai-workspace`, `/tmp/resolveio-support-qa`, or `/var/lib/resolveio` to rediscover Puppeteer, Playwright, or Chromium. Source the staged env file and use its `PUPPETEER_EXECUTABLE_PATH`/`CHROME_BIN`; if the staged browser/runtime is missing, return a precise dependency blocker.', 'When the current directory is an app/project root, shared QA tools may be staged one directory up. Prefer `../.resolveio-support-tools/env.sh` or `../.resolveio-ai-runner-tools/env.sh` before writing custom browser code. Do not use bare `require("puppeteer")` from an app root until checking the project/server node_modules or the staged helper pattern.', 'Secret handling: never print, cat, paste, or summarize `.env`, `.env.runtime`, `.env.codex`, `settings.json`, `.mongo-runtime.json`, Mongo URLs, API keys, tokens, or passwords in command output, QA artifacts, screenshots, captions, or final notes. Source staged env files or read only the named QA artifacts; redact connection strings if a tool emits one.', 'For targeted QA row repair, read `qa-artifacts/qa-live-data-seed-result.json`, `qa-artifacts/auth-bootstrap-result.json`, `qa-artifacts/auth-bootstrap-storage-state.json`, and `qa-artifacts/qa-workflow-probe-result.json` before writing browser probes. Use seeded `selected` ids/names directly; do not guess customer filters, invoice numbers, or dropdown options when the seed artifact already provides the exact QA fixture. After route navigation, wait for concrete route/workflow DOM text or controls for up to the row timeout before calling a page shell-only; a 1-2 second fixed delay is not enough evidence that a ResolveIO route failed to hydrate.', 'When the live seed artifact contains `selected.truck_treating_bol_context`, use the seeded ids/statuses directly instead of guessing customer data. If `primary_bol_status` or `bol_statuses[]` says Delivered, the direct `browser_routes.delivery` URL is an action route that may correctly redirect with `BOL has already been delivered`; do not treat that alone as an application defect. For delivered BOLs, test the delivered Open File/detail/Deliveries evidence path, or create the smallest localhost-only deliverable fixture from the fetched live BOL/route/delivery/treatment-plan context and record the fixture ids in the matrix. If `route_hint_matched === false`, the source database disproved the ticket route-name hint; use the seeded BOL-linked `bol_ids`, `route_ids`, `truck_treating_route_ids`, `linked_truck_treating_routes`, and usable browser route/fixture as the QA target, record the route-name mismatch in the row caption/assertion, and do not block only because the original route label is not visible.', 'QA owner source-code boundary: browser QA may write only QA artifacts, screenshots, traces, captions, coverage matrices, temporary row probe scripts, and localhost-only fixture data. Do not edit application source files, generated wrappers, package files, migrations, or tests from the QA lane. If QA proves a code/data/publication defect, return `needs-fix` with the exact matrix row, screenshot/log/data evidence, suspected files, and smallest repair hint so the build lane can fix it.', 'For Billing Dashboard QA rows, use seeded `qa_billing_fixture.customerId`, `psoId`, `deliveryId`, `invoiceId`, and `itemId` to choose/filter/open the exact row. If the page hides seeded rows behind filters, the QA row script should select by the seeded customer/id or return a data-seed/filter blocker with a screenshot instead of cycling through generic dropdown options.', 'For invoice edit, saved invoice, and inventory side-effect QA rows, prefer direct navigation to `/invoice/edit/${qa_billing_fixture.invoiceId}` or open invoice detail and click the explicit Edit control. Do not use Billing Dashboard or invoice-list `Open Invoice` as proof of the edit workflow; in ResolveIO that action can open/generated-preview invoice output instead of the edit component. If direct edit route redirects to a list/shell, return one precise route/data blocker with screenshot instead of retrying the same Open Invoice path.', 'When updating `qa-artifacts/qa-coverage-matrix.json`, verify the target row index still matches the active workflow before writing. If the row at that index has a different workflow, locate the row by exact workflow text; if multiple rows share a workflow, update only the row whose route/assertion matches the active row. Never overwrite an unrelated passing row or create duplicate workflow rows to work around a cursor mismatch.', 'Use the managed-server pattern for localhost QA: `command > .build-output/<name>.log 2>&1 & PID=$!; trap "kill $PID 2>/dev/null || true" EXIT; wait for the port with curl; run browser checks; then kill/wait the PID`. Prefer `npm run client` or `./start_client.sh`; those scripts honor `RESOLVEIO_SUPPORT_QA_CLIENT_PORT` and `PORT`. Never run `ng serve ... | tee ...` or another dev server as a foreground command.');
|
|
131
|
+
rules.push('When browser/localhost QA needs long-running commands like `npm run server`, `npm run client`, `npm run dev`, `ng serve`, `vite`, or `nodemon`, start them as managed background processes with log files and PIDs; do not leave foreground dev-server commands as the active shell tool.', 'Before localhost/browser QA, source `.resolveio-support-tools/env.sh` or `.resolveio-ai-runner-tools/env.sh` when present. It supplies shared EC2 browser cache settings, `PUPPETEER_EXECUTABLE_PATH`/`CHROME_BIN`, Mongo wrappers, and non-conflicting localhost QA ports/URLs.', 'For ResolveIO app login during browser QA, use the shared AI-runner auth bootstrap when staged: `node ./.resolveio-support-tools/qa-auth-bootstrap.js <project-root> /target-route`, `node ./.resolveio-ai-runner-tools/qa-auth-bootstrap.js <project-root> /target-route`, or the same command from an app root with `../`. It must use the exact localhost client origin, log out/clear stale browser credentials first, call `/login` then `/accessToken`, seed auth storage, repair the local QA user settings/tour flags if the app forces the post-login settings/tour gate, verify the browser reached the requested target route, and emit `qa-artifacts/auth-bootstrap-result.json`, `qa-artifacts/auth-bootstrap-storage-state.json`, plus a screenshot. For support-ticket QA, use Puppeteer first when `PUPPETEER_EXECUTABLE_PATH` or `CHROME_BIN` is set; `PLAYWRIGHT_MISSING` is not a blocker while that Puppeteer env exists. For every fresh Puppeteer/Playwright page, open the localhost origin, set localStorage from `auth-bootstrap-storage-state.json`, then navigate to the target route. The storage artifact may expose top-level object `localStorage`, array `localStorageEntries`, or Playwright-style `origins[].localStorage`; normalize all three shapes before setting storage (`Object.entries` for objects, `{key,value}` or `{name,value}` for arrays). Never run `for...of` directly on top-level `localStorage` unless it is already an array. A login-shell screenshot after bootstrap means the QA script failed to seed auth and must rerun the same row with storage seeded before returning needs-fix.', 'For support-ticket QA, run the browser as the ticket reporter whenever possible; if the ticket or latest customer response names another affected user, run as that affected user instead. Use `qa-live-data-seed-result.json.selected.qa_user_context` and `auth-bootstrap-result.json.user` to record the chosen user. Generic admin/dev QA is acceptable only when no reporter/affected user can be identified or copied into localhost QA; in that case the matrix must say why.', 'For ResolveIO browser checks, do not use Puppeteer/Playwright `networkidle0` or `networkidle2` as the page-ready condition; ResolveIO pages can keep background API/socket/polling activity open. Navigate with `domcontentloaded`, then wait for concrete route/workflow DOM text, buttons, table rows, dialogs, saved records, or persisted data assertions before screenshots.', 'Use browser API compatibility helpers instead of version-fragile calls: every row-level Puppeteer script must declare `const delay = ms => new Promise(resolve => setTimeout(resolve, ms));` before navigation and use `await delay(...)` for fixed waits. Do not use `page.$x`, `page.waitForTimeout`, `networkidle0`, or `networkidle2`. Use `page.evaluateHandle`/DOM traversal or Playwright `locator` when definitely using Playwright. If a browser helper call throws because the current runtime lacks that API, fix the QA script and rerun the same matrix row before marking it failed.', 'Browser click targeting must prefer exact interactive controls: `button`, `a[href]`, `[role="button"]`, `input[type="button"]`, `input[type="submit"]`, `select`, option/combobox controls, and app-specific clickable elements with a small visible bounding box. Do not include broad `div`, `span`, `body`, or `*` elements in click-by-text helpers; they often match whole-page containers and produce false progress. If a text match has a huge bounding box or contains unrelated page/navigation text, skip it and find a smaller descendant/control.', 'For QA row probes, use broad DOM text scans only for read-only diagnostics. Do not drive workflow clicks from broad `document.querySelectorAll("*")` or generic container matches. After at most two focused selector attempts on the seeded route/data, either capture the blocker screenshot and return `needs-fix`, or switch to persisted data assertions if the row can be proven without another UI click.', 'When launching Puppeteer on workers, pass `executablePath: process.env.PUPPETEER_EXECUTABLE_PATH || process.env.CHROME_BIN` if either env var is set. If either env var points to an executable, do not run `npx puppeteer browsers install`, `puppeteer browsers install`, Playwright install, or any browser download. Do not connect to `localhost:9223`, `/json/version`, or any Chrome remote-debug endpoint unless `RESOLVEIO_SUPPORT_QA_BROWSER_URL` or `RESOLVEIO_RUNNER_QA_BROWSER_URL` is explicitly set after sourcing the staged env and the endpoint responds; otherwise launch a scoped Puppeteer browser from the staged executable. If Playwright is missing but Puppeteer env exists, continue with Puppeteer instead of returning `PLAYWRIGHT_MISSING`. If the staged browser is missing or not executable, return one precise dependency blocker instead of downloading inside the QA owner turn.', 'Do not scan broad roots such as `/var/app/resolveio-ai-workspace`, `/tmp/resolveio-support-qa`, or `/var/lib/resolveio` to rediscover Puppeteer, Playwright, or Chromium. Source the staged env file and use its `PUPPETEER_EXECUTABLE_PATH`/`CHROME_BIN`; if the staged browser/runtime is missing, return a precise dependency blocker.', 'When the current directory is an app/project root, shared QA tools may be staged one directory up. Prefer `../.resolveio-support-tools/env.sh` or `../.resolveio-ai-runner-tools/env.sh` before writing custom browser code. Do not use bare `require("puppeteer")` from an app root until checking the project/server node_modules or the staged helper pattern.', 'Secret handling: never print, cat, paste, or summarize `.env`, `.env.runtime`, `.env.codex`, `settings.json`, `.mongo-runtime.json`, Mongo URLs, API keys, tokens, or passwords in command output, QA artifacts, screenshots, captions, or final notes. Source staged env files or read only the named QA artifacts; redact connection strings if a tool emits one.', 'For targeted QA row repair, read `qa-artifacts/qa-live-data-seed-result.json`, `qa-artifacts/auth-bootstrap-result.json`, `qa-artifacts/auth-bootstrap-storage-state.json`, and `qa-artifacts/qa-workflow-probe-result.json` before writing browser probes. Use seeded `selected` ids/names directly when they match the ticket diagnosis; do not guess filters, record numbers, or dropdown options when the seed artifact already provides the exact QA fixture. After route navigation, wait for concrete route/workflow DOM text or controls for up to the row timeout before calling a page shell-only; a 1-2 second fixed delay is not enough evidence that a ResolveIO route failed to hydrate.', 'QA owner source-code boundary: browser QA may write only QA artifacts, screenshots, traces, captions, coverage matrices, temporary row probe scripts, and localhost-only fixture data. Do not edit application source files, generated wrappers, package files, migrations, or tests from the QA lane. If QA proves the customer-reported behavior is still wrong, return `needs-fix` with the exact matrix row, proof artifact, suspected files, and smallest repair hint so the build lane can fix it.', 'When updating `qa-artifacts/qa-coverage-matrix.json`, verify the target row index still matches the active workflow before writing. If the row at that index has a different workflow, locate the row by exact workflow text; if multiple rows share a workflow, update only the row whose route/assertion matches the active row. Never overwrite an unrelated passing row or create duplicate workflow rows to work around a cursor mismatch.', 'Use the managed-server pattern for localhost QA: `command > .build-output/<name>.log 2>&1 & PID=$!; trap "kill $PID 2>/dev/null || true" EXIT; wait for the port with curl; run browser checks; then kill/wait the PID`. Prefer `npm run client` or `./start_client.sh`; those scripts honor `RESOLVEIO_SUPPORT_QA_CLIENT_PORT` and `PORT`. Never run `ng serve ... | tee ...` or another dev server as a foreground command.');
|
|
132
132
|
if (policy.context === 'support_ticket') {
|
|
133
133
|
rules.push('For support-ticket QA validation, the manager normally runs compile/startup preflight and keeps the local harness alive before the QA owner starts. In that mode, the QA owner must not run `run-local-qa.sh`, `npm run server`, `npm run client`, `ng serve`, `mongod`, `gulp`, or compile/build commands again; probe the existing localhost URLs and proceed to auth/browser proof.', 'If the preflighted support-ticket harness is not reachable, return a precise blocked/needs-fix result with the probed URL, HTTP/socket error, and qa-artifacts log paths. Do not start a duplicate server, duplicate client, duplicate Mongo, or duplicate compile from inside the browser QA owner.');
|
|
134
134
|
}
|
|
@@ -141,25 +141,20 @@ function buildResolveIOQaPolicyRules(options) {
|
|
|
141
141
|
rules.push('QA findings are implementation blockers, not manual TODOs: when QA proves missing fields, wrong publication payloads, failed persistence, bad calculations, missing side effects, or incomplete workflow coverage, return a typed needs-fix blocker so the runner starts a focused repair wave and reruns the same QA coverage.');
|
|
142
142
|
}
|
|
143
143
|
if (policy.qaLiveDataRequired) {
|
|
144
|
-
rules.push('For bug fixes
|
|
144
|
+
rules.push('For bug fixes, test against available live app state or a faithful seeded scenario; do not rely only on static inspection when the user reported a runtime workflow problem.');
|
|
145
145
|
rules.push('Local QA may create, update, or delete representative seed records only in the localhost QA Mongo/database started for the run. Production/live customer databases are read-only for QA unless explicit human approval is provided.');
|
|
146
146
|
rules.push('If the localhost QA database has no records for the workflow under test, seed the smallest faithful record set needed to exercise the customer action and identify the seeded fixture IDs/names in the QA Coverage Matrix. Do not return blocked only because local QA data is empty.');
|
|
147
|
-
rules.push('When a ticket or customer response names concrete entities
|
|
148
|
-
rules.push('
|
|
149
|
-
rules.push('For file upload/import QA, write a checkpoint artifact before launch, after route load, after file selection/upload, after parsing, after clicking the import/submit action, and after the final result. If the browser page/frame/process dies during file selection or parse, mark the row failed with that exact upload-stage blocker; do not silently retry as a pass or count route-load screenshots as proof.');
|
|
147
|
+
rules.push('When a ticket or customer response names concrete entities, live-data seeding must fetch those exact production records into localhost QA where possible. QA must prove every named entity or return a seed/query blocker; representative substitute records are not pass evidence for named-record bug reports.');
|
|
148
|
+
rules.push('QA must drive the actual customer action identified by the diagnosis and capture the relevant starting state, action state, and resulting state with a concrete assertion chosen from the code/data/UI path under test.');
|
|
150
149
|
rules.push('A navigation-only screenshot of an empty page, shell, table header, or unchanged screen is not sufficient evidence for data workflow fixes. If the page has no records, seed or choose a faithful test record and identify the record or fixture used.');
|
|
151
|
-
rules.push('
|
|
152
|
-
rules.push('For pricing import/upload tickets, expand the exact visible Ready accordion/control, then click the small enabled `Import Production Prices` button or equivalent submit control. Do not click broad page containers, nav/sidebar text, or generic div/span text matches. Do not treat static headings like `Production Prices With Errors`, `Ready For Import`, or unchanged table text as success or blocker evidence; wait for a real result dialog/message, button disabled/enabled state change, page error, or persisted Mongo row/count/value change.');
|
|
153
|
-
rules.push('For asset location/current-yard rename tickets, browser QA must prove the exact asset/unit on list, detail, and edit/save screens, and must include a joined/canonical yard record assertion showing the new yard name is used and the stale old yard name is absent.');
|
|
154
|
-
rules.push('For asset location/current-yard rename tickets that name multiple assets or units, QA must prove every named asset/unit, not one representative row. Captions/data assertions must name each requested unit number, its canonical joined yard, and the absence of each stale yard name before the row can pass.');
|
|
155
|
-
rules.push('For Update Interchangeables or Mass Update chemical tickets, browser QA must select the real source and target chemicals, run the update action, and assert before/after treatment-plan/tank document counts or ids in localhost QA Mongo. Route load, visible controls, or selected dropdowns alone are not pass evidence.');
|
|
150
|
+
rules.push('Let the model choose the proof technique from the ticket, diagnosis, code, UI, and local data evidence. Shared runner policy must not prescribe domain-specific routes, buttons, collections, or workflow categories. The only shared acceptance rule is that the proof must exercise the reported behavior and show before/action/after evidence; route-load, compile-pass, scorecard-pass, or model-claim alone is not success.');
|
|
156
151
|
}
|
|
157
152
|
rules.push('Before passing QA, create a QA Coverage Matrix from the approved scope, changed files, generated/publication changes, and touched collections/models. Each matrix row must name the workflow, route/screen, data used, assertion, screenshot/trace artifact, and pass/fail result.');
|
|
158
153
|
rules.push('When updating `qa-artifacts/qa-coverage-matrix.json`, support both matrix schemas: the file may be an array or an object with a `rows` array. Use `const rows = Array.isArray(matrix) ? matrix : matrix.rows` for row updates and preserve the original schema when writing it back. Never skip row updates because only `Array.isArray(matrix)` is false.');
|
|
159
154
|
rules.push('When a QA Coverage Matrix row is marked `pass`, remove stale negative fields from that row before writing it: `blocker`, `failure`, `error`, `notes`, `next_actions`, `failed_reason`, and `blocked_reason`. Passed rows must not retain old blocker text from earlier retries.');
|
|
160
|
-
rules.push('QA must cover the
|
|
161
|
-
rules.push('If the change touches
|
|
162
|
-
rules.push('
|
|
155
|
+
rules.push('QA must cover the changed customer-facing and data behavior, not only one smoke path. If implementation touches multiple independent state transitions, each touched transition needs proof or an explicit ticket-backed not-applicable note.');
|
|
156
|
+
rules.push('If the change touches customer-visible state, persisted data, calculations, publications, or server methods, QA must include at least one concrete assertion tied to the changed behavior before returning pass.');
|
|
157
|
+
rules.push('The QA Coverage Matrix should stay small and diagnosis-driven: one route/setup row when useful, one active customer action row, and one persisted/result row are enough for most support bugs. Add rows only when the approved proof_plan or changed behavior genuinely requires another independent workflow.');
|
|
163
158
|
rules.push('After localhost startup/auth succeeds, immediately drive the target customer workflow in the browser. Do not spend an open-ended reasoning pass after auth; create fresh feature screenshots/captions plus persisted row/count/value assertions, or return needs-fix with the exact blocker.');
|
|
164
159
|
rules.push('After startup/auth succeeds, missing selectors, dropdowns, options, saved values, rows, disabled/enabled states, or customer workflow controls are product/data QA failures. Mark the matrix row failed and return `needs-fix` with the exact row blocker and artifact paths; reserve `blocked` for true external/manual blockers such as auth, startup, infrastructure, credentials, or unavailable third-party systems.');
|
|
165
160
|
rules.push('Once any QA Coverage Matrix row is marked in_progress, finish that row promptly by marking it pass, failed, or blocked with screenshot/caption/assertion evidence. Leaving in_progress rows without workflow artifacts is a QA failure and should trigger a targeted repair wave.');
|
|
@@ -167,13 +162,13 @@ function buildResolveIOQaPolicyRules(options) {
|
|
|
167
162
|
rules.push('For desktop QA, verify the top navigation is in its normal desktop state and not wrapped, collapsed, open, or covering the workflow. For mobile-specific QA, explicitly use a mobile viewport and close the mobile menu unless the menu behavior itself is being proven.');
|
|
168
163
|
rules.push('Before every screenshot, settle the ResolveIO shell: press Escape, blur active controls, move the mouse away from the top/side nav, wait at least 750ms, and verify the target row/control/value has a visible bounding box inside the viewport. If the target text exists in DOM but is covered by the menu, sidebar, header, or a dark overlay, close the overlay or adjust the QA user/menu setting and recapture; do not count the covered screenshot as proof.');
|
|
169
164
|
rules.push('For table/list evidence, a pass screenshot must show the actual target row cells and the changed value in the same frame. Header-only, pagination-only, covered-row, or DOM-only proof can diagnose a failure, but cannot be used as customer-facing pass evidence.');
|
|
170
|
-
rules.push('For
|
|
165
|
+
rules.push('For selection/filter workflows, a pass screenshot must show the relevant control with a real non-placeholder selected value, an open control with the specific live option used, or a resulting data row/action state caused by that selection. Screenshots where required controls still show only placeholders are empty-state evidence and must be failed or recaptured before pass.');
|
|
171
166
|
rules.push('A matrix shortcut may only pass after all row-specific evidence gates pass. If any row was rejected for shallow proof, missing selected values, missing persisted data, or stale/contradictory matrix data, keep the row failed and trigger a targeted repair/retest instead of marking the matrix complete.');
|
|
172
167
|
rules.push('Route/screen screenshots are valid only when they show the specific workflow being tested. If a route redirects to a generic shell, default manage page, menu-only view, auth screen, or a different feature screen, mark that matrix row failed/blocked with the mismatch; never count that screenshot as pass evidence.');
|
|
173
168
|
if (policy.qaDistinctScreenshotRequired) {
|
|
174
169
|
rules.push('Capture one screenshot or trace for each distinct changed customer-facing feature, screen, workflow state, or data result. Do not repeat equivalent screenshots for multiple records unless record-specific behavior changed.');
|
|
175
170
|
}
|
|
176
|
-
rules.push('Every screenshot artifact must include a short customer-facing caption explaining what the screenshot proves. Captions should describe the workflow state, such as Before, Ready
|
|
171
|
+
rules.push('Every screenshot artifact must include a short customer-facing caption explaining what the screenshot proves. Captions should describe the workflow state, such as Before, Ready for action, Submitted result, or Mobile menu closed.');
|
|
177
172
|
if (policy.qaEvidenceRequired) {
|
|
178
173
|
rules.push('Final notes must list the exact QA command, route, account/data used, screenshot/trace/log paths, and result for each changed behavior; if browser QA is not applicable, say why and provide the compile/data proof used instead.');
|
|
179
174
|
}
|
|
@@ -185,31 +180,13 @@ function buildResolveIOQaPolicyRules(options) {
|
|
|
185
180
|
}
|
|
186
181
|
function buildResolveIORunnerQaCoverageChecklist(input) {
|
|
187
182
|
if (input === void 0) { input = {}; }
|
|
188
|
-
var text = "".concat(input.ticketText || '', "\n").concat((input.changedFiles || []).join('\n'));
|
|
189
183
|
var rules = [
|
|
190
184
|
'Build and include a QA Coverage Matrix: changed workflow, route/screen, data fixture/live record, before/action/after assertion, screenshot/trace artifact, caption, and result.',
|
|
191
|
-
'Fail QA as needs-fix when coverage only proves navigation, headers, empty tables, or UI controls without exercising the changed behavior and
|
|
185
|
+
'Fail QA as needs-fix when coverage only proves navigation, headers, empty tables, or UI controls without exercising the changed behavior and concrete result.',
|
|
186
|
+
'Let the model derive the specific proof rows from the ticket diagnosis, changed files, and runtime evidence; shared policy must not expand a ticket into unrelated app workflows or keyword categories.',
|
|
187
|
+
'Exercise the touched customer action and verify the saved, calculated, displayed, or emitted result with the smallest concrete assertion that proves the reported behavior.',
|
|
188
|
+
'When QA has no usable local records, seed the smallest localhost-only record set needed to prove the active customer action, record fixture IDs/names, and do not touch production data.'
|
|
192
189
|
];
|
|
193
|
-
if (/\b(invoice|billing|line item|surcharge|price|pricing|tax|sales tax)\b|(?:^|\/)(?:invoice|pricing|sales-tax|customer|item)(?:\/|-)/i.test(text)) {
|
|
194
|
-
rules.push('Invoice/billing/tax coverage: test create/new and edit/reopen where touched; verify line-item persistence, surcharge add/remove/default/override selection, subtotal/tax/total calculations, taxable vs non-taxable behavior, and the saved invoice detail/list state.');
|
|
195
|
-
rules.push('When invoice/billing/tax QA has no usable local records, seed a minimal localhost-only customer, job/order/delivery or treatment, taxable item, non-taxable/surcharge item, and inventory/location data needed to create and save the invoice workflow; record the fixture IDs/names and do not touch production data.');
|
|
196
|
-
rules.push('For Billing Dashboard invoice QA, do not hardcode one accordion bucket such as Processing. Read the live bucket labels and counts from the page/probe, choose the relevant non-empty invoice bucket for the row (for example PSO Type Invoice Awaiting Invoices, Prepared, Processing, or Open Invoices), expand it, then use the visible workflow control or invoice row. A selector is blocked only when no relevant non-empty billing bucket or invoice control exists after waiting for async data.');
|
|
197
|
-
rules.push('For invoice edit/reopen/inventory side-effect QA, use the seeded `qa_billing_fixture.invoiceId` on `/invoice/edit/<invoiceId>` or the invoice detail Edit control. Do not click `Open Invoice` to prove editing because that control can open invoice output/preview instead of the edit workflow.');
|
|
198
|
-
rules.push('Invoice/billing/tax coverage must include at least one concrete row/value assertion from the saved document or UI after submit, not only pre-submit form screenshots.');
|
|
199
|
-
}
|
|
200
|
-
if (/\b(inventory|warehouse|stock|fifo|pick ticket|checkout|check out|transaction)\b|(?:^|\/)(?:inventory|part|chemical|production-location|yard)(?:\/|-)/i.test(text)) {
|
|
201
|
-
rules.push('Inventory coverage: test the relevant source/destination location, transaction creation/reversal, FIFO or location selection when applicable, report/pick-ticket output when touched, and persisted inventory quantities/values after save/edit/delete.');
|
|
202
|
-
rules.push('When inventory QA has no usable local records, seed the smallest localhost-only item/location/quantity/value fixture needed to prove quantity/value movement and identify that fixture in the evidence.');
|
|
203
|
-
}
|
|
204
|
-
if (/\b(report|export|csv|excel|xlsx|download|filter|total|grouping)\b|(?:^|\/)report(?:\/|-)/i.test(text)) {
|
|
205
|
-
rules.push('Report/export coverage: verify rows, filters/date ranges, totals/grouping, download/export output, and at least one row/count/value assertion.');
|
|
206
|
-
}
|
|
207
|
-
if (/\b(publication|methods?\.ts|publications?\.ts|subscription|publish|payload|field projection)\b|(?:^|\/)server\/src\/publications\//i.test(text)) {
|
|
208
|
-
rules.push('Publication/API coverage: verify the changed fields are returned to the UI or method caller that needs them, including list/detail projections and any generated wrapper/call-site behavior.');
|
|
209
|
-
}
|
|
210
|
-
if (/\b(import|upload|file|spreadsheet|template)\b/i.test(text)) {
|
|
211
|
-
rules.push('Import/upload coverage: use a representative file/template, capture ready-to-upload and submitted states, and assert inserted/updated/skipped row counts plus visible result rows.');
|
|
212
|
-
}
|
|
213
190
|
return Array.from(new Set(rules));
|
|
214
191
|
}
|
|
215
192
|
function buildResolveIORunnerBasicsRules(options) {
|
|
@@ -243,7 +220,7 @@ function buildResolveIORunnerContract(options) {
|
|
|
243
220
|
: [];
|
|
244
221
|
var repairLoop = options.includeRepairLoop !== false
|
|
245
222
|
? [
|
|
246
|
-
"Use targeted repair waves: compile/startup blocker,
|
|
223
|
+
"Use targeted repair waves: compile/startup blocker, runtime behavior blocker, business-proof blocker, and review blocker each get a focused repair, then rerun the exact failed step. Limit this to ".concat(maxRepairWaves, " focused waves before returning a precise blocker."),
|
|
247
224
|
'Repair all instances of a detected blocker class in the touched scope, not only the first occurrence.'
|
|
248
225
|
]
|
|
249
226
|
: [];
|
|
@@ -254,7 +231,7 @@ function buildResolveIORunnerContract(options) {
|
|
|
254
231
|
? [
|
|
255
232
|
'Evidence must be customer/workflow oriented: routes, buttons, pages, data states, screenshots/traces, command results, and assertions. Do not expose internal file names, backend paths, stack traces, or implementation chatter in customer-facing text.',
|
|
256
233
|
'For UI-facing changes, capture one screenshot or trace per distinct changed feature/workflow; for data-only changes, provide live-data or seeded-data assertion proof.',
|
|
257
|
-
'For
|
|
234
|
+
'For any customer-reported behavior change, proof must follow the model-authored diagnosis proof plan and show the before/action/after business state with a concrete pass/fail assertion. Empty shell screenshots do not count as proof.',
|
|
258
235
|
'Desktop proof screenshots must use a wide/full-screen viewport, normally 1920x1080 or wider, with navigation closed/unwrapped unless the ticket is specifically about mobile or menu behavior.',
|
|
259
236
|
'Each screenshot must have a customer-facing caption that says what the image proves; these captions are used in validation emails.'
|
|
260
237
|
]
|
|
@@ -437,12 +414,6 @@ function classifyResolveIORunnerBlocker(blocker) {
|
|
|
437
414
|
if (/database call inside loop|findOne.*inside loop|query inside loop/i.test(text)) {
|
|
438
415
|
return 'db_call_inside_loop';
|
|
439
416
|
}
|
|
440
|
-
if (/inventory transaction parity|inventory transactions? are correct|inventory transaction creation\/reversal|inventory drift|reverse(?:s| old).*inventory|custom chemical lines?/i.test(text)) {
|
|
441
|
-
return 'inventory_transaction_parity';
|
|
442
|
-
}
|
|
443
|
-
if (/company\/global default line-item surcharge|customer surcharge override|surcharge override.*default|global\/company surcharge|fallback\/override|first active surcharge/i.test(text)) {
|
|
444
|
-
return 'surcharge_default_precedence';
|
|
445
|
-
}
|
|
446
417
|
if (/\bTS\d{4}\b[\s\S]{0,220}\bExpected\s+0\s+arguments?\b[\s\S]{0,160}\bgot\s+1\b/i.test(text)
|
|
447
418
|
&& /\b(publication|publications\.ts|subscribe|user_specific|ForUser|yardsForUser|customerNotifications|notificationCenter)\b/i.test(text)) {
|
|
448
419
|
return 'user_specific_publication_argument_mismatch';
|
|
@@ -463,10 +434,7 @@ function classifyResolveIORunnerBlocker(blocker) {
|
|
|
463
434
|
if (/UI-facing ticket needs|browser\/localhost QA|local\/browser QA/i.test(text)) {
|
|
464
435
|
return 'ui_qa_missing';
|
|
465
436
|
}
|
|
466
|
-
if (/
|
|
467
|
-
return 'report_export_missing';
|
|
468
|
-
}
|
|
469
|
-
if (/QA coverage matrix|full suite|limited smoke|too limited|only proves navigation|empty table|header screenshot|pre-submit only|missing persisted result|missing tax|missing inventory|missing invoice edit|missing reopen/i.test(text)) {
|
|
437
|
+
if (/QA coverage matrix|full suite|limited smoke|too limited|only proves navigation|empty table|header screenshot|pre-submit only|missing persisted result/i.test(text)) {
|
|
470
438
|
return 'qa_coverage_incomplete';
|
|
471
439
|
}
|
|
472
440
|
if (/Generated .* changed without a matching/i.test(text)) {
|
|
@@ -621,48 +589,13 @@ function buildResolveIORunnerRepairPlans(input) {
|
|
|
621
589
|
'rg -n "\\.(find|findOne|findOneAsync|count|countDocuments|update|updateOne|updateMany|insert|insertOne|bulkWrite|remove|deleteOne|deleteMany)\\(" <target file>'
|
|
622
590
|
], passingCondition: 'No loop in the touched/target server files has a database collection call in its body, or final notes prove each flagged call is not a database call.' }), input, blockerClass);
|
|
623
591
|
}
|
|
624
|
-
if (blockerClass === 'report_export_missing') {
|
|
625
|
-
return applyResolveIORunnerRepairTargetOverride(__assign(__assign({}, base), { requiredProof: ['Prove report rows, filters, totals/grouping, and export behavior, or cite ticket evidence that export is out of scope.'], repairRecipe: ['Exercise the report/export path and record evidence for each report dimension requested by the ticket.'], selfGateCommands: ['Run the report/export verification command or browser flow for the ticket.'], passingCondition: 'Final notes prove rows, filters, totals/grouping, and export behavior or a ticket-backed out-of-scope decision.' }), input, blockerClass);
|
|
626
|
-
}
|
|
627
|
-
if (blockerClass === 'inventory_transaction_parity') {
|
|
628
|
-
return applyResolveIORunnerRepairTargetOverride(__assign(__assign({}, base), { requiredProof: [
|
|
629
|
-
'Prove non-Manual Delivery and Truck Treat custom chemical lines create inventory relief transactions on invoice create.',
|
|
630
|
-
'Prove invoice edit reverses old custom chemical effects and applies the new custom chemical effects.',
|
|
631
|
-
'Prove invoice remove/delete reverses the same non-Manual custom chemical inventory effects.'
|
|
632
|
-
], repairRecipe: [
|
|
633
|
-
'Start in server/src/methods/invoices.ts and trace Manual inventory behavior before changing the non-Manual path.',
|
|
634
|
-
'Reuse the existing inventory transaction helper shape instead of creating a parallel inventory writer.',
|
|
635
|
-
'Handle all custom chemical lines in one sweep: create, edit, and remove for Delivery and Truck Treat invoices.',
|
|
636
|
-
'Do not stop after fixing only create; the reviewer blocker includes edit and remove reversal.'
|
|
637
|
-
], selfGateCommands: [
|
|
638
|
-
'git diff HEAD -- server/src/methods/invoices.ts server/src/methods/inventory-transactions.ts',
|
|
639
|
-
'rg -n "is_custom_line_item|addInventoryTransaction|removeInvoice|editInvoice|custom chemical" server/src/methods/invoices.ts',
|
|
640
|
-
'Run or add a focused server/data assertion covering create, edit, and remove inventory transactions for non-Manual custom chemical lines.'
|
|
641
|
-
], passingCondition: 'Create, edit, and remove paths for non-Manual custom chemical invoice lines all have inventory transaction proof.' }), input, blockerClass);
|
|
642
|
-
}
|
|
643
|
-
if (blockerClass === 'surcharge_default_precedence') {
|
|
644
|
-
return applyResolveIORunnerRepairTargetOverride(__assign(__assign({}, base), { requiredProof: [
|
|
645
|
-
'Show the persisted company/global default surcharge owner, not just the first active surcharge item.',
|
|
646
|
-
'Show precedence is customer override when active, then company/global default when active, then empty/none when inactive or unset.',
|
|
647
|
-
'Show at least one override customer and one default customer path in verification evidence.'
|
|
648
|
-
], repairRecipe: [
|
|
649
|
-
'Find the surcharge default selector and replace any first-active-item fallback with an explicit persisted default setting.',
|
|
650
|
-
'Keep customer override storage separate from the company/global default setting.',
|
|
651
|
-
'Reject inactive surcharge items during both override and default fallback.',
|
|
652
|
-
'Cover unset and inactive settings with safe empty/none behavior.'
|
|
653
|
-
], selfGateCommands: [
|
|
654
|
-
'git diff HEAD -- angular/app/manage/item angular/app/widgets/dialog/dialog.adjust-customer.content.ts server/src/collections server/src/models',
|
|
655
|
-
'rg -n "line_item_surcharge|surcharge|id_line_item_surcharge_override|default" angular/app server/src',
|
|
656
|
-
'Run or add a focused fallback/override assertion for active override, active company default, inactive override/default, and unset default.'
|
|
657
|
-
], passingCondition: 'Customer override -> company/global default -> none precedence is persisted and verified.' }), input, blockerClass);
|
|
658
|
-
}
|
|
659
592
|
if (blockerClass === 'support_qa_evidence') {
|
|
660
593
|
return applyResolveIORunnerRepairTargetOverride(__assign(__assign({}, base), { requiredProof: [
|
|
661
594
|
'Include browser route and screenshot/trace artifact paths for each distinct changed customer-facing feature or workflow state.',
|
|
662
595
|
'Do not duplicate screenshots across multiple customers unless the customer-specific override/fallback behavior is the feature being proven.',
|
|
663
596
|
'Include data/assertion evidence for requested persistence, calculations, and side effects.',
|
|
664
|
-
'Include a QA Coverage Matrix row for every approved scope item and every
|
|
665
|
-
'For
|
|
597
|
+
'Include a QA Coverage Matrix row for every approved scope item and every independently changed customer-visible/data behavior.',
|
|
598
|
+
'For data workflow fixes, include before/action/after screenshots or trace steps plus the exact concrete assertion proving the changed behavior.',
|
|
666
599
|
'Reject empty page/table/header screenshots as insufficient unless the approved requirement is explicitly an empty-state UI.',
|
|
667
600
|
'Use a 1920x1080-or-wider desktop viewport for screenshots unless the ticket explicitly requests mobile/responsive behavior; desktop nav must be closed and not wrapped over the workflow.',
|
|
668
601
|
'Before pass, prove each cited screenshot visibly contains the target row/control/value and is not covered by the ResolveIO menu/sidebar/header overlay. If DOM text passes but screenshot is covered, recapture after closing/settling the shell.',
|
|
@@ -681,8 +614,8 @@ function buildResolveIORunnerRepairPlans(input) {
|
|
|
681
614
|
}
|
|
682
615
|
if (blockerClass === 'qa_coverage_incomplete') {
|
|
683
616
|
return applyResolveIORunnerRepairTargetOverride(__assign(__assign({}, base), { requiredProof: [
|
|
684
|
-
'Provide a QA Coverage Matrix that covers every changed
|
|
685
|
-
'
|
|
617
|
+
'Provide a QA Coverage Matrix that covers every changed behavior from the approved scope and diff.',
|
|
618
|
+
'Let the diagnosis and diff determine proof rows; do not expand into unrelated product workflows from keywords alone.',
|
|
686
619
|
'Show fresh screenshots/traces with customer-facing captions for each distinct changed workflow state.'
|
|
687
620
|
], repairRecipe: __spreadArray(__spreadArray([
|
|
688
621
|
'Read the approved scope, BUILD_PLAN, changed files, and prior QA evidence; identify every workflow/domain touched by the implementation.'
|