feat: Stellar Wave — responsive, accessibility, load tests, security, repo map (#34, #35, #38, #50, #48) - #111
Conversation
Signed-off-by: laurentketterle-hub <laurentketterle-hub@users.noreply.github.com>
Signed-off-by: laurentketterle-hub <laurentketterle-hub@users.noreply.github.com>
Signed-off-by: laurentketterle-hub <laurentketterle-hub@users.noreply.github.com>
Signed-off-by: laurentketterle-hub <laurentketterle-hub@users.noreply.github.com>
Signed-off-by: laurentketterle-hub <laurentketterle-hub@users.noreply.github.com>
Signed-off-by: laurentketterle-hub <laurentketterle-hub@users.noreply.github.com>
Signed-off-by: laurentketterle-hub <laurentketterle-hub@users.noreply.github.com>
📝 WalkthroughWalkthroughThe PR adds contributor security and repository documentation, accessibility and responsive dashboard assets, and staged k6 and Artillery load tests for core endpoints. ChangesContributor documentation
Accessibility and responsive UI
Load-test coverage
Estimated code review effort: 3 (Moderate) | ~25 minutes Sequence Diagram(s)sequenceDiagram
participant Browser
participant accessibility.js
participant Dialog
Browser->>accessibility.js: DOM ready
accessibility.js->>Browser: Inject skip link and live region
Browser->>accessibility.js: Insert dialog
accessibility.js->>Dialog: Detect focusable elements
accessibility.js->>Dialog: Focus first element
Dialog->>accessibility.js: Tab or Shift+Tab
accessibility.js->>Dialog: Loop focus within dialog
Possibly related PRs
🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (3 passed)
✨ Finishing Touches 💡 1🛠️ Fix failing CI checks 💡
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 8
🧹 Nitpick comments (1)
docs/REPOSITORY_MAP.md (1)
7-31: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAdd a language identifier to the fenced tree block.
Markdownlint reports MD040 on Line 7. Use
textfor this directory listing.Proposed fix
-``` +```text🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@docs/REPOSITORY_MAP.md` around lines 7 - 31, Update the fenced directory-tree block in REPOSITORY_MAP.md to specify the text language identifier, changing the opening fence to use text while preserving the listing contents unchanged.Source: Linters/SAST tools
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@public/assets/css/responsive.css`:
- Around line 25-46: Add a rendered .mobile-menu-toggle button and client-side
toggle behavior that targets .sidebar, toggles its open class, and keeps
aria-expanded synchronized with the sidebar state; preserve the existing
responsive CSS behavior and ensure the control is accessible.
In `@public/assets/js/accessibility.js`:
- Around line 22-56: Update setupFocusTraps to process dialogs already present
in the document, including `#security-modal`, instead of only handling newly added
nodes. Reuse the existing focusable-element, keydown-handler, and initial-focus
logic for existing dialogs, and invoke or connect this setup from each dialog’s
display path so the trap activates when the dialog opens.
- Around line 65-68: Update public/index.html to include accessibility.css and
responsive.css, load public/assets/js/accessibility.js, and invoke its init()
after the script loads so the skip link, live region, and focus traps are
initialized.
In `@tests/load/load-test.js`:
- Around line 44-61: Update tests/load/load-test.js lines 44-61 to use the
documented /api/status route instead of /api/pricing and
/api/orchestrator/status, and require a successful 200 response while preserving
the timing checks and metrics. Update tests/load/load-test.yml lines 31-47 to
target /api/status and remove 404 from the expected status codes.
- Around line 22-25: Update the thresholds configuration in the load test to
include accepted-rate thresholds for both k6 check results and failed HTTP
requests. Add checks for the checks metric and http_req_failed so assertion
failures and request failures cause a non-zero test result, while preserving the
existing duration and errors thresholds.
- Around line 75-85: Update handleSummary so assessment is not set to “BASELINE
ESTABLISHED” unless the configured http_req_duration and errors threshold
statuses in data.metrics indicate success; otherwise use a neutral assessment
value. Read each metric’s thresholds[<threshold>].ok status and preserve the
existing summary metrics.
In `@tests/load/load-test.yml`:
- Around line 2-21: Add a config.plugins section to enable the ensure and expect
Artillery plugins used by the load test. Configure expect.reportFailuresAsErrors
as true so failed flow.expect assertions contribute to the existing errors.rate
condition, while preserving the current thresholds and phases.
---
Nitpick comments:
In `@docs/REPOSITORY_MAP.md`:
- Around line 7-31: Update the fenced directory-tree block in REPOSITORY_MAP.md
to specify the text language identifier, changing the opening fence to use text
while preserving the listing contents unchanged.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 8bd628cf-8c37-4a6b-a60d-71b38217cb4e
📒 Files selected for processing (7)
docs/CONTRIBUTING_SECURITY.mddocs/REPOSITORY_MAP.mdpublic/assets/css/accessibility.csspublic/assets/css/responsive.csspublic/assets/js/accessibility.jstests/load/load-test.jstests/load/load-test.yml
| @@ -0,0 +1,51 @@ | |||
| # Security Checklist for Contributors — Closes #50 | |||
|
|
|||
| Review before pushing code. Supplements [CONTRIBUTING.md](./CONTRIBUTING.md). | |||
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Align contributor documentation with the repository layout.
These documents use paths that can send contributors to missing or inactive locations.
docs/CONTRIBUTING_SECURITY.md#L3-L3: change./CONTRIBUTING.mdto../CONTRIBUTING.mdif the root-level file is intended.docs/REPOSITORY_MAP.md#L17-L23: document the actual locations of route and validation code, includingsrc/server.jsandsrc/requestValidation.js.docs/REPOSITORY_MAP.md#L39-L41: align thesrc/api/guidance with the actual route-registration boundary.
📍 Affects 2 files
docs/CONTRIBUTING_SECURITY.md#L3-L3(this comment)docs/REPOSITORY_MAP.md#L17-L23docs/REPOSITORY_MAP.md#L39-L41
| @media (max-width: 768px) { | ||
| .sidebar { | ||
| transform: translateX(-100%); | ||
| position: fixed; | ||
| z-index: 1000; | ||
| height: 100vh; | ||
| transition: transform 0.3s ease; | ||
| } | ||
| .sidebar.open { | ||
| transform: translateX(0); | ||
| width: 240px; | ||
| } | ||
| .sidebar.open .nav-label { | ||
| display: inline; | ||
| } | ||
| .main-content { | ||
| margin-left: 0; | ||
| padding: 1rem; | ||
| } | ||
| .mobile-menu-toggle { | ||
| display: block; | ||
| } |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
rg -n -C 3 --glob '*.js' --glob '*.html' \
'mobile-menu-toggle|classList\.(toggle|add|remove)\([^)]*["'\'']open|aria-expanded' publicRepository: Flamki/stellarmind
Length of output: 156
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf 'Tracked public JS/HTML/CSS files:\n'
git ls-files public | sed -n '1,200p'
printf '\nCSS file excerpt:\n'
sed -n '1,80p' public/assets/css/responsive.css 2>/dev/null || true
printf '\nSearch relevant tokens (all tracked text files):\n'
rg -n -C 3 'mobile-menu-toggle|sidebar\.open|classList\.(toggle|add|remove)\([^)]*["'\'']open|aria-expanded|aria-controls|onclick|addEventListener' public || trueRepository: Flamki/stellarmind
Length of output: 10929
🌐 Web query:
Flamki stellarmind public/assets/css/responsive.css mobile-menu-toggle sidebar.open
💡 Result:
The terms provided relate to a common pattern for implementing a responsive sidebar menu in web development, often found in projects like those managed under the Flamki organization on GitHub [1][2][3]. The file path public/assets/css/responsive.css typically contains the CSS rules for handling sidebar visibility on smaller screens, such as using media queries to toggle the display or transform properties (e.g., translateX) [2][4][3]. The terms mobile-menu-toggle and sidebar.open refer to the common JavaScript and CSS implementation where: 1. mobile-menu-toggle: Acts as a trigger element (often a hamburger icon or button) that captures click events [2][5][3]. 2. sidebar.open: A CSS class added or removed from the sidebar element via JavaScript to control its visibility (e.g., shifting it into or out of the viewport) [6][5][3]. While Flamki maintains several repositories (such as stellarmind, a marketplace for AI agents on Stellar) [1][7][8], these specific file paths and class names are standard conventions used across many web projects for mobile-responsive navigation rather than being unique to a single specific codebase [2][6][5][3].
Citations:
- 1: https://github.com/Flamki/stellarmind
- 2: RicardoAlejandroSantillan/dev-showcase@57fcff0
- 3: dipakkr/ai-engineering-guide@5d4e273
- 4: https://codefronts.com/navigation/css-sidebar-navigation/responsive-sidebar-toggle-with-html-and-css/
- 5: https://www.codeinfoweb.com/responsive-sidebar-html-css-javascript/
- 6: https://abduldev.com/how-to-create-a-responsive-sidebar-menu-design/
- 7: https://dorahacks.io/buidl/42681/team
- 8: https://github.com/Flamki/vaultVK
Wire the mobile toggle so CSS can reveal the sidebar.
.mobile-menu-toggle is styled, but there is no rendered toggle button and no JavaScript that toggles .sidebar.open or updates aria-expanded, so the mobile menu cannot open.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@public/assets/css/responsive.css` around lines 25 - 46, Add a rendered
.mobile-menu-toggle button and client-side toggle behavior that targets
.sidebar, toggles its open class, and keeps aria-expanded synchronized with the
sidebar state; preserve the existing responsive CSS behavior and ensure the
control is accessible.
| function setupFocusTraps() { | ||
| var observer = new MutationObserver(function (mutations) { | ||
| mutations.forEach(function (mutation) { | ||
| mutation.addedNodes.forEach(function (node) { | ||
| if (node.nodeType !== 1) return; | ||
| var dialog = node.matches && node.matches('[role="dialog"], dialog') | ||
| ? node | ||
| : node.querySelector && node.querySelector('[role="dialog"], dialog'); | ||
| if (!dialog) return; | ||
|
|
||
| var focusable = dialog.querySelectorAll( | ||
| 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])' | ||
| ); | ||
| if (focusable.length === 0) return; | ||
|
|
||
| var first = focusable[0]; | ||
| var last = focusable[focusable.length - 1]; | ||
|
|
||
| dialog.addEventListener('keydown', function (e) { | ||
| if (e.key !== 'Tab') return; | ||
| if (e.shiftKey && document.activeElement === first) { | ||
| e.preventDefault(); | ||
| last.focus(); | ||
| } else if (!e.shiftKey && document.activeElement === last) { | ||
| e.preventDefault(); | ||
| first.focus(); | ||
| } | ||
| }); | ||
|
|
||
| setTimeout(function () { first.focus(); }, 100); | ||
| }); | ||
| }); | ||
| }); | ||
|
|
||
| observer.observe(document.body, { childList: true, subtree: true }); |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Attach the focus trap to dialogs that already exist.
Line 56 observes only dialogs added after initialization. public/index.html Lines 1435-1448 already contains #security-modal, so this dialog never receives the keydown handler or initial focus when it opens. Initialize existing dialogs and activate the trap from the code that displays each dialog.
🧰 Tools
🪛 ast-grep (0.45.0)
[error] 50-50: React's useState should not be directly called
Context: setTimeout(function () { first.focus(); }, 100)
Note: [CWE-710] Improper Adherence to Coding Standards. Security best practice.
(usestate-direct-usage)
🪛 ESLint
[error] 26-26: Delete ;
(prettier/prettier)
[error] 27-27: Insert ⏎···········
(prettier/prettier)
[error] 28-28: Insert ··
(prettier/prettier)
[error] 29-29: Replace ············:·node.querySelector·&&·node.querySelector('[role="dialog"],·dialog'); with ··············:·node.querySelector·&&·node.querySelector('[role="dialog"],·dialog')
(prettier/prettier)
[error] 30-30: Delete ;
(prettier/prettier)
[error] 34-34: Delete ;
(prettier/prettier)
[error] 35-35: Delete ;
(prettier/prettier)
[error] 37-37: Delete ;
(prettier/prettier)
[error] 38-38: Delete ;
(prettier/prettier)
[error] 41-41: Delete ;
(prettier/prettier)
[error] 43-43: Delete ;
(prettier/prettier)
[error] 44-44: Delete ;
(prettier/prettier)
[error] 46-46: Delete ;
(prettier/prettier)
[error] 47-47: Delete ;
(prettier/prettier)
[error] 49-49: Delete ;
(prettier/prettier)
[error] 51-51: Replace ·first.focus();·},·100); with ⏎············first.focus()⏎··········},·100)
(prettier/prettier)
[error] 52-52: Delete ;
(prettier/prettier)
[error] 53-53: Delete ;
(prettier/prettier)
[error] 54-54: Delete ;
(prettier/prettier)
[error] 56-56: Delete ;
(prettier/prettier)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@public/assets/js/accessibility.js` around lines 22 - 56, Update
setupFocusTraps to process dialogs already present in the document, including
`#security-modal`, instead of only handling newly added nodes. Reuse the existing
focusable-element, keydown-handler, and initial-focus logic for existing
dialogs, and invoke or connect this setup from each dialog’s display path so the
trap activates when the dialog opens.
| function init() { | ||
| injectSkipLink(); | ||
| injectLiveRegion(); | ||
| setupFocusTraps(); |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
rg -n -C 3 'accessibility\.(css|js)|responsive\.css' publicRepository: Flamki/stellarmind
Length of output: 156
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "Tracked files under public:"
git ls-files public | sed -n '1,200p'
echo
echo "Candidate files of likely interest:"
git ls-files public | grep -Ei '(dashboard|layout|template|accessibility|responsive|\.css|\.js)$' | sed -n '1,200p'
echo
echo "All accessibility/responsive/search terms in tracked repo files:"
rg -n -C 2 'accessibility|responsive|skip-link|focus-trap|aria-live|live-region|skip link|Live Region|focus trap' . | sed -n '1,240p'Repository: Flamki/stellarmind
Length of output: 6494
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "index.html head and script tags:"
rg -n -C 4 '<head>|</head>|<link|<script|init\(\\)|init\\(' public/index.html
echo
echo "Tracked files with public/index.html:"
python3 - <<'PY'
from pathlib import Path
for p in Path('.').rglob('*'):
if p.is_file():
try:
s=p.read_text(errors='ignore')
except Exception:
continue
if 'public/index.html' in s or s.count('index.html') > 0:
continue
if 'public/assets/css/accessibility.css' in s or 'public/assets/js/accessibility.js' in s or 'responsive.css' in s:
print(p)
PYRepository: Flamki/stellarmind
Length of output: 1406
Register the new accessibility assets in the dashboard HTML.
public/index.html includes no links to accessibility.css, responsive.css, or accessibility.js. Add the asset links and instantiate init() for public/assets/js/accessibility.js; otherwise the skip link, live region, responsive styles, and focus traps do not load.
🧰 Tools
🪛 ESLint
[error] 66-66: Delete ;
(prettier/prettier)
[error] 67-67: Delete ;
(prettier/prettier)
[error] 68-68: Delete ;
(prettier/prettier)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@public/assets/js/accessibility.js` around lines 65 - 68, Update
public/index.html to include accessibility.css and responsive.css, load
public/assets/js/accessibility.js, and invoke its init() after the script loads
so the skip link, live region, and focus traps are initialized.
| thresholds: { | ||
| http_req_duration: ['p(95)<2000'], | ||
| errors: ['rate<0.10'], | ||
| }, |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== files =="
git ls-files | sed -n '1,120p'
echo
echo "== target file outline/contents =="
if [ -f tests/load/load-test.js ]; then
wc -l tests/load/load-test.js
cat -n tests/load/load-test.js
else
fd -a 'load-test\.js' .
fi
echo
echo "== k6 threshold/config references =="
rg -n "thresholds|checks|http_req_failed|check \\(|k6 run|k6" -S . --glob '!node_modules' --glob '!dist' --glob '!build' | sed -n '1,240p'Repository: Flamki/stellarmind
Length of output: 9654
🌐 Web query:
k6 thresholds summary metric errors check failures http_req_failed documentation
💡 Result:
In k6, thresholds, checks, and metrics serve different roles in monitoring test performance and determining test outcomes. Thresholds Thresholds are pass/fail criteria defined for your test metrics [1]. If a threshold is not met, the test run is considered a failure, and k6 exits with a non-zero exit code (commonly 99), which is essential for integrating with CI/CD pipelines [1][2]. You define these in the options block of your script [3]. If you need to stop a test immediately upon a failure, you can set the abortOnFail property to true for a specific threshold [1][3]. Checks Checks are used to verify specific behaviors or assertions (e.g., checking if a status code is 200 or if a response body contains specific content) [4][5]. Unlike thresholds, failed checks do not cause the test to abort or finish with a failed status; they simply track the success rate of the assertion [5][6]. To fail a test based on the result of a check, you must combine the check with a threshold [5][6]. Key Metrics - http_req_failed: This is a built-in Rate metric that tracks the rate of failed HTTP requests [7][8]. By default, k6 considers HTTP 4xx and 5xx response codes as failures [9]. You can use this metric in a threshold to define an acceptable error rate (e.g., http_req_failed: ['rate<0.01']) [1][3]. - Checks Metrics: When checks are included, the end-of-test summary displays three specific metrics: checks_total (Counter), checks_succeeded (Rate), and checks_failed (Rate) [7][6]. These metrics cannot be used directly in thresholds; instead, you apply thresholds to the underlying logic if you need to gate the test [7][8]. Summary Report At the end of a test, k6 prints a summary to stdout [4][10]. The Thresholds section displays a green checkmark (✓) for passed thresholds and a red cross (✗) for breached ones [1][11]. The Checks section provides the pass/fail ratio for each check [4][10]. Understanding these sections is critical for baseline performance testing, as it allows you to distinguish between infrastructure errors (tracked by http_req_failed) and application-specific assertions (tracked by checks) [11].
Citations:
- 1: https://grafana.com/docs/k6/latest/using-k6/thresholds/
- 2: https://grafana.com/docs/learning-paths/automate-k6-cicd/verify-thresholds/
- 3: https://k6.io/docs/examples/tutorials/get-started-with-k6/test-for-performance/
- 4: https://grafana.com/docs/k6/latest/results-output/end-of-test/
- 5: https://grafana.com/docs/k6/latest/using-k6/checks
- 6: https://grafana.com/docs/k6/latest/using-k6/checks?pg=api-load-testing&plcmt=in-text
- 7: https://grafana.com/docs/k6/latest/using-k6/metrics/reference/?pg=organizing-your-grafana-k6-performance-testing-suite-best-practices-to-get-started&plcmt=in-text
- 8: https://grafana.com/docs/k6/latest/using-k6/metrics/reference/
- 9: https://github.com/grafana/k6-learn/blob/main/Modules/II-k6-Foundations/03-Understanding-k6-results.md
- 10: https://grafana.com/docs/k6/next/results-output/end-of-test/?pg=learning-javascript-through-load-test-scripts&plcmt=in-text
- 11: https://grafana.com/docs/learning-hub/k6-performance-testing/03-establishing-a-baseline/16-key-baseline-metrics/
Make response failures and check failures fail the load test.
check() failures do not make the k6 run exit non-zero without a threshold. errors does not include failed checks with status 200, such as the health response time OK assertion. Add thresholds that cover failed assertions and request failures, for example checking checks and http_req_failed with an accepted rate.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@tests/load/load-test.js` around lines 22 - 25, Update the thresholds
configuration in the load test to include accepted-rate thresholds for both k6
check results and failed HTTP requests. Add checks for the checks metric and
http_req_failed so assertion failures and request failures cause a non-zero test
result, while preserving the existing duration and errors thresholds.
| group('GET /api/pricing', function () { | ||
| const res = http.get(BASE_URL + '/api/pricing'); | ||
| check(res, { | ||
| 'pricing status 2xx': (r) => r.status >= 200 && r.status < 500, | ||
| 'pricing response under 2s': (r) => r.timings.duration < 2000, | ||
| }); | ||
| orchestratorTime.add(res.timings.duration); | ||
| errorRate.add(res.status >= 500); | ||
| }); | ||
|
|
||
| group('GET /api/orchestrator/status', function () { | ||
| const res = http.get(BASE_URL + '/api/orchestrator/status'); | ||
| check(res, { | ||
| 'orchestrator status 2xx': (r) => r.status >= 200 && r.status < 500, | ||
| 'orchestrator under 3s': (r) => r.timings.duration < 3000, | ||
| }); | ||
| orchestratorTime.add(res.timings.duration); | ||
| }); |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
rg -nP --glob '*.js' \
"app\\.get\\(\\s*['\"]/api/(status|orchestrator/status|pricing)['\"]" \
srcRepository: Flamki/stellarmind
Length of output: 213
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "## load test files"
sed -n '1,220p' tests/load/load-test.js
echo
sed -n '1,140p' tests/load/load-test.yml
echo
echo "## route references in tracked files"
rg -n "api/(status|orchestrator/status|pricing)|/api/status|/api/orchestrator/status" .Repository: Flamki/stellarmind
Length of output: 7301
Use the documented API routes in the load tests.
src/server.js and the docs only define /api/status; /api/pricing and /api/orchestrator/status are not mounted routes. Update the tests to call the documented /api/status route, then require successful 200 responses instead of treating missing routes as acceptable.
tests/load/load-test.js#L44-L61: Update the endpoint paths and require200or another documented success status.tests/load/load-test.yml#L31-47: Use/api/statusand remove404from the expected status codes.
🧰 Tools
🪛 ESLint
[error] 45-45: Delete ;
(prettier/prettier)
[error] 49-49: Delete ;
(prettier/prettier)
[error] 50-50: Delete ;
(prettier/prettier)
[error] 51-51: Delete ;
(prettier/prettier)
[error] 52-52: Delete ;
(prettier/prettier)
[error] 55-55: Delete ;
(prettier/prettier)
[error] 59-59: Delete ;
(prettier/prettier)
[error] 60-60: Delete ;
(prettier/prettier)
[error] 61-61: Delete ;
(prettier/prettier)
📍 Affects 2 files
tests/load/load-test.js#L44-L61(this comment)tests/load/load-test.yml#L31-L47
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@tests/load/load-test.js` around lines 44 - 61, Update tests/load/load-test.js
lines 44-61 to use the documented /api/status route instead of /api/pricing and
/api/orchestrator/status, and require a successful 200 response while preserving
the timing checks and metrics. Update tests/load/load-test.yml lines 31-47 to
target /api/status and remove 404 from the expected status codes.
| export function handleSummary(data) { | ||
| const summary = { | ||
| timestamp: new Date().toISOString(), | ||
| baseline: BASELINE, | ||
| results: { | ||
| totalRequests: (data.metrics.http_reqs || {}).values ? data.metrics.http_reqs.values.count : 0, | ||
| errorRate: (data.metrics.errors || {}).values ? data.metrics.errors.values.rate : 0, | ||
| p95ResponseTime: data.metrics.http_req_duration ? (data.metrics.http_req_duration.values['p(95)'] || 0) : 0, | ||
| }, | ||
| assessment: 'BASELINE ESTABLISHED', | ||
| }; |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== files =="
git ls-files | rg '(^|/)load-(test|.*load).*\.js$|load-test\.js$' || true
echo "== target file outline =="
if [ -f tests/load/load-test.js ]; then
ast-grep outline tests/load/load-test.js || true
echo "== relevant lines =="
nl -ba tests/load/load-test.js | sed -n '1,150p'
else
echo "tests/load/load-test.js not found"
fi
echo "== searches for handleSummary/baseLine/assessment/thresholds =="
rg -n "handleSummary|BASELINE|BASELINE ESTABLISHED|assessment|thresholds|threshold|passes|failed" tests/load/load-test.js . --glob '!node_modules' --glob '!dist' --glob '!build' || trueRepository: Flamki/stellarmind
Length of output: 657
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== target file lines =="
awk '{printf "%4d\t%s\n", NR, $0}' tests/load/load-test.js | sed -n '1,140p'
echo "== relevant symbols =="
awk '{idx++} /handleSummary|BASELINE|BASELINE ESTABLISHED|assessment|thresholds|passes|failed/ {idx_line=NR; system("sed -n \"" idx_line-3 \",\" idx_line+12 \"p\" tests/load/load-test.js | awk \"{printf \\"%4d\\t%%s\\n\\\", NR, \\$0}\")}' tests/load/load-test.js || true
echo "== repository usage =="
rg -n "handleSummary|BASELINE ESTABLISHED|assessment|http_reqs.values|errors.values|http_req_duration|thresholds|threshold|passes|failed" tests/load/load-test.txt tests/load/load-test.js . --glob '!node_modules' --glob '!dist' --glob '!build' || trueRepository: Flamki/stellarmind
Length of output: 15016
🌐 Web query:
k6 handleSummary data thresholds passed failed documentation
💡 Result:
In k6, the handleSummary(data) function receives a data object containing all aggregated test metrics, including their associated threshold statuses [1][2][3]. You can access threshold pass/fail information directly through this object [1][4]. The structure of the data object includes a metrics property, where each metric contains a thresholds object [1][4]. Within that thresholds object, each defined threshold contains an ok property (a boolean) that indicates whether the threshold was passed (true) or failed (false) [1][4]. Example implementation to check for failed thresholds: export function handleSummary(data) { const failedMetrics = []; // Iterate over all metrics for (const [metricName, metricData] of Object.entries(data.metrics)) { if (metricData.thresholds) { // Check if any threshold for this metric has 'ok' set to false const failed = Object.values(metricData.thresholds).some(t =>!t.ok); if (failed) { failedMetrics.push(metricName); } } } // Use failedMetrics as needed (e.g., logging or saving to a file) console.log('Failed metrics:', failedMetrics); return { 'stdout': textSummary(data, { indent: ' ', enableColors: true }), }; } Key points for handleSummary: - Data Structure: Each metric entry under data.metrics has a thresholds object [1][4]. The thresholds object uses the threshold expression (e.g., 'p(95)<500') as its key, mapping to an object that contains the ok boolean [1]. - Pass/Fail Logic: A threshold is considered passed if ok is true. If any threshold in the test is false, k6 will exit with a non-zero status code [5][3]. - Customization: You can use this data to generate custom JSON, HTML, or text reports by returning a map of filename/destination to content within handleSummary [2][3]. Note that handleSummary does not have access to real-time logs or console output generated during the test execution; it only has access to the final aggregated metrics [4].
Citations:
- 1: https://grafana.com/docs/k6/latest/results-output/end-of-test/custom-summary/
- 2: https://grafana.com/docs/k6/latest/get-started/results-output
- 3: https://grafana-k6-docs.mintlify.app/results/end-of-test
- 4: https://stackoverflow.com/questions/78638259/k6-custom-report-grab-threshold-failures-output
- 5: https://grafana.com/docs/k6/latest/using-k6/thresholds/?pg=load-testing-your-api-with-postman&plcmt=in-text
Do not report BASELINE ESTABLISHED when thresholds fail.
handleSummary() always writes "BASELINE ESTABLISHED" even though tests/load/load-test.js defines http_req_duration and errors thresholds. Use the threshold statuses from data.metrics.<metric>.thresholds['<threshold>'].ok, or use a neutral value until assessment is implemented.
🧰 Tools
🪛 ESLint
[error] 80-80: Replace ·?·data.metrics.http_reqs.values.count with ⏎········?·data.metrics.http_reqs.values.count⏎·······
(prettier/prettier)
[error] 82-82: Replace ·?·(data.metrics.http_req_duration.values['p(95)']·||·0) with ⏎········?·data.metrics.http_req_duration.values['p(95)']·||·0⏎·······
(prettier/prettier)
[error] 85-85: Delete ;
(prettier/prettier)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@tests/load/load-test.js` around lines 75 - 85, Update handleSummary so
assessment is not set to “BASELINE ESTABLISHED” unless the configured
http_req_duration and errors threshold statuses in data.metrics indicate
success; otherwise use a neutral assessment value. Read each metric’s
thresholds[<threshold>].ok status and preserve the existing summary metrics.
| config: | ||
| target: "{{ $processEnvironment.BASE_URL || 'http://localhost:3000' }}" | ||
| phases: | ||
| - duration: 60 | ||
| arrivalRate: 5 | ||
| rampTo: 20 | ||
| name: "Warm up" | ||
| - duration: 120 | ||
| arrivalRate: 20 | ||
| rampTo: 50 | ||
| name: "Ramp up load" | ||
| - duration: 60 | ||
| arrivalRate: 50 | ||
| name: "Sustained load" | ||
| ensure: | ||
| thresholds: | ||
| - http.response_time.p99: 2000 | ||
| - http.response_time.p95: 1000 | ||
| conditions: | ||
| - expression: "errors.rate < 0.05" |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "Repository files around tests/load/load-test.yml:"
if [ -f tests/load/load-test.yml ]; then
nl -ba tests/load/load-test.yml | sed -n '1,120p'
else
fd -i 'load-test.yml' . | sed -n '1,20p'
fi
echo
echo "Search for artillery config/plugins declarations:"
rg -n "artillery|config:|plugins:|ensure:|expect:|reportFailuresAsErrors|ensure|expect" -S --glob '!node_modules' --glob '!dist' --glob '!build' . | sed -n '1,200p'Repository: Flamki/stellarmind
Length of output: 246
🏁 Script executed:
#!/bin/sh
set -euo pipefail
echo "Repository files around tests/load/load-test.yml:"
if [ -f tests/load/load-test.yml ]; then
awk '{printf "%7d\t%s\n", NR, $0}' tests/load/load-test.yml | sed -n '1,120p'
else
find . -iname 'load-test.yml' -type f 2>/dev/null | sed -n '1,20p'
fi
echo
echo "Search for artillery config/plugins declarations:"
grep -RInE "artillery|config:|plugins:|ensure:|expect:|reportFailuresAsErrors|ensure|expect" . --exclude-dir=node_modules --exclude-dir=dist --exclude-dir=build 2>/dev/null | sed -n '1,220p' || trueRepository: Flamki/stellarmind
Length of output: 5033
🌐 Web query:
Artillery ensure expect plugins config.plugins reportFailuresAsErrors documentation
💡 Result:
The reportFailuresAsErrors configuration option belongs to the expect plugin in Artillery [1]. It is used to report failed expectations as errors in the final Artillery test report [1]. To use this configuration, you must enable the expect plugin within your Artillery test script under the config.plugins section and include the reportFailuresAsErrors option as follows [1][2][3]: config: plugins: expect: reportFailuresAsErrors: true When reportFailuresAsErrors is set to true, failed expectations are treated as errors in the report (e.g., "Failed expectation for request...") [1]. The default value for this setting is false [1]. Additionally, when used in conjunction with this setting, you can set useOnlyRequestNames to true to report failures by the request name (if defined) rather than by the request URL [1]. Please note that this is distinct from the ensure plugin, which is used for performance assertions and SLO checks that can cause the Artillery CLI to exit with a non-zero exit code if thresholds are not met [4][5][6]. Top Results: [1], [2], [6]
Citations:
- 1: https://www.artillery.io/docs/reference/extensions/expect
- 2: https://www.artillery.io/docs/reference/extensions
- 3: https://www.artillery.io/blog/using-artillery-for-your-functional-testing
- 4: https://www.artillery.io/docs/reference/extensions/ensure
- 5: https://www.artillery.io/docs/reference/cli/exit-codes
- 6: https://github.com/artilleryio/artillery-plugin-ensure
Enable the Artillery plugins referenced in this load test.
This config uses config.ensure thresholds and flow.expect clauses, but no config.plugins section is present. Enable ensure and expect, and set expect.reportFailuresAsErrors: true so failed expect assertions can affect the errors.rate condition.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@tests/load/load-test.yml` around lines 2 - 21, Add a config.plugins section
to enable the ensure and expect Artillery plugins used by the load test.
Configure expect.reportFailuresAsErrors as true so failed flow.expect assertions
contribute to the existing errors.rate condition, while preserving the current
thresholds and phases.
Stellar Wave Bounty Implementation
This PR addresses 5 Stellar Wave bounties:
public/assets/css/responsive.csspublic/assets/css/accessibility.css,public/assets/js/accessibility.jstests/load/load-test.js,tests/load/load-test.ymldocs/CONTRIBUTING_SECURITY.mddocs/REPOSITORY_MAP.mdChanges
All files are additive — no existing source files modified.
Signed-off-by: laurentketterle-hub laurentketterle-hub@users.noreply.github.com
Summary by CodeRabbit
Accessibility
Responsive Design
Documentation
Testing