Skip to content

Commit be077d9

Browse files
CopilotbedaHovorkaclaude
authored
Add GitHub Copilot instructions (#9)
* Initial plan * Add GitHub Copilot instructions file Co-authored-by: bedaHovorka <5263405+bedaHovorka@users.noreply.github.com> * Add nullability guidelines for Java-to-Kotlin conversion Co-authored-by: bedaHovorka <5263405+bedaHovorka@users.noreply.github.com> * Fix jdisco URL capitalization for consistency Co-authored-by: bedaHovorka <5263405+bedaHovorka@users.noreply.github.com> * Add copilot/** branch triggers to GitHub Actions workflows Enables CI/CD automation for branches prefixed with copilot/, ensuring they receive the same build, test, and quality analysis as feature/** branches. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com> * Fix Claude Code Review workflow permissions to allow PR comments Changed pull-requests permission from read to write to enable the workflow to post review comments using 'gh pr comment' command. This resolves the "User does not have write access" authentication error. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com> * Initial plan --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: bedaHovorka <5263405+bedaHovorka@users.noreply.github.com> Co-authored-by: Bedřich Hovorka <bedrich.hovorka@gmail.com> Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
1 parent 6ea09c9 commit be077d9

1 file changed

Lines changed: 343 additions & 0 deletions

File tree

.github/copilot-instructions.md

Lines changed: 343 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,343 @@
1+
# GitHub Copilot Instructions
2+
3+
This file provides guidance to GitHub Copilot when working with code in this repository.
4+
5+
## Project Overview
6+
7+
Railway Interlocking Simulator - A BSc thesis project (2006/2007) from Brno University of Technology that simulates railway interlocking systems with a graphical editor and discrete event simulation engine.
8+
9+
**Language:** Kotlin (migrated from Java in January 2026)
10+
**Build System:** Gradle with Kotlin DSL
11+
**Java Version:** Java 21 LTS minimum
12+
13+
## Quick Start
14+
15+
**Build and test:**
16+
```bash
17+
./gradlew clean build
18+
```
19+
20+
**Run tests:**
21+
```bash
22+
./gradlew test # Unit tests only
23+
./gradlew integrationTest # Integration tests
24+
```
25+
26+
**Run editor GUI:**
27+
```bash
28+
./gradlew runEditor
29+
```
30+
31+
**Run simulation:**
32+
```bash
33+
./gradlew runSim
34+
```
35+
36+
## Build System
37+
38+
This project uses **Gradle with Kotlin DSL**. Key files:
39+
- `build.gradle.kts` - Build configuration and dependencies
40+
- `settings.gradle.kts` - Project settings
41+
- `gradle.properties` - Version management
42+
43+
### Dependencies
44+
45+
- **jDisco 1.2.0** - Discrete event simulation library (Java 6 compatible)
46+
- Repository: https://github.com/bedaHovorka/jdisco
47+
- Published to GitHub Packages
48+
- **JUnit 5.11.4** - Testing framework
49+
- **AssertJ 3.27.6** - Fluent assertions
50+
- **Mockito 5.21.0** - Mocking framework
51+
- **SLF4J 2.0.17** + **Logback 1.5.23** - Logging
52+
53+
## Architecture
54+
55+
### Main Entry Point
56+
57+
`cz.vutbr.fit.interlockSim.Main` - Handles three modes:
58+
- `sim` - Run simulation from XML file
59+
- `edit` - Launch graphical editor
60+
- `example` - Run built-in examples (uses `@Example` annotation)
61+
62+
### Core Components
63+
64+
**Context System:**
65+
- `Context` - Base abstraction for railway network configuration
66+
- `SimulationContext` - Simulation execution context
67+
- Factory pattern for context creation
68+
69+
**Object Model:**
70+
- `objects/tracks/` - Track facilities, blocks, occupants
71+
- `objects/cells/` - Grid-based spatial representation
72+
- `objects/paths/` - Route management
73+
74+
**Simulation Engine:**
75+
- Built on jDisco library (external dependency)
76+
- `sim/` package contains simulation processes
77+
78+
**GUI:**
79+
- Swing-based editor in `gui/` package
80+
- Grid-based canvas for track layout editing
81+
82+
### Package Structure
83+
84+
```
85+
src/main/kotlin/cz/vutbr/fit/interlockSim/
86+
├── Main.kt - Application entry point
87+
├── context/ - Context management and factories
88+
├── gui/ - Graphical editor (Swing)
89+
├── objects/ - Domain model (tracks, paths, cells)
90+
├── sim/ - Simulation scenarios
91+
├── util/ - Utilities and reporting
92+
└── xml/ - XML parsing and serialization
93+
```
94+
95+
## CRITICAL: Code Modification Guidelines
96+
97+
**Be extremely conservative when editing code in this codebase.**
98+
99+
### Rules
100+
101+
1. **Do not refactor or "improve" working code** - This is a historical codebase from 2007. Stability > modernization.
102+
103+
2. **Tests must exist before modifications** - Any file being modified MUST be covered by tests first. If tests don't exist, write them before changes.
104+
105+
3. **Minimal changes only** - Make only the specific changes requested, nothing more.
106+
107+
4. **No unsolicited modernization** - Do not update code to modern Kotlin/Java features unless explicitly requested.
108+
109+
5. **jDisco library** - jDisco is maintained separately. Do not modify jDisco code; report issues at https://github.com/bedaHovorka/jdisco
110+
111+
### Conservative Approach Applies To
112+
113+
- Java/Kotlin source code
114+
- Build configuration (unless breaking)
115+
- Architecture and design patterns
116+
- Test structure
117+
118+
## Testing
119+
120+
Comprehensive JUnit 5 test suite with AssertJ assertions in `src/test/kotlin/`.
121+
122+
**Test Organization:**
123+
- **Unit tests** - Run with `./gradlew test` (excludes integration tests)
124+
- **Integration tests** - Tagged with `@Tag("integration-test")`, run with `./gradlew integrationTest`
125+
126+
**Test Coverage:** 242 tests across 14 test classes
127+
128+
**Key test utilities:**
129+
- `MockSimulationContext` - Mock implementation
130+
- `TestContextBuilder` - Fluent builder for test contexts
131+
- `TestTrackBuilder` - Fluent builder for test track layouts
132+
- `TestFixtures` - Shared test data
133+
134+
### Tagging Integration Tests
135+
136+
```kotlin
137+
import org.junit.jupiter.api.Tag
138+
import org.junit.jupiter.api.Test
139+
140+
@Test
141+
@Tag("integration-test")
142+
fun myIntegrationTest() {
143+
// Test code
144+
}
145+
```
146+
147+
## Code Style
148+
149+
Follows `.editorconfig` configuration:
150+
- **Tabs for indentation** (width 4) - NOT spaces
151+
- Max line length: 120
152+
- UTF-8 encoding, LF line endings
153+
154+
### Kotlin Style
155+
156+
**Two-level approach** for Kotlin code quality:
157+
158+
1. **Legacy (Java→Kotlin converted)** - Permissive rules (`detekt.yml`)
159+
- Allows legacy patterns (var, complex methods)
160+
- Run with: `./gradlew detekt`
161+
162+
2. **New Kotlin code** - Strict rules (`detekt-strict.yml`)
163+
- Enforces modern Kotlin best practices
164+
- Place in: `src/main/kotlin/cz/vutbr/fit/interlockSim/new/`
165+
- Run with: `./gradlew detektStrict`
166+
167+
**Formatting:**
168+
```bash
169+
./gradlew ktlintCheck # Check formatting (respects .editorconfig tabs)
170+
./gradlew ktlintFormat # Auto-format (preserves tab indentation)
171+
```
172+
173+
**CRITICAL:** Both configurations use **tabs** (not spaces) to match original Java code style.
174+
175+
## Kotlin Migration Context
176+
177+
**Migrated from Java to Kotlin in January 2026** (100% of 94 files)
178+
179+
**Key Facts:**
180+
- Conservative structure-preserving conversion
181+
- 242/242 tests passing (236 pass, 5 skipped @Disabled, 1 property change test)
182+
- No unsolicited refactoring during migration
183+
- jDisco interop (Java 6) fully functional
184+
185+
See `KOTLIN-MIGRATION-STATUS.md` for details.
186+
187+
### Nullability Guidelines
188+
189+
**IMPORTANT:** The original Java code has been carefully tuned for null handling. Some Kotlin null-safety checks can introduce bugs if applied incorrectly.
190+
191+
**Type conversion rules:**
192+
- Java type `X` (no annotation) → Kotlin `X?` (nullable)
193+
- Java type `@NotNull X` → Kotlin `X` (non-nullable)
194+
- When in doubt, prefer nullable types (`X?`) for legacy converted code
195+
196+
**Null checks:**
197+
- The old Java code was designed with specific null-handling patterns
198+
- Adding Kotlin null-safety checks (like `requireNotNull()` or `!!`) can break existing logic
199+
- Use safe call operators (`?.`) and elvis operator (`?:`) instead of forcing non-nullability
200+
- Only use `!!` when absolutely certain the value cannot be null (with clear justification)
201+
202+
**Example:**
203+
```kotlin
204+
// GOOD - Preserves Java null behavior
205+
val track: Track? = getTrack()
206+
val length = track?.length ?: 0.0
207+
208+
// AVOID - May break existing logic
209+
val track: Track = getTrack()!! // Could crash if Java code expects null handling
210+
```
211+
212+
## XML Configuration
213+
214+
Railway networks defined in XML format:
215+
- Schema: `src/main/resources/cz/vutbr/fit/interlockSim/resource/data.xsd`
216+
- Example: `src/main/resources/cz/vutbr/fit/interlockSim/resource/vyhybna.xml`
217+
- Elements: RailSwitch, RailSemaphore, InOut (entry/exit points), track connections
218+
219+
## Logging
220+
221+
Uses SLF4J with Logback. Configuration: `src/main/resources/logback.xml`
222+
223+
**Log levels:** TRACE, DEBUG, INFO, WARN, ERROR
224+
225+
**Adding logging to code:**
226+
```kotlin
227+
import org.slf4j.LoggerFactory
228+
229+
private val logger = LoggerFactory.getLogger(ClassName::class.java)
230+
231+
// In methods:
232+
logger.debug("Debug message with context: {}", variable)
233+
logger.info("Informational message")
234+
logger.error("Error message", exception)
235+
```
236+
237+
## Docker Support
238+
239+
**Dockerfile** provides containerized build and runtime with X11 forwarding for GUI.
240+
241+
**Build:**
242+
```bash
243+
docker compose build app
244+
```
245+
246+
**Run editor:**
247+
```bash
248+
docker compose up app
249+
```
250+
251+
**Run simulation:**
252+
```bash
253+
docker compose run app java -ea -jar interlockSim.jar example shuntingLoop 60
254+
```
255+
256+
## Common Commands
257+
258+
**Build:**
259+
```bash
260+
./gradlew clean build # Full build with tests and JAR
261+
./gradlew shadowJar # Create uber JAR
262+
```
263+
264+
**Test:**
265+
```bash
266+
./gradlew test # Unit tests only
267+
./gradlew integrationTest # Integration tests
268+
./gradlew test integrationTest # All tests
269+
```
270+
271+
**Code Quality:**
272+
```bash
273+
./gradlew detekt # Check legacy Kotlin code
274+
./gradlew detektStrict # Check new Kotlin code (strict)
275+
./gradlew ktlintCheck # Check formatting
276+
./gradlew ktlintFormat # Auto-format
277+
./gradlew test jacocoTestReport # Generate coverage report
278+
```
279+
280+
**Run:**
281+
```bash
282+
./gradlew runEditor # Launch GUI editor
283+
./gradlew runSim # Run simulation
284+
./gradlew runExample -PexampleName=shuntingLoop -PendTime=300
285+
```
286+
287+
**Manual execution:**
288+
```bash
289+
java -ea -jar build/libs/interlockSim.jar sim [xmlFile] # Simulation mode
290+
java -ea -jar build/libs/interlockSim.jar edit [xmlFile] # Editor mode
291+
java -ea -jar build/libs/interlockSim.jar example [name] [time] # Examples
292+
```
293+
294+
**Note:** Always use `-ea` flag to enable assertions.
295+
296+
## Known Issues
297+
298+
### Critical
299+
None. All critical bugs have been fixed.
300+
301+
### Major
302+
- **DEFERRED-001:** Missing assertion predicates in XMLContextFactoryTest (9 occurrences)
303+
- Tests work correctly but lack explicit exception type predicates
304+
- SonarQube rule java:S5833
305+
306+
### Minor
307+
- **SIM-001:** Potential division by zero in Motor calculation (mitigated by guard)
308+
- **SIM-002:** Static train counter not reset between runs (cosmetic)
309+
- **DEFERRED-002:** Integer division precision loss in GUI rendering (3 occurrences)
310+
- **DEFERRED-003:** Doubleton missing equals() override (deprecated class)
311+
312+
### Design Limitations
313+
- **SIM-004:** Hardcoded grid coordinates in ShuntingLoop (works only with vyhybna.xml)
314+
- **SIM-005:** Negative train length allowed (no validation)
315+
- **SIM-006:** Assertion-only validation (always run with `-ea` flag)
316+
317+
See `CLAUDE.md` "Known Bugs and Issues" section for detailed information.
318+
319+
## CI/CD
320+
321+
GitHub Actions workflows in `.github/workflows/`:
322+
- `gradle-java21.yml` - Build, test, package JAR
323+
- `sonarqube.yml` - Code quality analysis
324+
- `claude.yml` - Claude AI integration
325+
- `claude-code-review.yml` - Automated code reviews
326+
327+
## Additional Resources
328+
329+
- **Comprehensive documentation:** See `CLAUDE.md` for detailed information
330+
- **Kotlin migration:** See `KOTLIN-MIGRATION-STATUS.md`
331+
- **Code style guide:** See `KOTLIN_STYLE_GUIDE.md`
332+
- **CI/CD workflows:** See `CICD_WORKFLOW_QUICK_START.md`
333+
334+
## Getting Help
335+
336+
When making changes:
337+
1. Read the relevant sections of `CLAUDE.md` for detailed context
338+
2. Ensure tests exist and pass before modifications
339+
3. Follow the conservative approach - minimal changes only
340+
4. Run tests and code quality checks before committing
341+
5. Always enable assertions with `-ea` flag when running the application
342+
343+
**Remember:** This is a working historical codebase. Stability and preservation are more important than modernization.

0 commit comments

Comments
 (0)