Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
dc88e77
[issue-287] Refactor neuro out of Layout.h (#877)
NicolasJPosey Aug 12, 2025
97075c3
Added Star Wong to Contributors.md
Oct 23, 2025
bc0bc30
- adjusted set(ENABLE CUDA YES) to be on their own line so that it ca…
stardriftfx Oct 23, 2025
ca6f1a3
= added CUDAToolkit_root
stardriftfx Oct 23, 2025
89a018e
- .gitignore: removed CMakeList
stardriftfx Oct 23, 2025
314f3b7
Merge pull request #888 from UWB-Biocomputing/issue-887-add-contributor
stardriftfx Oct 31, 2025
d492938
Added Kyle Ricks to Contributors.md
Hum-Bao Nov 6, 2025
b028b6f
Merge pull request #891 from UWB-Biocomputing/issue-890-add-contributor
kblricks Nov 10, 2025
d904172
Hotfix from master
stiber Jan 16, 2026
33570a2
Update compare_matrices.cpp to properly compare two outputs instead o…
kblricks Jan 21, 2026
a955cb8
Change test.yml to use new compare_matrices.cpp instead of diff
kblricks Jan 21, 2026
7ed2c33
Change tests.yml to run workflow on issue branch for testing
kblricks Jan 21, 2026
adfdd89
Merge remote-tracking branch 'origin/SharedDevelopment' into issue-84…
kblricks Jan 21, 2026
0735fd6
Merge test.yml from SharedDevelopment and fix file input order for ma…
kblricks Jan 21, 2026
1433fb0
Remove dev branch from tests.yml since tests passed with compare_matr…
kblricks Jan 21, 2026
02a8be2
Removed if statements. The if statements mean that GH actions would c…
stardriftfx Jan 21, 2026
644af4f
Merge pull request #904 from UWB-Biocomputing/894-stop-github-actions…
stardriftfx Jan 22, 2026
5ece139
Merge branch 'origin/SharedDevelopment' into issue-848-replace-simple…
kblricks Jan 23, 2026
b7795f5
Update compare_matrices to have better error checking/handling
kblricks Jan 23, 2026
8d892af
Fix comparison bug in approximately_equal
kblricks Jan 25, 2026
be1d900
Add check for failed parsing and better check for empty files
kblricks Jan 26, 2026
db153ad
Merge pull request #903 from UWB-Biocomputing/issue-848-replace-simpl…
kblricks Jan 28, 2026
6e252a5
[issue-873] Templated Event Buffer (#876)
NicolasJPosey Jan 30, 2026
7335b41
Add unit test prompt file for auto generating test cases with copilot
kblricks Feb 4, 2026
2e52870
Add copilot-instructions.md file for better PR code reviews
kblricks Feb 5, 2026
ffba67e
Fix formatting and style issues in md files, and added additional ins…
kblricks Feb 8, 2026
befbbce
Remove the wildcard instructions file as it does not seem to do anyth…
kblricks Feb 8, 2026
833c3ce
Refactor the test case prompt to also be shorter and more concise
kblricks Feb 8, 2026
4c8b800
Further refinements to prompts and instructions, and added documentat…
kblricks Feb 9, 2026
111d5ad
Refactor files again and repush since last push did not show in the pr
kblricks Feb 17, 2026
da22048
Fix minor spelling and formatting errors
kblricks Feb 18, 2026
4541eb4
Update copilot-instructions.md to better meet GitHub's reccomendation…
kblricks Feb 23, 2026
d5a64e0
Update .prompt.md file to be more concise, leverage tools, and have a…
kblricks Feb 23, 2026
f6a44bc
Merge pull request #912 from UWB-Biocomputing/issue-812-llm-unit-tests
kblricks Feb 25, 2026
cdae890
Add debug.prompt.md file for debugging code issues
kblricks Mar 5, 2026
cab259c
Add doc file for debug prompt, and move re-used information into sepa…
kblricks Mar 5, 2026
65d647e
Fix small errors with links and documentation info
kblricks Mar 5, 2026
e45ae36
Fix typos and broken crosslinks and made sections more clear
kblricks Mar 5, 2026
e59e8f6
Add more crosslinks for sections that were missing them, and added Ma…
kblricks Mar 7, 2026
a5323c3
Merge pull request #915 from UWB-Biocomputing/issue-914-add-debug-pro…
kblricks Mar 8, 2026
7b905ff
Rename slash command from /debug to /debug-code, as copilot sometimes…
kblricks Mar 9, 2026
b49d55f
Update doc example to say /debug-code instead of /debug
kblricks Mar 9, 2026
4df50a2
Merge pull request #917 from UWB-Biocomputing/issue-914-add-debug-pro…
kblricks Mar 9, 2026
7616b04
Merge PoseyDevelopment into SharedDevelopment (#918)
NicolasJPosey Mar 13, 2026
a804b4b
Merge pull request #919 from UWB-Biocomputing/SharedDevelopment
stiber Mar 13, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 83 additions & 0 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# Graphitti Copilot Instructions

## 1. Project Overview

Graphitti is a high-performance graph-based simulator for computational neuroscience and emergency communications research, developed at the University of Washington Bothell. It simulates large-scale graphs (tens of thousands of vertices; millions of edges) over billions of time steps. It runs on both CPUs and GPUs.

Repository: https://github.com/UWB-Biocomputing/Graphitti

## 2. Tech Stack

- **Language:** C++17 (strict)
- **Build System:** CMake
- **Testing:** Google Test (gtest)
- **Logging:** log4cplus
- **GPU:** CUDA (guarded by `USE_GPU` and `ENABLE_CUDA` macros)
- **Parallelism:** CUDA (GPU); OpenMP planned for CPU multi-threading
- **Data Recording:** HDF5 (binary) and XML
- **Config Format:** XML (parsed via `ParameterManager`)
- **OS:** GNU/Linux

## 3. Code Standards

Apply these rules to every code generation and review task.

### Language & Modern C++

- **Standard:** C++17. Do not use features from C++20 or later.
- Avoid manual `delete` and owning raw pointers; prefer RAII and smart pointers (`std::unique_ptr` / `std::shared_ptr`).
- Avoid `printf`; use standard streams or log4cplus.
- Prefer `<algorithm>` when it improves clarity, but traditional loops are acceptable in performance-critical paths.
- Use `[[nodiscard]]` on functions with non-void return values to prevent silent discard of error codes or computed results.
- Use `const` and `constexpr` wherever possible.
- Use `#pragma once` for all headers.
- Use explicit `override` on virtual function overrides.

### Formatting

- **Indentation:** 3 spaces. Not 2, not 4. This is a project-wide convention for codebase consistency.
- **Column Limit:** 100 characters.
- **Naming:**
- `CamelCase` for classes: `Vertex`, `Graph`, `EdgeIndexMap`.
- `camelCase` for variables and functions: `numVertices`, `calculateEdges`.
- No `snake_case`.
- **Braces:**
- Control flow: Cuddled (`} else {`).
- Functions: Opening `{` on a new line.
- Always use braces, even for single-line blocks, to prevent dangling-else bugs when lines are added during maintenance.

## 4. Architecture Map

Understand where code belongs so you can suggest correct file paths and appropriate performance considerations.

- **`Simulator/Core/`** — The simulation hot path. Code here must be highly optimized. `Graphitti_Main.cpp` is the entry point; `Simulator::simulate()` and `Simulator::advanceEpoch()` are the main loop.
- **`Simulator/Edges/`** and **`Simulator/Vertices/`** — Graph element implementations with internal state. Frequently called per time step.
- **`Simulator/Recorders/`** — Data recording subsystem. Supports `XmlRecorder` and `HDF5Recorder`.
- **`Testing/UnitTesting/`** — Google Test unit tests. Must be fast and isolated.
- **`Testing/RegressionTesting/`** — Full simulation runs. Only modify when physics or logic changes.
- **`ThirdParty/`** — External dependencies. **Read-only.** Do not suggest changes here.

## 5. Pull Request Review Priorities

When reviewing PRs or suggesting fixes, check in this order:

1. Flag unnecessary object copying; suggest `const&` or move semantics.
2. Flag expensive allocations or dynamic_cast calls inside simulation loops (`Simulator/Core/`).
3. Identify potential cache misses in hot loops.
4. Check for iterator invalidation and thread-safety in shared data structures (OpenMP/CUDA context).
5. Verify `CMakeLists.txt` is updated if source files were added or removed.
6. Verify all required headers are included.

## 6. Testing Requirements

- **New logic** must have corresponding `TEST()` or `TEST_F()` cases in `Testing/UnitTesting/`.
- **Bug fixes** require a regression test if the bug was a logic error.
- **GPU code** (`.cu` files) must check `ENABLE_CUDA` macros and have CPU-path equivalents tested.
- Test names use `PascalCase`: `TEST(Graph, AddsVertexCorrectly)`.
- Use `EXPECT_*` for non-fatal assertions; use `ASSERT_*` for preconditions where continuing would crash.

## 7. Interaction Behavior

- **On PR review:** Start by identifying the impact area (e.g., "This PR modifies the core simulation loop; checking performance constraints...").
- **On code generation:** Always specify the file path where the generated code should be placed, based on the Architecture Map above.
- **On refactoring:** Preserve existing public API signatures unless the user explicitly requests breaking changes.
167 changes: 167 additions & 0 deletions .github/prompts/debug.prompt.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
---
name: debug-code
description: Trace and explain the root cause of a bug in the C++17 Graphitti code
agent: agent
tools: ["search", "read"]
---

# Inputs and Context

Use the following inputs as the primary source of truth for expected vs. actual behavior. Treat them as ground truth unless you explicitly state otherwise in your assumptions.

- **Problem description from the user (required):**

${input:problemDescription}

- **Target code (optional selection from the editor):**

${selection}

- **Steps to reproduce (optional):**

${input:stepsToReproduce}

- **Logs, stack traces, or failing test output (optional):**

${input:logs}

- **Environment / configuration details (optional):**

${input:environment}

If any of these are missing or incomplete, call that out explicitly in the **Assumptions and Scope** section instead of silently guessing.

# Step 1: Understand the Code and Problem

Before proposing any fix, read and summarize the target code and the reported behavior. Answer these questions internally (do not output them):

1. **What is the primary function, method, or code path under suspicion?** Is this a class (`Graph`, `Vertex`), a free function, or a template?
2. **What is the expected behavior versus the actual behavior?** Include inputs, outputs, and any side effects.
3. **What dependencies does it have?** Other Graphitti classes, standard library containers, external libraries?
4. **What invariants or assumptions are relevant?** (e.g., "vertex count must equal the size of the adjacency list", "counter should increase by exactly 1").
5. **What categories of bug are most likely?** (logic error, off-by-one, stale or shared state, wrong constant, incorrect default, misuse of a dependency, etc.).

Use the **Inputs and Context** section above as your starting point. Do **not** output your answers to these questions directly. Use them only to guide the trace and explanation in later steps.

# Step 2: Trace the Execution Path

Now that you understand the problem, trace how the code executes from the entry point of the bug to the final incorrect result.

Use the `search` and `read` tools to locate and inspect any relevant files, definitions, and call sites in the Graphitti codebase (for example, where a method is defined and where it is called).

Design an internal execution trace that answers:

1. Which public or entry-point function is called when this bug occurs?
2. Which functions, methods, or constructors are invoked along the way (including helpers, virtual overrides, and templates)?
3. How do the key values change at each step (inputs, member variables, return values, accumulators, caches)?
4. Which branches or conditions are taken in the failing scenario?
5. Where is the first point at which the state diverges from what is expected?

Do not output this raw trace verbatim. In the next step, you will convert it into a clear explanation for the user.

When exploring the repository:

- Only reference functions, classes, and files that you have actually located with `search` / `read`.
- If you cannot find a symbol, file, or configuration that seems important, note this as a limitation in **Assumptions and Scope** rather than inventing its behavior.

# Step 3: Explain the Root Cause and Fix

Using the analysis from Step 1 and the trace from Step 2, generate a structured debugging report following these rules:

## Project Conventions

- Organize the answer into the following sections, in this exact order:
1. **Problem Summary** — Restate the bug in 1–3 sentences, including the relevant function(s) and the expected vs. actual behavior.
2. **Assumptions and Scope** — Briefly list any assumptions you are making about inputs, configuration, or environment, including any missing information from the Inputs and Context section.
3. **Execution Trace** — Summarize the key steps in the call chain that lead to the incorrect result, focusing on functions, important state changes, and branches taken.
4. **Root Cause Analysis** — Explain precisely _why_ the bug happens, referencing specific functions, conditions, or state transitions.
5. **Proposed Fix** — Describe a minimal, targeted change that would correct the behavior, including a concrete code snippet or patch-style suggestion when appropriate.
6. **Verification Steps** — Outline how to verify the fix (existing tests to run, new tests to add, and any manual steps).

- In **Execution Trace**, summarize only the essential steps, state changes, and branches relevant to the failing scenario. Avoid line-by-line commentary or speculative paths that are not actually taken when the bug occurs.
- Only reference functions, classes, files, and configuration values that you have actually seen in the repository or in the provided inputs. If something is inferred or assumed, make that explicit in **Assumptions and Scope**.
- If there are multiple plausible root causes or the available information is incomplete, clearly:
- Identify the most likely root cause first.
- List alternative possibilities as secondary hypotheses, along with what extra data would be needed to confirm or reject them.
- Use concise paragraphs and bullet points. Avoid long, unstructured walls of text.
- When referencing functions or methods, include both the name and file path where possible (e.g., ``Counter::increment` in `Simulator/Utils/Counter.cpp``).

## File Placement

- You are **not** required to create or edit files directly in this prompt. Focus on analysis and explanation.
- When you propose code changes, show them as **snippets** the user can apply manually, rather than editing files yourself.
- If you reference tests or new test files, follow the existing project structure:
- Unit tests live under `Testing/UnitTesting/`.
- For functions touched by the fix, you may suggest using the `/generate-unit-tests` prompt on the affected code to create new tests that reproduce the bug and guard against regressions.

## Code Style

- Keep code examples minimal and focused on the bug and its fix.
- Use C++17 features and the project’s conventions when writing example code (e.g., `auto` where appropriate, no `using namespace std;`).
- When showing a fix, include only the smallest necessary surrounding context (e.g., the function signature plus the corrected lines).
- Add brief inline comments explaining _why_ the fix works, especially when adjusting constants, conditions, or state transitions.

## Few-Shot Example

Below is an example of the expected output format. Match this style exactly, adapting it to the actual bug and code under analysis.

**Input:** Problem description — “`Counter::increment()` always returns 2 when it should return 1 after a single call.” The user selects the implementation of `Counter::increment()` and its helper `internalAdd`.

**Output:**

````md
1. Problem Summary

`Counter::increment()` increases the internal counter by 2 instead of 1 on a single call.
Expected: calling `increment()` once from an initial count of 0 should yield 1.
Actual: the count becomes 2.

2. Assumptions and Scope

- We assume `Counter` starts at 0 unless explicitly initialized otherwise.
- We focus on the non-thread-safe, single-threaded usage of `Counter`.
- No external configuration or environment flags modify the increment step.

3. Execution Trace

- Step 1: `Counter::increment()` is called while `count_` is 0 (`Simulator/Utils/Counter.cpp`, ~line 25).
- Step 2: Inside `increment()`, it calls `internalAdd(2)` instead of `internalAdd(1)`.
- Step 3: `internalAdd(2)` updates `count_` from 0 to 2 and returns.
- Step 4: `getCount()` simply returns `count_` without further modification, so the observed result is 2.

4. Root Cause Analysis

The root cause is a hard-coded increment value of 2 inside `Counter::increment()`.
The intended behavior is to increase the count by exactly 1 per call, but the call to `internalAdd(2)` doubles the expected increment.
There are no additional side effects or state mutations that compensate for this, so the incorrect value propagates directly to `getCount()`.

5. Proposed Fix

Change the argument passed to `internalAdd` from 2 to 1:

```cpp
void Counter::increment() {
// Increment by 1 to match the documented behavior.
internalAdd(1);
}
```

This ensures a single call to increment() increases count\_ by exactly 1.

6. Verification Steps

Add or update a unit test that:

- Constructs a Counter at 0.
- Calls increment() once.
- Asserts that getCount() returns 1.

Run the existing unit test suite (for example, ctest or your standard test command) to confirm no unrelated regressions.

Optionally, use the /generate-unit-tests prompt on Counter to generate additional tests that:

- Call increment() twice and confirm the result is 2.
- Interleave increment() and decrement() and ensure the count returns to the original value.
````

Now generate the debugging report for the target problem and selection.
102 changes: 102 additions & 0 deletions .github/prompts/generate-unit-tests.prompt.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
---
name: generate-unit-tests
description: Generate comprehensive Google Test cases for C++17 Graphitti code
agent: agent
tools: ["search", "read", "edit"]
---

# Step 1: Understand the Code

Before writing any tests, read and summarize the target code. Answer these questions internally (do not output them):

1. **What is the SUT (System Under Test)?** Is this a class (`Graph`, `Vertex`), a free function, or a template?
2. **What are the public methods and their signatures?** List each method, its parameters, return type, and any preconditions.
3. **What dependencies does it have?** Other Graphitti classes, standard library containers, external libraries?
4. **What invariants does the class maintain?** (e.g., "vertex count must equal the size of the adjacency list")
5. **What can go wrong?** Null pointers, empty containers, out-of-range indices, integer overflow, floating point precision.

Target Code:
${selection}

# Step 2: Design the Test Plan

Now that you understand the code, design 5–7 test scenarios covering these categories. For each scenario, write one sentence describing the test and the expected outcome.

1. **Happy Path** — The standard use case works as expected.
2. **Boundary Values** — Min/max values (0 nodes, max edges, empty containers, single-element collections).
3. **Error Handling** — Verify correct exceptions are thrown or error codes are returned for invalid input.
4. **State Preservation** — After an operation, the object is in a valid and expected state.
5. **Idempotency / Repeated Calls** — Calling a method twice produces consistent results.
6. **Interaction Between Methods** — A sequence of operations (e.g., add then remove) leaves the object in the correct state.

# Step 3: Generate the Test Code

Using the analysis from Step 1 and the plan from Step 2, generate the C++ test code following these rules:

## Project Conventions

- Use `PascalCase` for test names: `TEST(Graph, AddsVertexCorrectly)`.
- Do NOT use `using namespace std;`.
- Use `EXPECT_*` for assertions that should not abort the test. Use `ASSERT_*` for pointer validity or preconditions where continuing would crash.
- Use the AAA pattern: **Arrange** (setup), **Act** (call the method), **Assert** (verify the result). Separate each section with a blank line.

## File Placement

- All tests go into `Testing/UnitTesting/`.
- If a test file already exists (e.g., `Testing/UnitTesting/VertexTests.cpp`), generate **only the new test cases** to append.
- If no test file exists, generate the **entire file** including headers and fixture setup.

## Code Style

- Include necessary headers with relative paths (e.g., `#include "Simulator/Core/Vertex.h"`).
- If the class requires complex setup, create a test fixture: `class VertexTest : public ::testing::Test { ... }`.
- Use C++17 features where appropriate: `auto`, structured bindings, `std::optional`, `constexpr`.
- Add a brief inline comment on each test explaining **why** that specific value or scenario is being tested.

## Few-Shot Example

Below is an example of the expected output format. Match this style exactly.

**Input:** A class `Counter` with methods `increment()`, `decrement()`, and `getCount()`.

**Output:**

```cpp
#include <gtest/gtest.h>
#include "Simulator/Utils/Counter.h"

class CounterTest : public ::testing::Test {
protected:
Counter counter_;

void SetUp() override {
counter_ = Counter();
}
};

// Happy path: incrementing increases the count by 1
TEST_F(CounterTest, IncrementIncreasesCount) {
counter_.increment();

EXPECT_EQ(counter_.getCount(), 1);
}

// Boundary: decrementing from zero should not produce a negative count
TEST_F(CounterTest, DecrementFromZeroDoesNotGoNegative) {
counter_.decrement();

EXPECT_GE(counter_.getCount(), 0);
}

// State preservation: increment then decrement returns to original state
TEST_F(CounterTest, IncrementThenDecrementReturnsToOriginal) {
int original = counter_.getCount();

counter_.increment();
counter_.decrement();

EXPECT_EQ(counter_.getCount(), original);
}
```

Now generate the test code for the target selection.
Loading
Loading