Schema is provisional. Spikes are expected to surface friction with this format. If a convention does not work for your approach, document why in your spike writeup. The schema will be revised before the integration phase.
Each question is a folder under questions/ named by its question ID.
questions/<question-id>/
index.md — frontmatter metadata + markdown problem statement
starter.<ext> — starter code shown to the student
solution.<ext> — reference solution; must pass the test file
tests.<ext> — test suite executed against the student's submission
<ext> is .py for Python and .java for Java.
---
id: string # matches the folder name exactly
title: string # display title shown to the student
type: code # literal string "code"
language: python | java
tags: [string, ...] # topic tags, e.g. ["recursion", "strings"]
entry_point: string # the function or class name the student implements
---The markdown body of index.md is the problem statement shown to the student. Write it as you would a problem description on an assignment sheet.
Starter code shown to the student in the editor. Should include:
- Any required imports
- The function or class signature matching
entry_point - A
TODOcomment body orpass/stub return
The student replaces the stub with their implementation.
The reference solution. Must pass tests.<ext> without modification. Not shown to the student.
The test file executed by the spike runner against the student's submission.
Python. The test file imports the submission as solution and calls solution.<entry_point>:
import solution
result = solution.add(1, 2)The submission file is always named solution.py at runtime, regardless of what the student originally named it.
Java. The test file references the student's class directly by the entry_point name. The submission class must be in the same package (default package) as the test file.
The runner executes the test file and determines pass/fail from two signals:
- Exit code.
0= all tests passed. Non-zero = at least one failure or a runtime error. - Structured stdout. The test file must print a single JSON line to stdout as its last line of output:
{"passed": 3, "failed": 1, "failures": [{"test": "test_name", "message": "expected X got Y"}]}Both signals are expected. A runner that only checks exit code is incomplete. A runner that only checks stdout is also incomplete — use both.
Spike authors: if this output protocol is impractical for your execution environment, document the specific friction and propose an alternative in your writeup.
A trivial Python question to illustrate all four files.
---
id: add-two-numbers
title: Add Two Numbers
type: code
language: python
tags: ["arithmetic", "functions"]
entry_point: add
---
Implement a function `add(a, b)` that returns the sum of two integers `a` and `b`.
**Example**
- `add(1, 2)` → `3`
- `add(-1, 5)` → `4`
- `add(0, 0)` → `0`def add(a: int, b: int) -> int:
# TODO: implement this function
passdef add(a: int, b: int) -> int:
return a + bThe harness is hand-rolled rather than using unittest or pytest so that the output protocol is explicit and not dependent on a test framework's output format. Spike authors can replace it once they know what their runner can parse.
import json
import solution
results = {"passed": 0, "failed": 0, "failures": []}
def run(name, got, expected):
if got == expected:
results["passed"] += 1
else:
results["failed"] += 1
results["failures"].append({
"test": name,
"message": f"expected {expected} got {got}",
})
run("test_positive", solution.add(1, 2), 3)
run("test_negative", solution.add(-1, 5), 4)
run("test_zeros", solution.add(0, 0), 0)
run("test_large", solution.add(100, 200), 300)
print(json.dumps(results))
exit(results["failed"])