Skip to main content

Nofax: explicit human decisions for AI agents

An open-source bridge between AI coding agents and explicit human decisions. Local mode supports approvals, choices, refinements, and bounded waits; the optional remote Worker is intentionally limited to one-way notifications and safe request inspection.

View repository
  • Open-source developer tooling
  • MCP integration
  • Human-in-the-loop workflow
  • Cloudflare Worker boundary

Local decisions, narrower remote visibility

Nofax keeps decision authority local. The local workflow can ask a person to approve or deny an action, choose among options, refine a request, and wait for an explicit response. The optional remote Worker has a smaller contract: it can send a one-way notification and expose bounded request metadata for inspection. It cannot approve, deny, choose, refine, or wait for a decision.

Capability boundary

The distinction is intentional: remote reachability does not grant remote decision authority.

CapabilityLocal workflowRemote Worker
One-way notificationYesYes
Inspect request metadataYesYes
Allow / denyYesNo
Choices / refinementYesNo
Wait for a decisionYesNo

Pending is not approval

The current documentation and tests are fail-closed: pending, timeout, malformed results, network failures, and disconnects must not be converted into an Allow decision. A wait that is still pending remains pending and requires another explicit wait. Nofax transports a human decision; it is not the policy engine that decides whether an action should be allowed.

Engineering note

Recovering the newest pending request

PR #34, “fix: recover newest pending requests,” was merged on 22 September 2026 at merge commit 979df9f5a3a3e52004a398c1b8738dbb80c6ffd2.

Before

Pending filenames contain random request IDs. The implementation reverse-sorted those filenames and stopped once the bounded result count was reached. A newly created request with a lexicographically low ID could therefore be omitted before its record was ever examined.

After

The implementation reads the pending records, sorts them by durable createdAt newest-first with request ID as a deterministic tie-breaker, and only then applies the result limit.

Synthetic regression fixture

The regression test creates 20 older records plus one newest record, requests a limit of 20, and asserts that the newest record is first and included while the oldest record is excluded. This is synthetic test data, not user volume, a client incident, or measured customer impact.

Public evidence

Historical CI on 22 September 2026 passed the Node 20, Node 22, Node 24, Worker, and CodeQL checks. That is historical GitHub CI evidence, separate from the portfolio tests run for this page.

Current boundaries

  • The remote Worker exposes notification and safe-inspection functions only; it is not a hosted approval service.
  • No paying-team, adoption, uptime, or universal security claim is made here.
  • Package versions and download counts are intentionally omitted because they are volatile and do not establish the approval boundary.