Development
Changing a dependency breaks three environments
This is the single most common way to break a working checkout, and nothing detects it automatically — the failure surfaces as a precompilation error the next time you run tryit:
ERROR: Package TryIt does not have TOML in its dependenciesThree environments each carry their own Manifest.toml, and none of them is updated by pulling a commit that changes dependencies:
| Environment | What breaks when it goes stale |
|---|---|
. | Pkg.test() |
docs | docs/make.jl |
test | Running the test env directly. Pkg.test() resolves a fresh sandbox, so this hides until you use --project=test |
@TryIt | tryit itself — the shell function runs against it |
Moving the repository breaks all four at once. A develop install records an absolute path, so relocating the checkout leaves every manifest pointing at a directory that no longer exists. The same script fixes it — it re-runs Pkg.develop against the current location before resolving.
@TryIt is the one that bites, because it breaks the tool rather than the build, and it is the one a contributor is least likely to think of.
After adding, removing or bumping any dependency:
./bin/resolve-envs.shThat resolves all three and reports which failed. Doing it by hand means three separate Pkg.resolve() invocations, and forgetting the third leaves tryit broken while every test passes.
Gates
Everything below runs in CI; run it locally before pushing.
julia --startup-file=no --project=. -e 'using Pkg; Pkg.test()'
julia --startup-file=no --project=docs docs/make.jl
julia --startup-file=no -e 'using Pkg; Pkg.activate(temp=true);
Pkg.add("JuliaFormatter"); using JuliaFormatter; format(".")'Check the exit status, not the output. A pipeline like … | tail -5 or a trailing && echo ok will report success for a command that failed — that has already produced two false "passing" readings in this project's history, once masking a build error and once masking a docs failure.
Guards worth knowing about
Three tests exist to catch drift rather than defects, and each has caught something real:
test/spec/test_traceability.jl— every requirement ID inspec.mdmust appear insrc/ortest/, or carry a written exemption. It found twelve capabilities that had been built with no written requirement.test/spec/test_docs_sync.jl— every documentedCtrl+Xmust be a key the selector handles and must appear in the?overlay; the documented default tries root must match the code.test/docs/test_embedded_docs.jl— the manual embedded for the in-app browser must matchdocs/src. It caught the embedding going stale because Julia does not invalidate a precompiled image for a file that is merelyread;include_dependencyfixed it.
When one of these fails, the fix is usually the documentation or the spec, not the test.
Two globals that leak between tests
Both are correct in production and wrong under a test runner, which shares one process across test items:
_APP_MODE— aRefthat_app_mainsets and never clears. An app process only ever runs as an app, so nothing resets it; but one test item leaving ittruemakesemit_shell_initemit the compiled-app form in a later item, pointing at a binary that does not exist. Pin and restore it around anything that renders the shell snippet.ENV—withenvmutates the process-global environment. With test items running concurrently, one item's cleanup can clear another's override. Anything that writes (config, files) must take its path as an argument rather than reading it fromENV.
Spawning julia from a test
Pkg.test sets JULIA_LOAD_PATH for its sandbox, and any julia a test spawns inherits it — leaving the child unable to resolve the package's own dependencies, with an error that looks like a missing dependency rather than an inherited one. Clear it:
withenv("JULIA_LOAD_PATH" => nothing, "JULIA_PROJECT" => nothing) do
run(...)
endAdding a key binding
The selector owns its whole key map (default_bindings=false), so a new binding needs four things, and the guards enforce the last two:
- A branch in
Tachikoma.update!insrc/selector.jl. - A mapping in
press_keys!intest/tachikoma_helpers.jl— without it the keystroke silently lands in the filter and the test passes for the wrong reason. - A row in
HELP_KEYS, which is the?overlay. - A row in the key-binding table in
docs/src/interface.md.