Skip to content

About

Deterministic scope contracts and guardrails for AI coding agents.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Repository files navigation

⚑ ChangeBudget

Keep AI coding changes inside the scope you approved.

Small task β‰  giant diff.

TypeScript 5.9 Node.js 20+ Public npm package Local first Deterministic core OpenCode integration

Scope contracts for coding agents. ChangeBudget records what a task is allowed to change, inspects the real Git state, and reports whether the result is inside the approved boundary.

No cloud policy engine. No telemetry. No LLM required at runtime.

πŸš€ Quick Start β€’ πŸ”„ Update β€’ πŸ’» Show Me Code β€’ πŸ€– Agent Discovery β€’ 🧠 How It Works β€’ πŸ—ΊοΈ Roadmap

The Problem

A small request can become a large, difficult-to-review diff:

Task:
"Add an empty state to the player"

Expected:
3 files
~100 lines

Agent result:
17 files
new dependency
navigation refactor
configuration changes
full-project cleanup

The agent may produce valid code and still exceed the change the developer intended.

The Solution

ChangeBudget turns the intended scope into a Change Contract, then compares the repository's actual Git changes with that contract.

Task
  ↓
Change Contract
  ↓
Agent implements
  ↓
Git inspection
  ↓
Deterministic rules
  ↓
PASS / REPAIR / HUMAN_REVIEW

The agent proposes code. The developer owns the boundaries.

ChangeBudget is deterministic, local-first, Git-backed, explainable, and usable without an LLM. Git and explicit ChangeBudget rules decide compliance; the LLM uses the framework but does not control its policy.

πŸš€ Quick Start

The recommended first run is three separate steps.

Step 1 β€” Install ChangeBudget

npm install -g changebudget

ChangeBudget is installed from the npm registry. To install a specific published release, use its exact version:

npm install -g changebudget@VERSION --registry=https://registry.npmjs.org/

Step 2 β€” Integrate ChangeBudget into the project

From the target Git repository:

changebudget integrate opencode

This creates or updates exactly one project-local OpenCode V2 resource:

  • .opencode/plugins/changebudget.js

The marked wrapper is loaded automatically by OpenCode V2. The plugin adds the ChangeBudget workflow to the session context and evaluates permissions through the native context and evaluate hooks. The command never creates or edits opencode.json, instruction files, or AGENTS.md; the core CLI remains independent of OpenCode.

Step 3 β€” Start coding

Open OpenCode and describe the task normally:

Implement T031

or:

Add pagination to the users endpoint. Keep the change minimal.

That's it. OpenCode V2 loads the project-local plugin automatically, so the coding agent receives the ChangeBudget workflow through the session context. This automatic discovery currently refers specifically to OpenCode; it is not a claim that every model or coding tool supports it.

To inspect command syntax without executing a command, run changebudget <command> --help or changebudget help <command>.

πŸ”„ Keep ChangeBudget Updated

changebudget update discovers published versions from the npm registry and installs only a newer compatible release in the installed major line. It installs the selected release by exact version and reports real installation start and result status without estimating progress. If the current release is already up to date, it safely refreshes only an existing managed OpenCode integration in the current project. If a newer major version is reported and automatic installation is refused, it still safely refreshes an existing managed OpenCode integration.

changebudget update

After a successful compatible update, ChangeBudget automatically refreshes a managed stale OpenCode V2 wrapper in the current project. Projects with no wrapper or a user-owned conflict are not changed automatically.

For a first-time setup, or to explicitly action an integration, run:

changebudget integrate opencode

Use changebudget integrate opencode --dry-run to preview the explicit integration action. The command manages only its marked wrapper and leaves unrelated project files untouched.

To only check for a new update without installing it:

changebudget update --check

This queries the npm registry and reports the installed version, the latest compatible version, and whether an update is available. It makes zero writes and does not inspect or modify the target project.

πŸ’» Show Me Code

The developer gives the implementation request. The integrated coding agent handles the ChangeBudget ceremony according to the workflow delivered through the OpenCode V2 session context, while the developer keeps authority if more scope is required.

The following is an illustrative workflow, not a promise of fixed prose output:

You:
"Implement T031"

Agent:
- runs `changebudget status`
- if the repository is uninitialized, runs `changebudget init` and checks status again
- if no contract is active, runs `changebudget diagnose T031`
- starts the appropriate contract, such as `changebudget start T031 --tiny`
- implements the task and runs targeted validation
- runs `changebudget check`
- repairs an in-scope violation without widening the contract
- runs `changebudget close` only after validation and PASS

For a project without Spec-Kit:

You:
"Add pagination to the users endpoint. Keep the change minimal."

Agent:
- checks ChangeBudget state
- establishes the appropriate contract
- implements only within the approved scope
- validates the implementation
- runs `changebudget check`
- closes the contract only after PASS

πŸ€– How the Agent Discovers ChangeBudget

changebudget integrate opencode creates the project-local OpenCode V2 plugin wrapper, which makes the workflow explicit to the coding agent:

Developer integrates once
        ↓
changebudget integrate opencode
        ↓
Native V2 plugin wrapper + Runtime Guard
        ↓
OpenCode loads the plugin
        ↓
Session context receives the ChangeBudget lifecycle
        ↓
status β†’ diagnose/start β†’ implement β†’ check β†’ close

The plugin's session context tells the agent to:

Before implementation

  • run changebudget status;
  • if the repository is uninitialized, run changebudget init and check status again;
  • start a contract if none is active;
  • for a Spec-Kit Txxx task without an explicit budget, run changebudget diagnose Txxx;
  • never widen a contract automatically; wait for explicit developer approval before adding each exact literal path with changebudget amend --allow-path <path> --reason <reason>, then run changebudget check and ask again for any further scope. The CLI cannot cryptographically distinguish a human from an agent; its technical guarantees are an explicit amendment request, exact literal path, non-empty reason, and path safety invariants.

During implementation

  • stay inside allowed paths;
  • never manually modify .changebudget/**;
  • respect protected and denied paths.

After implementation

  • run targeted validation;
  • run changebudget check;
  • repair violations without widening the contract;
  • run changebudget close only after validation succeeds.

There is no special ChangeBudget model, no required prompt to paste every session, and no persistent model memory involved. The integration is project-local and idempotent. ChangeBudget can also be used manually or by another coding agent capable of invoking commands. Automatic workflow discovery documented here targets OpenCode only; support for Cursor, Claude Code, Copilot, Aider, or other agents is not implied.

🧠 How It Works

flowchart LR
    A[Developer task] --> B[Change Contract]
    B --> C[Coding Agent]
    C --> D[Repository changes]
    D --> E[Git inspection]
    E --> F[ChangeBudget rules]
    F --> G{Decision}
    G -->|PASS| H[Continue]
    G -->|REPAIR| I[Bring changes back in scope]
    G -->|HUMAN_REVIEW| J[Developer decides]
Loading

The enforcement core is intentionally simple:

Git + explicit rules + deterministic evaluation

The diff is the source of truth, not the agent's description of what it changed. ChangeBudget can evaluate staged, unstaged, untracked, deleted, renamed, and binary Git changes. Its own .changebudget/** metadata is excluded from the user budget.

Decisions

PASS

Repository state satisfies the active contract.

REPAIR

A deterministic violation exists. Bring the implementation back inside the already-approved contract.

HUMAN_REVIEW

Developer authority is required because ChangeBudget cannot safely continue under the current contract or environment. HUMAN_REVIEW is not authorization to amend or widen a contract.

ChangeBudget never automatically widens a contract, raises a budget, rewrites permissions, reverts work, or deletes user files. REPAIR and HUMAN_REVIEW report a decision; neither grants authority to amend or widen a contract.

Decision Exit code
PASS 0
REPAIR 1
HUMAN_REVIEW 2

What ChangeBudget Guards

Guard What it controls
Allowed paths allow_paths controls WHERE a task may touch existing repository paths; an allowed path does not grant file-creation permission
Denied paths Protected paths that remain unavailable
Maximum files The number of changed files
Maximum lines Added plus deleted lines
New files allow_new_files controls WHETHER file creation is allowed; it defaults to false, including for paths allowed by allow_paths, unless --allow-new-files is set
Dependencies Dependency-sensitive changes
Migrations Migration paths and changes
Configuration Configuration-sensitive files
Public API Explicitly classified API-sensitive files
Stack policies Android, Flutter, Spring Boot, and Node/TypeScript rule packs
Spec-Kit tasks Deterministic association with Txxx tasks
Runtime Guard Optional project-local OpenCode allow / ask / deny behavior
Diagnose advisor Read-only budget recommendation before implementation

allow_paths controls WHERE changes may occur. allow_new_files controls WHETHER a new file may be created. An allowed path does not imply permission to create a new file. New file creation defaults to false unless --allow-new-files is set.

Command Reference

Command Purpose
changebudget init Initialize ChangeBudget state in the current Git repository
changebudget diagnose Recommend a deterministic budget before implementation
changebudget start Open a Change Contract
changebudget status Inspect lifecycle state and the active contract
changebudget check Compare real Git changes with the active contract
changebudget close Close a validated contract
changebudget amend Amend numeric budgets or developer-authorized literal paths
changebudget integrate opencode Install or update project-local OpenCode integration
changebudget update --check Check for a compatible ChangeBudget update
changebudget update Install a newer validated compatible ChangeBudget release

Useful options include --json for check, status --budget, and diagnose; contract presets --tiny, --normal, and --free; --allow-path, --deny-path, --max-files, --max-changed-lines, and --stack-profile; and integrate opencode --dry-run or --remove.

OpenCode Runtime Guard

ChangeBudget policy and the OpenCode Runtime Guard are separate layers:

ChangeBudget policy Runtime Guard action
Deterministic contract evaluation Runtime allow, ask, or deny behavior
PASS Allow known in-scope work
Risky or unresolved context Ask when explicit review is appropriate
REPAIR, unsafe mutation, or protected state Deny or block

The project-local Runtime Guard can allow known in-scope writes, ask again for risky operations, deny protected paths, protect .changebudget/**, and fail safely when a mutation target cannot be resolved. It remains local and is not an operating-system sandbox.

The normal installation path is changebudget integrate opencode; users do not need to hand-write a plugin wrapper. The compiled plugin must exist, so a source checkout should run npm run compile first.

Spec-Kit

ChangeBudget can associate a contract with an existing Spec-Kit task without replacing or modifying Spec-Kit:

changebudget diagnose T031
changebudget start T031 --tiny

Txxx resolution is deterministic. Task metadata is captured when the contract starts. ChangeBudget never modifies tasks.md, marks tasks complete, invokes /speckit.*, or treats PASS as proof that a Spec-Kit task is complete.

Task lines may define a default:

- [ ] T031 [budget:tiny] Implement task bridge

Precedence is deterministic: explicit CLI budget, then task [budget:...] default, then normal contract behavior. Projects without Spec-Kit work normally.

Diagnose & Budget Advisor

diagnose is a deterministic, read-only advisor based on observable repository and task evidence. It is not an LLM, does not enforce the result, and cannot widen an active contract.

Possible recommendations are tiny, normal, free, or manual review:

changebudget diagnose --allow-path "src/player/**"
changebudget diagnose T031 --json

It does not create contracts, modify .changebudget/**, modify project files, modify Spec-Kit tasks, or invoke OpenCode.

Stack Policies

Stack policies are deterministic rule packs, not semantic AI analysis. Current profiles are:

  • Android: Gradle, manifests, signing, release, and protected configuration surfaces.
  • Flutter: pubspec, analysis configuration, platform, and release surfaces.
  • Spring Boot: Maven/Gradle dependencies, application configuration, and migration paths.
  • Node / TypeScript: package.json, lockfiles, TypeScript configuration, and selected public API surfaces.

Select a profile when starting a contract:

changebudget start --task "Update application config" --base-revision HEAD --stack-profile spring-boot --max-files 5 --max-changed-lines 150

Repository overrides live in .changebudget/stack-policy-overrides.json; individual rules can be disabled with --disable-stack-rule <rule-id>.

πŸ—ΊοΈ Roadmap

βœ… Shipped

  • Local Change Contract lifecycle and deterministic Git budget engine.
  • PASS, REPAIR, and HUMAN_REVIEW results with reports and exit codes.
  • OpenCode Runtime Guard and project-local integrate opencode workflow.
  • Android, Flutter, Spring Boot, and Node/TypeScript stack policies.
  • Spec-Kit task bridge and deterministic diagnose advisor.
  • Personal v1.0 reliability hardening.
  • Immutable tagged installation, Windows/Linux CI, and tagged-smoke validation.
  • SPEC-012 complete: immutable v1.1.5 tagged smoke passed on Ubuntu and Windows.
  • Working Tree Baseline: unchanged pre-existing work is excluded from a new contract while later semantic edits remain enforced.

The roadmap's explicitly deferred items remain deferred: cloud services, dashboards, accounts, billing, marketplaces, remote execution, full OS sandboxing, silent auto-repair, and LLM-based compliance.

View the full roadmap β†’

Release & Validation

Current development version: 2.0.0-beta.7.

  • Normal CI runs on Windows and Ubuntu.
  • Windows test execution uses native Node sharding.
  • npm package installation is validated from the public registry.
  • A maintainer-controlled GitHub Release triggers npm-publish.yml, which uses GitHub Actions OIDC trusted publishing after publication validation passes on Ubuntu and Windows.
  • SPEC-012 is complete.
  • GitHub Release publication remains a manual maintainer action.

The npm package is public. The stable OIDC release flow uses the public registry and does not require a PAT, custom secret, SSH key, gh, or a personal credential helper.

Release channels

The published Git tag must be exactly v followed by the package version. Stable releases use a normal GitHub Release and npm dist-tag latest; prereleases use a GitHub prerelease and their matching npm channel:

Version Git tag GitHub Release npm dist-tag
X.Y.Z vX.Y.Z Normal release (prerelease=false) latest
X.Y.Z-alpha.N vX.Y.Z-alpha.N Prerelease (prerelease=true) alpha
X.Y.Z-beta.N vX.Y.Z-beta.N Prerelease (prerelease=true) beta
X.Y.Z-rc.N vX.Y.Z-rc.N Prerelease (prerelease=true) rc

Only those stable and prerelease forms are supported. The release workflow validates the package, lockfile, Git tag, and GitHub Release classification, then always publishes with an explicit npm dist-tag. Before a prerelease it records the existing stable latest; afterward it verifies that the prerelease channel points to the new version and latest is unchanged. A mismatch fails without attempting to repair registry tags. Prereleases never modify latest.

changebudget update remains stable-only: it does not discover or automatically install prereleases. Install or update a prerelease explicitly through npm, for example npm install changebudget@beta.

Design Principles

  • Local-first: no backend or account is required for normal operation.
  • Deterministic: Git and explicit rules decide compliance.
  • Human authority: agents cannot authorize their own scope expansion.
  • Explainable: violations expose rules, paths, and reason codes.
  • No silent destruction: validation does not revert or delete user work.
  • Fast-path friendly: small tasks should have a small workflow.
  • No LLM required at runtime: AI may write code; it does not decide policy.
  • Zero telemetry by default: code, diffs, and project paths stay local.

πŸ› οΈ Development

This is for working on ChangeBudget itself, not the normal end-user installation path.

Requirements: Node.js 20+, Git, and npm.

npm install
npm run compile
npm run typecheck
npm test

Project Structure

ChangeBudget/
β”œβ”€β”€ src/                    # CLI, Git inspection, rules, state, and policies
β”œβ”€β”€ opencode-plugin/        # OpenCode Runtime Guard package
β”œβ”€β”€ tests/                  # Unit, integration, acceptance, and contract tests
β”œβ”€β”€ specs/                  # Spec-Kit feature artifacts
β”œβ”€β”€ .specify/               # Spec-Kit project configuration
└── ChangeBudget_Roadmap.md

Deliberate Non-Goals

ChangeBudget does not provide a cloud backend, accounts, teams, telemetry, a web dashboard, remote code execution, a general shell parser, a full operating-system sandbox, universal AST analysis, LLM-based compliance decisions, automatic rollback, silent contract widening, or a public policy marketplace.

License and Community

ChangeBudget is available under the MIT License. See third-party notices, contributing guidance, the security policy, and the Code of Conduct.

About

Deterministic scope contracts and guardrails for AI coding agents.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages