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 repositoryLocal 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.
| Capability | Local workflow | Remote Worker |
|---|---|---|
| One-way notification | Yes | Yes |
| Inspect request metadata | Yes | Yes |
| Allow / deny | Yes | No |
| Choices / refinement | Yes | No |
| Wait for a decision | Yes | No |
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.
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.

