DEV Community

dormitivegit
dormitivegit

Posted on

Same pack, different CWD, different verdict

Earlier in development, the same governance pack passed from one working directory
and failed from another. Same pack bytes. Same referenced source bytes. Only the
process working directory differed.

A relative embedded source path was being resolved against the process working
directory. A value the tool never declared as an input was changing the verdict.

The defect became visible when the same check was run from a different working
directory.

What the fix actually changed

Relative embedded source paths now resolve against the pack's own directory instead
of the process working directory. Absolute references stay absolute.

For file-backed packs, relative references resolve from the pack's directory. With
stdin there is no pack directory, so relative references are rejected rather than
silently inheriting the process working directory. I required that stdin reject
relative references instead of inventing a base directory.

Why ordinary tests did not catch it

A passing behavior test does not by itself prove that the files or evidence source I
intended to check stayed bound.

In an AI-assisted workflow, changes can arrive faster than I can re-check every
assumption behind them. I wanted a small mechanical check for the things I had
already decided mattered, while keeping the acceptance decision with me.

This CLI adds a narrower deterministic check after ordinary tests. Its result is
evidence for a reviewer or a CI system; it is not release authorization.

The smallest thing you can run

I use the corpus command below because it is the shortest way to show the mechanism.
It is not a reproduction of the path-resolution bug above.

All commands below were replayed against software-evidence-controls==0.4.0rc1.

python3 -m venv .venv
. .venv/bin/activate
python -m pip install software-evidence-controls==0.4.0rc1
Enter fullscreen mode Exit fullscreen mode

Create a throwaway source directory, freeze it, change one byte, and verify:

demo_dir="$(mktemp -d)"
source_dir="$demo_dir/source"
manifest="$demo_dir/accepted-manifest.jsonl"
mkdir -p "$source_dir"
printf '%s\n' 'value = 1' > "$source_dir/example.py"

software-evidence-controls corpus freeze "$source_dir" --manifest "$manifest" --format json

manifest_sha256="$(python - "$manifest" <<'PY'
import hashlib, pathlib, sys
print(hashlib.sha256(pathlib.Path(sys.argv[1]).read_bytes()).hexdigest())
PY
)"

printf '%s\n' 'value = 2' > "$source_dir/example.py"

software-evidence-controls corpus verify "$manifest" \
    --accepted-manifest-sha256 "$manifest_sha256" \
    --expected-root "$source_dir" \
    --format json
Enter fullscreen mode Exit fullscreen mode

Abridged from the actual JSON output:

{
  "result": "HOLD",
  "findings": [
    {
      "code": "CI03_SOURCE_CHANGED",
      "severity": "ERROR",
      "message": "filesystem source bytes changed",
      "evidence": "example.py"
    }
  ],
  "exit_code": 4,
  "counts": {
    "match": 0,
    "missing": 0,
    "changed": 1,
    "type_changed": 0,
    "self_ingested": 0
  }
}
Enter fullscreen mode Exit fullscreen mode

This means the recorded source changed. It does not mean "reject the change." The
finding is an input to CI or review; acceptance remains a human decision.

The fastest way to evaluate this is to run it.

What the tool covers

The CLI has several surfaces; these are the two used in this article.

corpus freeze / corpus verify records the bytes of a set of files you explicitly
select, then verifies that those recorded sources have not changed. It does not prove
that the scope you selected was complete.

check validates a pack against explicit rules and returns a machine-readable
PASS / FAIL / HOLD result with structured findings.

With --format json, these commands emit structured output meant to be consumed by
CI or read by a reviewer rather than skimmed as a log.

What this does not prove

The published package declares no third-party Python runtime dependencies and
requires Python 3.11 or newer. That is a statement about declared runtime
dependencies, not about pip, the build backend, packaging tooling, or Python
itself.

I have not tested it on Windows. I have not exhaustively tested every CLI option
combination, or long-running and repeated-operation behavior. The integrity check
covers the sources you recorded, not the question of whether you recorded the right
set. Other tools work on adjacent problems. I have no adoption data and make no
claim about who else is using it.

Why the name changed

The project was previously published as fable5-assurance-toolkit. In August 2026 I
renamed the GitHub repository and published the Python distribution under
software-evidence-controls. Existing GitHub URLs redirect; the old PyPI prereleases
remain as historical artifacts.

Anthropic also uses "Fable 5" for a Claude model; this project is unrelated to
Anthropic. The collision accelerated the rename, but the real problem was simpler:
the old name spent its most visible word on an internal lineage label instead of
saying what the tool does.

Who it is for

It is for developers who can already say what must stay true after an AI-assisted
change — which files, which manifest, which pack — and want that boundary checked
mechanically.

If you want a hosted service, a GUI, or an AI agent that decides what to accept for
you, this is not that.

Repository: https://github.com/dormitivegit/software-evidence-controls


I used AI coding and analysis tools while building this. I decided the scope, what I
was willing to claim publicly, and when public changes were authorized.

Top comments (0)