This document defines how coding agents should work in this repository.
docs/architecture.mdis the source of truth for system architecture and execution flow.docs/agent-analyzability.mdis the source of truth for import-graph layering, deep-module public entries, fan-out/file-size caps, and CI architecture checks.- Before changing parser/transpiler/runtime/CLI boundaries, read
docs/architecture.mdand keep changes aligned. - Before adding cross-package imports or new
src/modules, readdocs/agent-analyzability.mdand import only through public entry points, downward through layers. - Preserve the documented contracts:
- runtime -> CLI live events via
__JAIPH_EVENT__, - runtime -> durable artifacts via
.jaiph/runsandrun_summary.jsonl, - Jaiph runtime test lane (
*.test.jh) viajaiph test.
- runtime -> CLI live events via
- Preserve user-facing CLI behavior, especially
jaiph runoutput. - Prefer small, verifiable changes over broad rewrites.
- Keep tests readable and stable; treat them as product contracts.
- Run tests for every substantive change.
- Order of confidence:
- Colocated module tests in
src/**/*.test.tsfor pure logic. - Cross-cutting tests in
test/*.test.tsfor process/runtime behavior. - E2E shell tests in
e2e/tests/*.shfor CLI contracts and golden outputs.
- Colocated module tests in
- Before broad test runs, execute the most relevant targeted test(s) first.
- New module tests go next to the source file they test (e.g.
src/parse/core.test.ts). - Tests that span multiple modules or test process-level behavior go in
test/.
Useful commands:
npm run buildnode --test dist/src/**/*.test.js(colocated module tests)node --test dist/test/*.test.js(cross-cutting tests)bash e2e/test_all.sh- Single e2e script:
bash e2e/tests/<name>.sh
E2E tests are documentation. They must be easy for humans to read.
- Use clear sections and comments.
- Structure each scenario with explicit comments:
# Given# When# Then
- Keep setup local to the scenario; avoid hidden coupling.
- Prefer deterministic inputs and outputs.
For jaiph run output, assert the whole tree contract, not isolated fragments.
- Use
e2e::expect_stdoutwith a heredoc for full normalized output comparison. - Build an expected multiline output block and compare end-to-end.
e2e::assert_containsis allowed only when full equality is not feasible — every use must have an inline comment explaining why (nondeterministic output, absolute paths, platform-dependent text).- If output is dynamic (timings/colors), normalize first via
e2e::normalize_output. - Verify run artifacts independently with
e2e::expect_out/e2e::expect_run_file.
- TTY behavior is fragile and must be protected by acceptance/e2e coverage.
- Validate observable behavior, not implementation details:
- Running line appears.
- Timer updates over time.
- Final PASS/FAIL summary is present.
- Tree projection remains correct.
- Avoid overfitting tests to exact ANSI escape internals.
- Do not modify unrelated files.
- If you find unrelated failing tests, call them out explicitly.
- If updating behavior, update tests in the same change.
- Keep commits coherent: one logical intent per change.
- Keep code and tests readable for humans.
- Prefer existing helpers in
e2e/lib/common.shover custom assertion logic. - Avoid large custom test harnesses unless existing tools cannot solve the problem.
- When introducing nontrivial logic, add concise comments explaining intent.