Durable, file-backed execution state for coding agents.
Project description
Context Compass
Working memory for coding agents, stored in your repo instead of a chat window.
cd my-repo
uvx contextcompass init
That writes a context_compass/ directory into your project. Point an agent at
context_compass/AGENTS.MD and its tickets, decisions, evidence and handoff state
live in files you own — surviving compaction, new chats, model swaps, and the next
agent.
Why It Exists
Agent work falls apart the second the chat stops being fresh. The context gets long, compaction happens, the model forgets half the reasoning, another agent takes over, or you switch from GPT to Claude to Gemini — and suddenly the work has no memory of why it looks the way it looks.
The failures are boring and repetitive:
- the agent forgot what it was doing
- the next chat lost the reasoning
- the important decisions stayed in chat instead of in the project
- compaction wiped the context
- a new agent took over with no reliable handoff
- the platform kept the task state, but you wanted to keep the task state
Context Compass moves the working memory into the repo. Not a prompt pack, not a documentation template — a persistence and control layer: an onboarding contract, role maps with routed skill chains, ticket-first execution, durable notes and evidence, artifact tracking, mailbox handoffs, and re-entry rules after compaction.
The point is simple. Chat memory is weak, repository state is durable, and process should be recoverable from files rather than vibes.
Install
Three ways in. They produce the same context_compass/ directory in your
repo — pick whichever fits how you work.
1. uvx — nothing installed, nothing cloned (recommended)
cd my-repo
uvx contextcompass init
uvx fetches the package into a throwaway environment, runs it, and discards it.
Nothing lands in your project's dependency tree, because a repo-scaffolding tool
has no business there.
Pin a version for reproducibility, or track the latest:
uvx contextcompass@2.15.1 init # exact, repeatable
uvx contextcompass@latest init # whatever is newest
Don't have uv yet?
# macOS and Linux
curl -LsSf https://astral.sh/uv/install.sh | sh
wget -qO- https://astral.sh/uv/install.sh | sh # if you have no curl
# Windows
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
uv also installs Python itself, which is the other reason to have it:
uv python install 3.14 # or 3.12, 3.13 - whichever you want
uv python install 3.14t # the `t` suffix is the free-threaded build
uv venv --python 3.14 # creates .venv using that interpreter
2. pip / pipx — if you would rather not use uv
pipx install contextcompass && contextcompass init # isolated, preferred
pip install --user contextcompass && contextcompass init
3. Clone — no Python needed at all
The package is Markdown. If all you want is the system, copy the folder:
git clone https://github.com/Synaptic724/contextcompass
cp -r contextcompass/src/context_compass my-repo/
# Windows
git clone https://github.com/Synaptic724/contextcompass
Copy-Item -Recurse contextcompass\src\context_compass my-repo\
Clone when you want to read the source first, work offline, vendor a specific commit, or modify the package before adopting it.
What actually needs Python
Only tools/ — the scripts that build the manifest, index documents, generate the
source graph, and upgrade an install. Python 3.10+, stdlib only, no dependencies
ever. An agent that has to pip install before it can read a document is an
agent that cannot read the document on a fresh clone.
Tested on 3.10 through 3.14 (including free-threaded 3.14t) on Linux and Windows, on every push. Verify an install any time:
python context_compass/tools/package_manifest.py --root context_compass --check
Quickstart
- Point your agent at
context_compass/AGENTS.MDand ask it to onboard as anengineer. - Approve the certification step it asks for:
CERTIFY: APPROVED. - Work normally. The agent routes through
attention_board.mdand the active ticket, and writes findings into ticket## Notes. - Commit
context_compass/. It is your repository's memory now, and it is meant to be reviewed and diffed like any other source. - After every compaction or handoff, tell the next agent to re-onboard. That is the whole trick — it rebuilds context from the repo instead of guessing from a half-remembered chat.
Core Features
1) Compaction durability
Compaction is treated as a reliability event, not a convenience step. Action after
it is blocked until re-onboarding completes: the agent re-reads the policy
anchors, re-resolves its role chain, reopens the board and active tickets, and
posts a REONBOARD: COMPLETE attestation carrying read-integrity proof before it
may touch anything.
2) Certification gate
Nothing executes on trust. Before tools or edits, the agent posts what it read and
what each document changes about its behavior, then waits for a message containing
AGENT_NAME: <name> and the exact token CERTIFY: APPROVED. Proof is a
comprehension claim, not a tool log — "I ran cat" is not evidence of reading.
3) Evidence and the Unknowns Gate
UNKNOWN is the default state for every claim. Promotion to FACT requires an
evidence pointer (path:start_line-end_line). Inferring behavior from a class
name, a folder layout, or what a framework usually does is explicitly rejected as
proof. Documents are evidence of intent; only source is evidence of behavior.
4) Ticket microcycle
A strict loop: investigate → document → plan → document → implement → document → validate → document. No second investigation tranche before the current finding is written down. Notes are not side output; they are the execution memory that makes compaction survivable.
5) Three read states
Every section of a role's skill map is exactly one of these, and the section heading declares which:
| state | required to certify? | when it is read |
|---|---|---|
| baseline | yes | at onboarding, every time |
| On-demand | no | only when the section's stated trigger fires |
| Self-directed | no | at the agent's initiative — no trigger, no permission |
The third state exists because collapsing it into On-demand produces a specific failure: an agent finds no trigger has fired, reads none of the system documents, and reasons from class names instead — with sound-looking justification. Waiting for permission to read is not caution.
6) The understanding hierarchy
Large system documents are entered through indexes and sliced, never read whole. Each level hands you the key the next is looked up by:
src_architecture.md WHICH PART - read whole, at onboarding
v
src_components_index.md WHICH COMPONENT - look up that name
v
src_components.md (slice) WHAT it owns, its Key Files
v
src_graph_index.md WHICH NODES
v
src_graph.md (slice) HOW it wires - ownership, lifecycle, callers
v
THE CODE the only authoritative account
Enter at the graph with no name in hand and you are searching tens of thousands of lines for something you cannot describe. Descend it instead.
7) Role overlays and inheritance
Roles are delta layers, not separate systems. A role names its parent with
INHERITS_SKILLS_FROM, the chain is read parent-first, and a custom role extends
engineer or general without forking core behavior.
8) Mailbox handoffs
Not every handoff should be broadcast. mailbox_board.md carries point-to-point
messages between named agents — handoff, notice, question, ack — so directed
communication does not turn the routing board into noise.
Roles
SKILLS.MD is the single role registry. A role exists if and only if it has a
row in that table; adding one is two steps — add the row, create the SKILLS.MD
it points to.
Shared foundation
| role | extends | what it is |
|---|---|---|
general |
— | process, ticketing, evidence discipline, compaction contract |
new |
— | first-time onboarding only; never a steady-state role |
Software roles
| role | extends | choose it for |
|---|---|---|
engineer |
general |
most coding: debugging, refactors, repo changes |
design_engineer |
engineer |
architecture plans, component boundaries, ADRs |
platform_engineer |
engineer |
CI/CD, deployment, observability, production safety |
qa_engineer |
engineer |
test strategy, quality gates, release signoff |
security_engineer |
engineer |
threat modeling, security review, hardening |
Fiction and editorial roles
| role | extends | choose it for |
|---|---|---|
story_designer |
general |
premise, arcs, chapter purpose, story bibles |
story_novel_artist |
general |
style systems, scene art briefs, cover direction |
researcher |
general |
source-backed constraints, confidence labels |
draft_writer |
general |
chapter-complete prose under architecture constraints |
developmental_editor |
general |
pacing, stakes, arc diagnosis, rewrite planning |
line_copy_editor |
general |
clarity, style consistency, mechanical correctness |
continuity_fact_checker |
general |
canon, timeline, contradiction detection |
proofreader |
general |
final typo, punctuation and format lock |
User-defined overlays
Live under agent_onboarding/user_defined/ and are never touched by an
upgrade. The package ships three as working examples —
synaptic_python_developer, synaptic_finishing_developer, and data_engineer,
all extending engineer.
A directory there is not a role until it has a registry row. That is deliberate: a folder on disk with no row is scaffolding, not a selectable role.
How A Session Actually Runs
Onboard. The agent reads AGENTS.MD, then the execution contract, the config,
and SKILLS.MD. It lists the roles and asks which to take. It walks the chain
parent-first and reads every baseline section — for engineer that is its own
required skills, the parent's active skills, and the system-orientation set
(src_architecture.md plus the architecture and component indexes).
Certify. It posts what it read and what each document changes about its
behavior. You reply with AGENT_NAME: helper_1 and CERTIFY: APPROVED.
Route. It opens attention_board.md and picks up the active row:
| work_item | status | mode | owner | agent_name | blocker | next | ... | ticket |
| parser_retry_fix | in_progress | implementation | claude | helper_1 | none |
finish the backoff branch | ... | tickets/tasks/2026-08-01_parser_retry_task.md |
Work the microcycle. It opens the linked ticket, investigates until it has one
meaningful finding, and writes it to ## Notes before continuing:
DATETIME: 2026-08-01T14:22:10Z
TYPE: FACT
CLAIM: retry backoff is computed but never applied on the 429 path
EVIDENCE: src/client/retry.py:88-104
IMPACT: every 429 retries immediately; the ceiling is never reached
NEXT: apply the computed delay before the recursive call
REREAD: REQUIRED
SCORE_0_TO_10: 8
Close. The ticket moves to tickets/tasks/completed/, the board row is
updated in the same pass, and an anchor row records where it went.
Re-enter. After compaction the next agent re-onboards, reopens the board and that ticket, reads the notes, and continues — from evidence, not from memory.
The Boards
Three files, each with one job. All three carry USER-DEFINED regions that no
tool writes to in any mode, so your rows survive upgrades while the surrounding
structure improves.
attention_board.md — routing only. What is active, who owns it, what mode it
is in, what comes next, and which ticket holds the detail. Not for narrative, not
for analysis, not for artifact paths. Durable history belongs in ticket notes.
artifact_board.md — artifact associations by ticket, with disposition:
delete_on_close, retain_as_reference, or promote_to_documentation.
mailbox_board.md — point-to-point messages plus a checked-in roster, so
concurrent agents can see who is live and hand work to a named recipient.
Repository Anatomy
context_compass/
AGENTS.MD entrypoint - onboarding and execution policy
SKILLS.MD the single role registry
CONTEXT_COMPACTION.md compaction and handoff contract
config/ behaviour settings (never a role list)
attention_board.md routing
artifact_board.md artifact lifecycle
mailbox_board.md agent-to-agent messages
agent_onboarding/
default/ the shipped roles
user_defined/ YOURS - never touched by upgrade
tickets/epics|stories|tasks/ work, each with backlog/ and completed/
templates/ ticket and workflow templates
artifacts/ ticket-linked supporting files
context_management/ optional reusable reread packs
system_docs/ SHIPS EMPTY - your architecture maps
special_instructions/ project-specific rules
user_defined/ free space, never written to
examples/ the quality bar - read these, don't edit them
tools/ stdlib-only Python
Five directories are yours outright and an upgrade never touches them:
system_docs/, tickets/, artifacts/, special_instructions/, and both
user_defined/ trees.
system_docs/ ships empty on purpose. A seeded placeholder in a live lane gets
read as repository truth no matter what banner sits on it, so the package does not
put one there. Build the maps when your repo has real structure to describe;
system_docs/system_docs_read_first.md explains the order.
Configuration
config/context_compass_config.yaml holds behaviour settings only. It never
enumerates roles and is never consulted to resolve one — that is SKILLS.MD's job
alone. Notable keys:
| key | effect |
|---|---|
system_of_record.enforce |
when true, agents may not use harness task lists, plans or session memory to track work. This package is the only tracking surface. |
workflow.ticket_microcycle.* |
strict or relaxed loop, note score floor, expansion gate |
workflow.note_behavior.* |
append-only notes, required evidence ranges, per-ticket focus |
artifacts.* |
store root, disposition defaults, ticket-link requirements |
reading.read_loc_max |
chunk size for manual reads of large documents |
Config is merged key by key on upgrade. New keys arrive with their comments; a value you set is never reset.
Upgrading An Existing Install
uvx contextcompass@latest upgrade --check # exactly what would change
uvx contextcompass@latest upgrade --apply # do it
Every tool refuses to act without --apply and prints a full plan under --check.
Read the plan.
How it decides what is safe to replace
One hash tells you a file changed. It cannot tell you who changed it, which is the only question that matters. So three are compared — what shipped, what is on disk, and what is incoming:
| on disk | incoming | what happens |
|---|---|---|
| unchanged | changed | replace — clean update |
| unchanged | unchanged | skip |
| you edited it | unchanged | keep yours — nothing to conform to |
| you edited it | changed | conform, and say so by name |
Boards keep your rows
Everything inside a USER-DEFINED region is yours; everything outside is package
structure that gets conformed, so a board's shape can improve over time.
Boards created before those regions existed hold their rows in open text, where nothing distinguishes them from stale package headings. The updater refuses to conform such a board and names the fix:
uvx contextcompass@latest migrate-boards --check --diff
uvx contextcompass@latest migrate-boards --apply
Anything with no matching region is parked under ## Notes rather than dropped.
Migrating three real boards carrying 277 lines of live agent state moved every line
and lost zero, verified line-by-line against a pre-migration snapshot.
The tools
All under context_compass/tools/, all stdlib-only, all --check before --apply.
| tool | what it does |
|---|---|
package_manifest.py |
what ships, who owns it, its hash. Everything else reads this. |
update_context_compass.py |
upgrade an install to a newer package |
migrate_boards.py |
one-time board migration into USER-DEFINED regions |
cleanup_context_compass.py |
repair a broken install, or reset lanes for a release |
build_llm_full.py |
concatenate the package into one file, plus a line-range index |
system_documents/index_document.py |
line-range index over an authored document |
system_documents/python/extract_graph.py |
derive the source graph from code |
system_documents/python/assemble_graph.py |
render the graph and its index |
system_documents/python/graph_walker.py |
state of the graph's authored tier |
system_documents/python/graph_semantics_tickets.py |
turn unauthored areas into tickets |
system_documents/python/migrate_authored_graph.py |
carry a graph out of the retired JSON format |
Feed The Whole System To A Model
Sometimes you want a model to see everything at once — reviewing a change to the onboarding contract, working out why two policies disagree, handing the system to something that cannot browse a filesystem.
python context_compass/tools/build_llm_full.py \
--root context_compass --out llm_full.md --slice context_compass/AGENTS.MD
That writes llm_full.md (every file concatenated, ~30,000 lines) and
llm_full_index.md (483 lines saying which lines each file occupies).
Read the index, slice what you need, never load the document whole. The index
carries line_count and content_sha256, and --slice recomputes both before
returning anything, so a hand-edited document makes the next slice refuse rather
than confidently hand back the wrong file.
Design Notes
The package installs into repositories that agents actively write to, so the tooling is built around not destroying that work.
- Ownership classes. Every shipped file is PACKAGE, RESET, INSTANCE, LIVE or
CONFIG, recorded with its hash in a generated
MANIFEST.md— derived from the files themselves, so it cannot drift the way a hand-bumped stamp does. - Nothing deletes authored work automatically. Every tool that can remove
something refuses without
--apply, and the one that deletes authored prose refuses without a terminal to ask at. - Line-range indexes carry staleness proofs, and every consumer refuses on mismatch rather than returning confidently wrong content.
- 419 tests, plus mutation testing. A green suite is equally consistent with
"the code is correct" and "the tests assert nothing", so
tests/mutation_check.pyapplies 49 deliberate defects and requires at least one test to fail for each. Several survived their first run; each named a real gap.
uv sync && uv run pytest # the suite
uv run python tests/mutation_check.py # prove the suite has teeth
The source graph is honest about what it cannot know
Context Compass can derive a source graph from your code — one node per class and module, with the relationships between them. Half of it derives cleanly. The other half cannot:
self._pool = pool # borrows
self._pool = pool # uses
self._pool = pool # owns_lifecycle_of
Three different relationships, identical syntax. That difference is design intent
appearing nowhere in the source text — measured against a hand-authored graph,
68% of all edges. So the graph has an authored tier, and nodes without one are
marked UNSEMANTIC rather than guessed at.
Authored prose is also the tier that rots: the mechanical half self-heals on
re-extraction, while prose stays exactly as written while the code moves under it.
A read-only walker reports each node as UNSEMANTIC, AUTHORED,
SEMANTICS_STALE, or RETIRED — tracked per node, because a file-level hash
would mark all forty classes in a module stale because one changed, and a census
that cries wolf gets ignored.
Common Failure Modes This Prevents
- "The agent started coding before onboarding."
- "It claimed it read the docs but could not say what changed about its behavior."
- "Critical decisions vanished after compaction."
- "The new chat had no reliable re-entry path."
- "Two agents did the same work because neither could see the other's state."
- "Role responsibilities blurred and the quality gates quietly disappeared."
Practical Adoption
- Start with
general+engineer. - Enforce board and ticket routing first.
- Then evidence and unknowns discipline.
- Then certification and compaction re-entry gates.
- Add specialized roles as the workflow matures.
- Add user-defined overlays once baseline behavior is stable.
This sequence keeps adoption fast without weakening the core controls.
Final Word
You own the state. You can review it, diff it, commit it, hand it to another agent, and come back in three months and still know what happened.
If you want project memory that stays with the repo, survives branch work, handles handoffs, resists drift, and still makes sense when another agent shows up later — that is exactly what this system is for.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file contextcompass-2.15.1.tar.gz.
File metadata
- Download URL: contextcompass-2.15.1.tar.gz
- Upload date:
- Size: 433.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8700c7a7812244e42e17d8699614bac6b1a1442d3d340b4d93f2ba0276db607d
|
|
| MD5 |
147bd7649138565ec447579fe5b2a714
|
|
| BLAKE2b-256 |
08ff466214906c10f11af67b6c9d84d00f0cb29931cf59b9407df9980c7d45e1
|
File details
Details for the file contextcompass-2.15.1-py3-none-any.whl.
File metadata
- Download URL: contextcompass-2.15.1-py3-none-any.whl
- Upload date:
- Size: 660.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
869ca62b6d7a1bf380e99689a4ee8a8a0e428f812e518c627d87ca8b2f01f546
|
|
| MD5 |
8bcd9ba1f28f61d22242a1cf99a79c64
|
|
| BLAKE2b-256 |
d0e6ddbaddd31da6945571c0a65e15bca99f772a9481611d8990eeefab795a80
|