7e1f1483a4
- Document exception handling, zero-value BotResult trap, shared adversary bots - Add offline parsing example using parseServerOutput - Skip tests gracefully when JARs missing (guard before suite blocks) - Fix blocking readLine in runner_process.nim: poll with 50ms sleep + atEnd check (was preventing timeout enforcement, now blocks correctly during battle) - Add test task to QBot.nimble and config.nims setup docs to AGENTS.md - Add debug logging to TestBattleRunner for bot identity tracking Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
123 lines
3.1 KiB
Markdown
123 lines
3.1 KiB
Markdown
## Agent skills
|
|
|
|
### Issue tracker
|
|
|
|
Gitea Issues at git.fossellini.top:SirStone/SirRoboGarage. See `docs/agents/issue-tracker.md`.
|
|
|
|
### Triage labels
|
|
|
|
Default label vocabulary. See `docs/agents/triage-labels.md`.
|
|
|
|
### Domain docs
|
|
|
|
Single-context layout. See `docs/agents/domain.md`.
|
|
|
|
### Folders
|
|
|
|
## SirGarage Directory Layout
|
|
|
|
**SirGarage** (root directory)
|
|
|
|
- `botname_garage/` — each bot gets its own directory following this pattern
|
|
- src/
|
|
- botname.nim
|
|
- botname.json
|
|
- botname.sh
|
|
- config.nim
|
|
- botname/ — bot-specific modules
|
|
- *.nim files
|
|
- tests/
|
|
- test*.nim files
|
|
- out/
|
|
- compiled binaries
|
|
- prototypes or spikes for this bot (not at root)
|
|
- docs/ — generic project documentation
|
|
- tools/ — generic tools valid for all bots (battle runners, scripts, etc.)
|
|
- common_libs/ — shared libraries valid for all bots
|
|
- worktrees/ — git worktrees (gitignored)
|
|
- AGENTS.md
|
|
- CONTEXT.md
|
|
- README.md
|
|
- .gitignore
|
|
|
|
## How to use
|
|
|
|
- These indications are for files that are always present, for files not mentioned here should be claer from context where belongs too.
|
|
- Each bot development must be done in each folder in isolation.
|
|
- If the bot requires extra folders during runtime, these must be created by the bot itself if not present already.
|
|
|
|
### NIM
|
|
|
|
This repsoitory's main language is Nim, when you need to work with nim use the /nim mcp.
|
|
|
|
---
|
|
|
|
## Writing tests for a bot
|
|
|
|
Framework lives at `common_libs/test_framework/`. Full docs: `common_libs/test_framework/README.md`.
|
|
|
|
### One-liner
|
|
|
|
```nim
|
|
import test_framework/test_framework
|
|
|
|
let r = runBattle(@[myBotDir, adversaryDir], rounds = 10)
|
|
```
|
|
|
|
`runBattle` blocks, returns `BattleResult`, raises on failure.
|
|
|
|
### Types
|
|
|
|
```
|
|
BattleResult → bots, rounds: seq[RoundResult], results: seq[BotResult], winners: seq[string]
|
|
BotResult → name, totalScore, rank, firstPlaces, survivalCount
|
|
RoundResult → round, results: seq[BotRoundResult]
|
|
BotRoundResult→ name, score, rank, survived
|
|
```
|
|
|
|
### Shared adversaries
|
|
|
|
```nim
|
|
const tfAdversaries = currentSourcePath().parentDir.parentDir.parentDir /
|
|
"common_libs" / "test_framework" / "adversaries"
|
|
const sittingDuck = tfAdversaries / "SittingDuck" # passive — does nothing
|
|
const oscillator = tfAdversaries / "OscillatorBot" # fights back
|
|
```
|
|
|
|
### Setup (once per garage)
|
|
|
|
**`tests/config.nims`**
|
|
```nim
|
|
--path:"../../common_libs" # adjust depth to match garage location in repo
|
|
```
|
|
|
|
**`YourBot.nimble`** test task:
|
|
```nim
|
|
task test, "Run integration tests":
|
|
exec "nim c -r --path:../common_libs tests/test_basic_battle.nim"
|
|
```
|
|
|
|
### Skip when JARs are absent (put before any suite block)
|
|
|
|
```nim
|
|
import std/os
|
|
if not existsEnv("TR_SERVER_JAR") or not existsEnv("TR_BATTLE_RUNNER"):
|
|
echo "Skipping: TR_SERVER_JAR / TR_BATTLE_RUNNER not set"
|
|
quit(0)
|
|
```
|
|
|
|
### Offline parsing (no Java needed)
|
|
|
|
```nim
|
|
import test_framework/battle_result
|
|
let r = parseServerOutput(rawJsonLines)
|
|
```
|
|
|
|
### Exceptions
|
|
|
|
| Exception | Cause |
|
|
|---|---|
|
|
| `OSError` | Bot compilation failed |
|
|
| `IOError` | Battle runner exited non-zero |
|
|
| `TimeoutError` | Server startup (15s), compile (30s/bot), or battle runner timeout |
|