Skip to content

v0.9.0

Choose a tag to compare

@prabhuakshay prabhuakshay released this 25 Jun 05:29

forge v0.9.0 hardens the core that the whole enforcement model rests on — the
workflow state and the green-gate fingerprint — and pins down the supported
platform.

Fixed

  • The green-gate fingerprint no longer misses a same-second edit. A new
    stat-keyed digest cache makes code_fingerprint skip files it can prove are
    unchanged, but a naive (mtime, size) cache would wrongly trust a same-size
    edit landing in the same clock-granularity tick as the last hash — the classic
    "racy clean" problem, and not theoretical (fast/tmpfs writes hit it). The cache
    now applies git's rule: an entry is trusted only when the file's mtime is in a
    strictly earlier whole second than the recorded cache build time. A
    same-second change is always re-hashed; the content-addressed guarantee holds.

Changed

  • Workflow state is now concurrency-safe. Claude Code can run tools (and
    hooks) at once; two updaters racing on a read-modify-write of state.json
    could let one os.replace silently drop the other's change — a lost dirty_py
    entry, or worse a dropped overrides audit record. Every mutation now runs
    under an exclusive POSIX advisory lock (.forge/.state.lock).
  • code_fingerprint only re-reads what changed, via a git-ignored
    .forge/fpcache.json cache, so the per-commit hash stays proportional to the
    edit rather than to repo size. The logic moved into a new dependency-free
    lib/fingerprint.py; state re-exports it, so callers are unchanged.

Documentation

  • forge now states its requirements plainly: Python projects only, and
    Linux/macOS only — the hooks invoke python3 and the state relies on POSIX
    file locking (fcntl), so Windows is unsupported. The manifests carry the same
    constraint.
  • docs/state-schema.md documents the two new local-only sidecar files.

Internal

  • A meta-test asserts the prompt layer stays wired up: every bin/*.py a command
    invokes, every agent it names, and every hooks.json script must resolve to a
    real file — so a rename or typo there can't ship undetected.

Full changelog: v0.8.0...v0.9.0