Skip to content
JairogelpiPublic

About

Executable intent contracts for coding agents. Detect and block silent intent drift in Claude Code, Codex and other coding agents.

Topics

Resources

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

Northstar

CI Coverage gate Scripted silent drift Python License

The deterministic intent-fidelity layer for coding agents.

Compaction remembers. Northstar verifies.

You ask an agent to “refactor authentication, but do not change the public API.” Fifty steps later the API changed, the tests were edited to agree, and every local decision looked reasonable. Northstar freezes the non-negotiable parts of the request at step zero and checks the complete repository against that baseline after every action.

It is not another prompt file, an LLM judge, or a command deny-list. The judge is a deterministic process outside the agent conversation. It compares hashes, ASTs, dependencies, module edges and optional test outcomes against a sealed authority.

Northstar demo: a protected edit and public API drift are denied before a scoped approval

Try it in 60 seconds

Python 3.11+ is required. Until the first 0.2.x PyPI release is published, install the reviewed source directly from GitHub:

pipx install "git+https://github.com/Jairogelpi/northstar.git"
# or: uv tool install "git+https://github.com/Jairogelpi/northstar.git"

northstar demo

The demo creates a disposable project, blocks a protected test edit, catches a public signature change, exercises a scoped approval and deletes the project. It does not modify the current directory.

To govern a real repository, preview the exact contract before anything is written:

cd /path/to/project
northstar init "refactor authentication" --dry-run
northstar init "refactor authentication"
northstar doctor

init creates a human approval passphrase, freezes the baseline, stores the canonical authority outside the working tree, writes reviewable mirrors, and wires Claude Code and Codex. The objective is not silently interpreted as policy: the default profile is shown explicitly. For task-derived constraints, use a reviewed task file:

northstar init --from-task TASK.md --dry-run
northstar init --from-task TASK.md

If a sentence cannot be compiled deterministically, init stops and prints NOT COMPILED; after manual review, --accept-uncompiled records that conscious decision. See the five-minute quickstart for agent trust, approvals, diagnosis and clean uninstall.

The core idea

Northstar turns intent drift into a versioned state comparison:

  1. Freeze at t=0. Capture the public API, runtime dependencies, module graph, protected files and optional behavioural witness while the request is fresh.
  2. Check state, not edits. Compare the whole tree with the original baseline. A sequence of individually plausible edits cannot launder a violation.
  3. Keep authority outside the tree. Seal canonical state and mirror digests with HMAC; authenticate human amendments with an encrypted Ed25519 key.
  4. Widen only by grant. The agent may request an exception, but only a human in a separate interactive terminal can approve the named grant.
flowchart TD
    A["Human task"] --> B["Frozen contract + baseline"]
    B --> C["Agent action"]
    C --> D["Whole-tree deterministic check"]
    D -->|on course| C
    D -->|drift| E["Deny or require approval"]
    E -->|scoped human grant| C
Loading

The working copy contains readable mirrors; the operating-system data directory holds the canonical bundle. Missing authority, mirror mismatch, corrupt signatures or broken hook wiring is an INTEGRITY_FAILURE, never a silent pass.

What makes it different

Approach Survives context compaction Checks cumulative tree state Deterministic verdict External sealed authority Scoped signed exceptions
Prompt / AGENTS.md instructions No No No No No
Context summaries and memory Partly No No No No
Command or tool-call firewall Yes No Usually No Sometimes
LLM reviewer / semantic judge Partly Sometimes No No Sometimes
Northstar Yes Yes Yes Yes Yes

This is a category comparison, not a claim that Northstar replaces every layer. Instructions tell an agent what to do; sandboxes limit capability; tests verify behaviour; Northstar preserves the task's declared invariants across the trajectory. The detailed product boundary is in positioning.

A small, reviewable contract

The contract is a deny-list, not a full specification. Anything it does not name is free to change.

objective: refactor authentication

constraints:
  protected_paths: ["tests/**"]
  public_api:
    change: forbidden
    additions: allowed
    scope: ["**/*.py"]
  dependencies:
    additions: forbidden
  module_graph:
    new_edges: allowed
  behavior:
    change: allowed
  commands:
    forbidden: ["git push*", "rm -rf*"]
  tools:
    unknown: approval_required
    read_only: []
    mutating: []

For behavioural compatibility, northstar init --behavior freezes the existing test outcomes as an executable witness. It records behaviour that exists—including current failures—not behaviour somebody hoped for.

Verdicts are explicit: ALLOW, WARN_DRIFT, UNKNOWN, REQUIRE_APPROVAL and DENY. Unsupported or unparseable input becomes UNKNOWN; Northstar does not report coverage it cannot prove.

Everyday workflow

northstar status                 # objective + current verdict after any handoff
northstar check                  # deterministic full-tree check
northstar request --grant public_api:src/auth.py::login --reason "tenant agreed"
# human in another interactive terminal:
northstar approve REQUEST_ID
northstar receipt                # contract, decisions and amendment chain
northstar doctor --strict        # runtime, authority, mirrors, hooks and activity
northstar uninstall --agent all  # authenticated removal; preserves foreign settings

Claude Code is wired through PreToolUse and PostToolUse. Codex uses project hooks plus AGENTS.md; a human must inspect and trust those hooks through /hooks before relying on them. Post-state checks remain the backstop because no tool parser is a complete security boundary.

See it block a real agent

These are not staged screenshots. Each GIF is a real terminal session, generated from commands actually run against a disposable test project in this repo's own CI-style setup -- the exact input and output, only the typing speed is simulated for readability.

A protected-path edit, denied before it lands. tests/** is frozen at init. An agent (or a raw PreToolUse hook call, shown here) trying to edit a protected test gets a structured DENY and a non-zero exit -- Claude Code reads exit code 2 from a hook as "block this tool call."

Northstar denies an edit to a protected test file

A public API change, caught after the edit -- not trusted on the agent's word. The pre-check on src/auth.py allowed the edit (it isn't a protected path); only check/PostToolUse, comparing the real AST against the frozen baseline, catches that login()'s signature actually changed.

Northstar detects a public API signature change after the edit

Tampering with the local mirror does not work. .northstar/ is a readable mirror, not the runtime authority. Editing contract.yaml by hand to "allow" what was just denied doesn't fool check -- it fails closed with INTEGRITY_FAILURE, and doctor reports the project BROKEN until a human repairs it.

Northstar detects a tampered contract mirror as an integrity failure

The regression evidence table is generated, not typed into this README. northstar bench re-runs IntentDriftBench and prints exactly this table -- the numbers in Evidence, with claim boundaries below come from this command, not from hand-edited markdown.

Northstar bench prints the regression table live

Command reference

Every command Northstar ships, what it does, and when you'd reach for it. -h/--help on any of them prints the same flags shown here, straight from argparse -- nothing in this table is aspirational or unimplemented.

Command What it does Typical use
northstar demo [--json] Runs a disposable, self-contained end-to-end scenario: freeze, a denied protected edit, a denied API change, a scoped approval. Touches nothing outside a temp dir. First thing to run. No setup, no target repo needed.
northstar init [objective] [--from-task FILE] [--behavior] [--agent claude|codex] [--no-install] [--dry-run] [--accept-uncompiled] Compiles an objective (plain text or --from-task FILE) into a contract, freezes the baseline (files, public API, deps, module graph, optionally test outcomes with --behavior), seals the authority outside the tree, and wires agent hooks/AGENTS.md/CLAUDE.md unless --no-install. Once per task/objective, at the repository root. --dry-run first to review the compiled contract before anything is written. Requires a real interactive terminal -- an agent cannot run this for itself.
northstar compile [text|--file FILE] [--write] Translates a task description into constraints without doing the freeze/wiring init does. --write saves the result as the contract. Iterating on a task description before committing to a full init.
northstar migrate [--accept-existing-state] Moves an explicitly reviewed pre-R1 contract bundle forward to the current format. Only when upgrading an older installed contract; requires the human to confirm they reviewed the existing state.
northstar check [--json] Deterministic whole-tree verification against the frozen baseline: hashes, AST-level public API, dependencies, module edges. This is what PostToolUse calls under the hood. Run after any batch of edits, or wire it into CI as a gate. Non-zero exit on any divergence.
northstar status Restates the objective and the current verdict from authenticated state, not conversational memory. The first thing an agent should read after a context compaction or a session handoff.
northstar request --grant KIND:ID --reason "..." Files a scoped, named widening request against the running contract. Does not grant anything by itself. The agent's only path when a real constraint blocks the objective -- request, don't work around.
northstar amend --grant KIND:ID --reason "..." Deprecated alias for request, kept for backward compatibility. Prefer request.
northstar approve REQUEST_ID Approves one pending request, authenticated with the approval passphrase. Structurally cannot be run by the same automated process that filed the request. A human, in a separate interactive terminal from the agent's.
northstar receipt [--json] Prints the bound chain of contract, baseline, diff and every decision made. Audit trail: "why was this allowed/denied," after the fact.
northstar freeze --reason "..." Human-confirmed full re-baseline -- redeclares the entire frozen state, not a scoped grant. Only when the objective itself has legitimately changed, not to route around a single denial.
northstar install [--agent claude|codex] Wires agent hooks/config for an already-init'd project without touching the contract. Adding a second agent client to an existing installation.
northstar uninstall [--agent all|claude|codex] Authenticated removal of Northstar's adapters; leaves unrelated settings alone. Cleanly stop governing a project.
northstar doctor [--json] [--strict] Read-only diagnostic: runtime, sealed authority, mirror integrity, agent wiring, observed hook activity, installed agent executables. Normal mode passes on warnings; --strict fails on them too. Before the first real run, and any time something looks off. --strict in CI.
northstar bench [--json] [--output FILE] Re-runs IntentDriftBench (24 scripted paired trajectories) live and prints the regression table -- the "with vs. without runtime" numbers below come from this. Verifying the shipped evidence yourself instead of trusting the README.
northstar live-bench {validate,plan,preflight,run,packet,analyze,report} The paired, blinded evaluation harness for running the benchmark against real Claude Code/Codex agents: validates a study manifest, writes a preregistered plan, checks pinned versions, runs isolated clones, blinds outcome packets, combines independent annotations, and renders a claim-bounded report. Producing or reproducing an independent effectiveness study -- see LiveAgentBench.
northstar hook The actual PreToolUse/PostToolUse entrypoint: reads a Claude Code/Codex-shaped hook JSON payload from stdin, returns the verdict, exits non-zero to block. Not something you run by hand day-to-day -- this is what the wired hooks call automatically. Useful to pipe a crafted payload into when debugging what a specific tool call would do.
northstar show Prints the current contract as-is. Quick "what am I actually bound by right now."

Compatibility

  • Python 3.11, 3.12, 3.13 -- CI runs Linux and Windows on all three, plus macOS on 3.12.
  • Static analysis (AST-precise): Python. Public API, module graph and signature changes are extracted from the real AST, not text diffing.
  • Static analysis (heuristic, says so explicitly): JavaScript, TypeScript, Go, Rust, Java. Unsupported constructs surface as UNKNOWN rather than a false ALLOW.
  • Agent wiring: Claude Code (PreToolUse + PostToolUse hooks, native) and Codex (project hooks + AGENTS.md; the human must trust the hook via /hooks -- Northstar can verify the hook file but not Codex's local trust decision).
  • Contract authority: OS-native data directory (outside the working tree), sealed with HMAC; human amendments authenticated with an encrypted Ed25519 key.
  • Not an OS sandbox. Tamper-evident, not tamper-proof against an unrestricted same-user process -- see SECURITY.md for the actual threat model before relying on it against a genuinely malicious process.

Evidence, with claim boundaries

Evidence Status What it supports What it does not support
Unit, integration and adversarial tests Reproduced in CI Implementation and integrity behaviour Live-agent effectiveness
IntentDriftBench, 24 scripted paired trajectories Reproduced in CI 0% silent drift, 0% false blocks and 100% completion in this authored corpus Independent or real-world rates
LiveAgentBench harness Implemented and preflightable Reproducible paired runs, blinding, annotation and bootstrap analysis A result before real runs are published
Independent Claude Code/Codex study Pending Would support an external effectiveness estimate Nothing is claimed yet
External adopter outcomes Pending Would support usability and retention claims Stars are not effectiveness evidence

Run the internal regression evidence yourself:

northstar bench
Metric Without runtime With runtime
Hard-constraint violation rate 91.7% 20.8%
Silent drift rate 91.7% 0.0%
False block rate 0.0% 0.0%
Human escalation rate 0.0% 4.2%
Task completion rate 100.0% 100.0%

Read that as: on this authored corpus, tasks still finish (100% completion either way), false blocks stay at zero, but a silent, un-noticed violation of a declared constraint drops from 91.7% of trajectories to 0.0% -- the cost is a small human-escalation rate (4.2%) instead of a violation nobody caught. See Honest limits below for what this evidence does not yet support -- these are scripted, project-authored trajectories, not an independent estimate of live-agent effectiveness.

These are product-authored scripted trajectories, not an external estimate. The publication rules, claim ladder and current ledger live in EVIDENCE.md. The live study protocol includes exact version pins, commit-pinned clones, blinded outcome packets, independent labels and paired confidence intervals:

northstar live-bench validate study.yml
northstar live-bench preflight study.yml --check-repositories
northstar live-bench plan study.yml --output preregistered-plan.json
# run -> packet -> independently label -> analyze
northstar live-bench report report.json --output report.md

See LiveAgentBench. The report renderer refuses a report whose declared ground truth is not independent_annotations.

Honest limits

  • Northstar verifies declared, machine-checkable invariants; it does not prove subjective intent such as “keep the architecture simple.”
  • Python surfaces use the AST. JavaScript, TypeScript, Go, Rust and Java extractors are heuristic and say so; unsupported surfaces become UNKNOWN.
  • External state and seals are tamper-evident, not an OS sandbox. An unrestricted same-user process can ultimately reach the authority key. Use real isolation when defending against a malicious process; read SECURITY.md.
  • API, dependency and graph changes are generally detected after the edit; protected paths can be blocked before it. Git owns rollback.
  • No independently labelled live-agent numbers are claimed today.

Development and release status

python -m pip install -e ".[dev]"
ruff check src tests
python -m pytest --cov=northstar --cov-report=term-missing
northstar demo --json
northstar bench --json

CI tests Python 3.11–3.13 on Linux and Windows plus Python 3.12 on macOS, enforces 95% branch coverage, reruns the scripted benchmark, and clean-installs the wheel. The tag-driven workflow is prepared for PyPI Trusted Publishing, SBOMs, GitHub release assets and build provenance. 0.2.0 remains unreleased until the one-time publisher configuration and release smoke test are complete; see releasing.

Contributions are welcome, especially independently authored benchmark tasks, compiler corpora and false-block reports. Start with CONTRIBUTING.md and the roadmap.

License

Apache-2.0

About

Executable intent contracts for coding agents. Detect and block silent intent drift in Claude Code, Codex and other coding agents.

Topics

Resources

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages