Skip to content

feat(installer): tag-triggered Windows installer, plus a dry run that publishes nothing - #2

Merged
joepetjr merged 1 commit into
mainfrom
feat/windows-installer
Aug 3, 2026
Merged

joepetjr merged 1 commit into
mainfrom
feat/windows-installer

Conversation

@joepetjr

@joepetjr joepetjr commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Summary

Ports the reviewed installer pattern from keycut (#2/#3), with two deviations that a faithful port
would have got wrong.

--help was a lying smoke test here

agent-audit loads its analysis-pass prompts as packaged markdown through importlib.resources
(src/agent_audit/prompts/__init__.py:32, declared at pyproject.toml:42-43). PyInstaller's import
analysis cannot see data loaded that way and does not collect it.

The keycut-identical build command was run first, deliberately. It succeeded, and:

dist/agent-audit --help                  -> exit 0
dist/agent-audit --version               -> exit 0, "agent-audit 0.1.0"
dist/agent-audit skills scan <empty dir>  -> exit 1
   FileNotFoundError: no packaged prompt named 'skills_security'

A faithful port would have shipped an installer that passes its own release-gate smoke test and is
broken for every real user
. Two changes close it:

  1. --collect-data agent_audit on the PyInstaller line — the bad artifact becomes unbuildable
    rather than merely detectable.
  2. The smoke step now runs a real skills scan over an empty directory with
    AGENT_AUDIT_CLAUDE_BIN pointed at a nonexistent name. A missing CLI is recorded as a coverage
    gap rather than raising, so this exercises prompt loading and report writing end to end with no
    CLI, no network and no spend. --help stays as the first assertion.

After the rebuild that scan exits 0 and writes 2026-08-03-skill-audit.md.

The external requirement is the claude CLI — not "none"

The brief guessed this might be the dependency-free port. It is not, and the distinction matters:
dependencies = [] means no third-party Python packages, which is a different claim.

  • src/agent_audit/runner.py:23 — CLAUDE_BIN = os.environ.get("AGENT_AUDIT_CLAUDE_BIN", "claude")
  • runner.py:93-107 — every pass is a claude -p … --json-schema argv
  • runner.py:124-129 — subprocess.run, with FileNotFoundError → "install the Claude Code CLI,
    or set $AGENT_AUDIT_CLAUDE_BIN"

The finish page and README state it, along with the counterweight the README already documents at
106-108: skills manifest, skills diff and --focus structural work without the CLI. No install
one-liner was invented
— it cites https://www.anthropic.com/claude-code, matching the existing
README. No ffmpeg wording leaked from the reference: grep -rin 'keycut|ffmpeg|ffprobe|Gyan' over
every changed file is clean.

Test plan

  • Build without --collect-data → broken as shown above; with it → skills scan exits 0
  • pytest → 160 passed, re-run unpiped by the dispatcher; ruff check . → all checks passed;
    ruff format --check . → 22 files already formatted
  • Frozen binary 8.2 MB (Linux ELF; Windows PE differs)
  • Warn file: after filtering platform false positives, only _scproxy (macOS-only) and five
    multiprocessing.<attr> non-module entries. No --hidden-import needed. Grepped for
    import_module/plugin discovery — importlib is used for data only
  • .iss pure ASCII, no BOM, [Registry] PATH on one line; fresh AppId GUID, not keycut's
  • Workflow parses, 11 steps, both if: gates present

Unverified until a real Windows run

ISCC compiling the .iss, the HKLM PATH add/remove Pascal, the Windows freeze,
choco install innosetup, the gh release branch, and SmartScreen on the unsigned binary.
Merge after keycut's dry run goes green.

Diff 281 sum (cap 300). src/, tests/ and ci.yml untouched.

…mpts

Pushing a v* tag freezes agent-audit with PyInstaller on windows-latest,
wraps it in Inno Setup, and attaches the result to that tag's release.
The installer lands in Program Files, appends that directory to the
machine PATH (HKLM, removed again on uninstall) and registers itself in
Add/Remove Programs. workflow_dispatch runs the same build and keeps the
installer as an artifact instead of publishing it, so the Windows-only
steps can be proven without a public release.

--collect-data agent_audit is the part that is specific to this repo.
The analysis-pass prompts are markdown loaded through
importlib.resources, which PyInstaller's import analysis cannot see. A
build without the flag succeeds, answers --help, and then dies with
FileNotFoundError on the first real audit, so the smoke test runs an
actual `skills scan` over an empty directory rather than trusting
--help.

agent-audit needs the Claude Code CLI on PATH for its model-backed
passes and the installer does not bundle it. The finish page and the
README say so; the deterministic commands still work without it.

The [Registry] PATH line stays one long line on purpose, the .iss stays
pure ASCII because Inno reads a BOM-less script as ANSI, and AppVersion
has no default so a build that forgets it fails instead of shipping
0.0.0-dev.
@joepetjr
joepetjr merged commit d4a7483 into main Aug 3, 2026
4 checks passed
@joepetjr
joepetjr deleted the feat/windows-installer branch August 3, 2026 22:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant