Skip to content

feat: Stellar Wave — responsive, accessibility, load tests, security, repo map (#34, #35, #38, #50, #48) - #111

Open
laurentketterle-hub wants to merge 7 commits into
Flamki:masterfrom
laurentketterle-hub:feat/stellarwave-v2
Open

feat: Stellar Wave — responsive, accessibility, load tests, security, repo map (#34, #35, #38, #50, #48)#111
laurentketterle-hub wants to merge 7 commits into
Flamki:masterfrom
laurentketterle-hub:feat/stellarwave-v2

Conversation

@laurentketterle-hub

@laurentketterle-hub laurentketterle-hub commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

Stellar Wave Bounty Implementation

This PR addresses 5 Stellar Wave bounties:

Issue Description File(s)
Closes #34 Mobile responsiveness public/assets/css/responsive.css
Closes #35 Accessibility improvements public/assets/css/accessibility.css, public/assets/js/accessibility.js
Closes #38 Load test scenarios tests/load/load-test.js, tests/load/load-test.yml
Closes #50 Security checklist docs/CONTRIBUTING_SECURITY.md
Closes #48 Repository map docs/REPOSITORY_MAP.md

Changes

All files are additive — no existing source files modified.

Signed-off-by: laurentketterle-hub laurentketterle-hub@users.noreply.github.com

Summary by CodeRabbit

  • Accessibility

    • Added keyboard-friendly navigation, visible focus indicators, screen-reader support, improved contrast, reduced-motion handling, and accessible dialog focus management.
  • Responsive Design

    • Improved tablet and mobile layouts, including collapsible navigation, off-canvas menus, adaptive dashboards, table scrolling, and print-friendly styling.
  • Documentation

    • Added contributor guidance for security practices, repository structure, setup, and development workflows.
  • Testing

    • Added load-testing coverage for health, pricing, status, homepage, and streaming endpoints with performance and error thresholds.

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>
@coderabbitai

coderabbitai Bot commented Aug 8, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The PR adds contributor security and repository documentation, accessibility and responsive dashboard assets, and staged k6 and Artillery load tests for core endpoints.

Changes

Contributor documentation

Layer / File(s) Summary
Security checklist and repository map
docs/CONTRIBUTING_SECURITY.md, docs/REPOSITORY_MAP.md
Adds pre-PR security checks, repository structure guidance, setup commands, workflows, and architecture notes.

Accessibility and responsive UI

Layer / File(s) Summary
Accessibility behavior
public/assets/css/accessibility.css, public/assets/js/accessibility.js
Adds skip navigation, live-region support, focus styles, reduced-motion and high-contrast rules, target sizing, and dialog focus trapping.
Responsive and print layout
public/assets/css/responsive.css
Adds tablet, mobile, and print styles for the sidebar, menu toggle, content, tables, dashboard grids, and cards.

Load-test coverage

Layer / File(s) Summary
Load-test profiles and scenarios
tests/load/load-test.js, tests/load/load-test.yml
Defines configurable URLs, staged load phases, endpoint scenarios, expected statuses, and performance thresholds.
k6 execution and reporting
tests/load/load-test.js
Runs requests against health, pricing, orchestrator status, and homepage endpoints, records metrics, and writes JSON summaries.

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
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning The PR addresses responsiveness and accessibility [#34, #35], but load-test targets [#38] and requested documentation locations [#48, #50] are not clearly met. Target /api/orchestrate and /api/events with documented concurrency and baselines, add the checklist to CONTRIBUTING.md, and place or link the repository map from README.md or CONTRIBUTING.md.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the five main changes and identifies the related issues.
Description check ✅ Passed The description gives a clear scope and file mapping, but it omits the template's Validation and Checklist sections.
Out of Scope Changes check ✅ Passed The added CSS, JavaScript, tests, and contributor documentation all relate to the five linked objectives; no unrelated product changes are identified.
✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 8

🧹 Nitpick comments (1)
docs/REPOSITORY_MAP.md (1)

7-31: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add a language identifier to the fenced tree block.

Markdownlint reports MD040 on Line 7. Use text for 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

📥 Commits

Reviewing files that changed from the base of the PR and between 6eb1d2b and c92754a.

📒 Files selected for processing (7)
  • docs/CONTRIBUTING_SECURITY.md
  • docs/REPOSITORY_MAP.md
  • public/assets/css/accessibility.css
  • public/assets/css/responsive.css
  • public/assets/js/accessibility.js
  • tests/load/load-test.js
  • tests/load/load-test.yml

@@ -0,0 +1,51 @@
# Security Checklist for Contributors — Closes #50

Review before pushing code. Supplements [CONTRIBUTING.md](./CONTRIBUTING.md).

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 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.md to ../CONTRIBUTING.md if the root-level file is intended.
  • docs/REPOSITORY_MAP.md#L17-L23: document the actual locations of route and validation code, including src/server.js and src/requestValidation.js.
  • docs/REPOSITORY_MAP.md#L39-L41: align the src/api/ guidance with the actual route-registration boundary.
📍 Affects 2 files
  • docs/CONTRIBUTING_SECURITY.md#L3-L3 (this comment)
  • docs/REPOSITORY_MAP.md#L17-L23
  • docs/REPOSITORY_MAP.md#L39-L41

Comment on lines +25 to +46
@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;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 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' public

Repository: 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 || true

Repository: 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:


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.

Comment on lines +22 to +56
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 });

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 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.

Comment on lines +65 to +68
function init() {
injectSkipLink();
injectLiveRegion();
setupFocusTraps();

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

rg -n -C 3 'accessibility\.(css|js)|responsive\.css' public

Repository: 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)
PY

Repository: 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.

Comment thread tests/load/load-test.js
Comment on lines +22 to +25
thresholds: {
http_req_duration: ['p(95)<2000'],
errors: ['rate<0.10'],
},

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 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:


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.

Comment thread tests/load/load-test.js
Comment on lines +44 to +61
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);
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 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)['\"]" \
  src

Repository: 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 require 200 or another documented success status.
  • tests/load/load-test.yml#L31-47: Use /api/status and remove 404 from 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.

Comment thread tests/load/load-test.js
Comment on lines +75 to +85
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',
};

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 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' || true

Repository: 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' || true

Repository: 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:


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.

Comment thread tests/load/load-test.yml
Comment on lines +2 to +21
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"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 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' || true

Repository: 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:


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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant