Code Polishy runs from one verified native release built from an exact reviewed source version. The source tag, portable archive, and Linux OCI image all bind to that same commit and internal release digest. This page describes source and portable installation, how a target selects the exact release it requires, and what makes that release acceptable to run. Target configuration is covered in Adoption.
The normal user experience starts with the one bootstrap request in the root
README. After adoption, the installed AGENTS.md
owns recurring operating guidance.
The agent follows AI-Agent Setup and Adoption. It preserves an
existing target lock. For a new adoption it honors a caller-specified exact tag
or resolves the highest strict stable v<MAJOR>.<MINOR>.<PATCH> tag, then makes
a temporary shallow clone of that tag. The clone must prove that the selected
ref is annotated, points directly at HEAD, and matches VERSION. The default
branch supplies current instructions; it is never an installable release.
Adoption pins the canonical publication-index URL and its separately published SHA-256 when it writes the repository lock. This records the exact native archive for every host without embedding a release in the target repository. An unpublished source checkout can build or recover an installation, but it cannot become repository lock authority.
A private repository URL or clean local checkout may be supplied explicitly for private development. The same exact-source rules apply, and the agent never substitutes another repository or revision. Published tags are immutable: never move or reuse one after consumers can select it.
Adoption installs a small POSIX wrapper and PowerShell wrapper in the target
repository. A developer can prepare a fresh clone without finding an installer
or changing PATH:
./code-polishyw setup.\code-polishyw.ps1 setupThe wrapper reads .code-polishy.lock.json. If that exact release already
exists in the default shared user prefix, setup verifies and reuses it without
network access. A v2 lock otherwise supplies the exact HTTPS URL,
SHA-256, and size for every supported host. Setup selects this host, downloads
and checks that archive, and invokes the archive's engine to perform the bounded
bundle installation. It does not need Git, a language toolchain, or a local
build.
An explicit clean local checkout is also available as a recovery path for the exact release already named by a v2 lock:
./code-polishyw setup --source <local-code-polishy-checkout>The source installer must still prove that its result satisfies the target lock. The wrapper never silently clones or falls back to source.
After setup, use ./code-polishyw <command> or
.\code-polishyw.ps1 <command>. Ordinary dispatch verifies the exact installed
release through the stable launcher and performs no clone, download, build,
fallback selection, or PATH mutation. The wrappers contain only bootstrap and
dispatch logic; the complete release remains in the shared user store.
Source acquisition stays outside the installers. They never select a version,
fetch, pull, switch revisions, invoke gh, or call a GitHub API. They require a
clean Git checkout, read its exact commit, and build only what is already there.
Maintainers can therefore use the same installers for a clean candidate commit
before its version tag exists.
From a verified checkout on Linux or macOS:
./tools/install-policy-tools.sh
./scripts/install.shFrom a verified checkout on Windows x64, in PowerShell:
.\tools\install-policy-tools.ps1
.\scripts\install.ps1./scripts/install.sh --require-repository <target> and
.\scripts\install.ps1 -RequireRepository <target> add a pre-publication
constraint for wrapper-driven installation. The completed staged release and
all its bytes must satisfy that target's exact lock before installation begins.
Windows requires Git and PowerShell but does not need WSL or Git Bash. The PowerShell installer locally builds the same deterministic native ZIP format, verifies its checksum and complete release manifest, installs it atomically, and deletes its temporary archive.
When Windows does not grant symlink creation privilege, pnpm materializes its isolated dependency graph with absolute directory junctions. The tool installer therefore builds that graph only at its stable transaction-owned location and removes incomplete output on failure; moving a completed graph from a different staging path would leave its junction targets pointing at the wrong tree. The native release builder uses the same frozen lock and offline store to ask the pinned pnpm for its portable hoisted layout, converts its remaining links to regular entries, writes the bundle manifest, and proves the staged runner can report provenance before creating the ZIP. The portable layout is confined to the sealed release bundle and never resolves dependencies from a target.
The tool installer is the only networked installation stage. It admits only the checked-in pinned tool artifacts, verifies every archive before extraction, builds the pinned Go analyzers with the pinned Go toolchain, and installs the JavaScript graph from its frozen lock with lifecycle scripts disabled. The source installer then refuses to run until the sealed runtime, bundle, and every other pinned tool are present and verified. Its manifest records every staged byte, so the launcher verifies the carried tools with the rest of the release before it runs.
The release gate separately resolves every standalone tool pin against its fixed upstream publication metadata and enforces the shared 30-day minimum. Checksum verification proves which bytes were acquired; release-age admission proves the selected upstream release has matured or carries one exact, expiring assessment.
Each supported host publishes one deterministic ZIP, internal manifest,
CycloneDX 1.6 SBOM, deterministic in-toto/SLSA provenance metadata, and
machine-readable release descriptor. This local metadata binds inputs and
outputs but does not authenticate a builder or publisher. The five hosts are
darwin-arm64, darwin-x64,
linux-arm64, linux-x64, and windows-x64. The descriptor binds every
accompanying metadata file, the archive SHA-256, host-specific content digest,
shared release digest, version, and source revision.
From a clean Linux or macOS release checkout with tools already installed:
./scripts/build-release.sh --output /absolute/path/to/publicationOn Windows x64:
.\scripts\build-release.ps1 -Output C:\release\code-polishy.zip -PublicationDirectory C:\release\publicationEach command refuses an existing destination and publishes atomically. After
all native builders finish, combine the five descriptors with repeated
--artifact-descriptor options:
code-polishy release-manifest index \
--artifact-descriptor /release/darwin-arm64/*.release.json \
--artifact-descriptor /release/darwin-x64/*.release.json \
--artifact-descriptor /release/linux-arm64/*.release.json \
--artifact-descriptor /release/linux-x64/*.release.json \
--artifact-descriptor /release/windows-x64/*.release.json \
--output /release/code-polishy-release-index.jsonThe index is written only when every descriptor and sidecar validates, all five hosts appear exactly once, and every host names one version, source commit, and release digest. The command prints the SHA-256 of the exact canonical index; publish that digest beside its HTTPS URL for repository adoption and upgrade planning. Downloading and digest custody belong to the caller or CI. Given already acquired bytes and their trusted SHA-256, installation remains local:
code-polishy install-bundle \
--source /absolute/path/code-polishy-<version>-<host>.zip \
--sha256 <archive-sha256> \
--prefix /opt/code-polishyThe installer accepts no URL, tag, redirect, or relative source. It verifies the archive digest, host, complete internal manifest, and launcher before atomically publishing the release and stable launcher.
The version-tag release workflow builds the Linux image from its already verified publication archive instead of creating a second release tree. It reuses the archive's engine to prepare the OCI context, while Buildx emits SBOM and provenance attestations. The workflow resolves and pulls the registry's exact image digest, then exercises the installed launcher as the image's declared user before reporting success.
Tags aid discovery only. Every workflow and invocation uses the reported
ghcr.io/riteofstring/code-polishy@sha256:... identity. The image runs as
non-root user 65532, starts in /workspace, keeps the stable launcher on
PATH, and verifies its internal release on every command.
A GitLab job may use the public canonical image directly. The package currently publishes Linux x86-64, and a public pull needs no GHCR credentials:
policy:
image:
name: ghcr.io/riteofstring/code-polishy@sha256:<index-digest>
entrypoint: [""]
script:
- code-polishy merge-gate --base "$CI_MERGE_REQUEST_DIFF_BASE_SHA"The equivalent GitHub Actions job sets
container: ghcr.io/riteofstring/code-polishy@sha256:<index-digest> and runs
the same command after checkout. A private or self-managed GitLab repository
does not make this public image private; the runner needs only outbound GHCR
access. Code Polishy needs no GitLab account, API token, monitoring provider,
or machine-global runner installation. The version-tag release workflow
publishes the native archives and this image together; see the Release
Checklist.
The Unix prefix defaults to ~/.local/share/code-polishy; the Windows prefix
defaults to %LOCALAPPDATA%\CodePolishy. Releases are installed under
<prefix>/releases, and the stable launcher is installed under <prefix>/bin.
The default Unix install also creates the guarded command link
~/.local/bin/code-polishy. It refuses to replace an unrelated path there.
The installers report command discovery and print a session-local PATH
command when needed. Persistent PATH setup is explicit:
./scripts/install.sh --add-to-path.\scripts\install.ps1 -AddToUserPathOn Unix, --add-to-path adds one owned entry to the supported shell startup
file for future shells. --path-profile <file> selects a specific startup file
when needed. On Windows, -AddToUserPath adds the launcher directory to the
user PATH for future processes. Repeating either operation is idempotent.
A custom Unix --prefix alone keeps installation writes under that prefix. Add
--command-dir <directory> to create a guarded command link elsewhere.
code-polishy doctor reports command discovery for an installed release.
One release identity has one self-contained policy root per supported host:
- the
code-polishybinary built from the reviewed commit with the pinned Go toolchain; - the sealed Node runtime and JavaScript tool bundle;
- every other pinned tool the engine runs: the Go toolchain, ShellCheck,
staticcheck, govulncheck, OSV-Scanner, Ruff, PyPA
packaging26.3, Vulture2.16,ty, and the carried CPython3.12.13+20260728runtime from python-build-standalone. A target installs no policy tooling, and none of these is ever taken from an ambientPATH, a host installation, or an environment override, so a check decides the same thing on every machine that has the matching host release; - the version-matched
README.md,CHANGELOG.md, permanentdocs/tree, and documentation catalog; - the configuration schema, templates, canonical guidance, pinned tool versions, and native workflow contracts the engine reads at runtime;
- the canonical repository wrapper templates installed during adoption;
- the bundle's dependency and license inventory;
- the launcher, which the installer also copies to
<prefix>/bin/code-polishy; the default Unix installer links~/.local/bin/code-polishyto that stable path; and release-manifest.json, which records everything above.
From a managed repository, read its exact locked guides without locating the release directory:
code-polishy docs list
code-polishy docs find dependency review
code-polishy docs read installationThe files remain available below
<prefix>/releases/<version>-<releaseDigest>/docs/. Documentation and catalog
bytes are recorded in the release manifest like runtime inputs, so a changed,
missing, or added file makes the installed release invalid. Agent guidance is
delivered through generated root files and the versioned documentation CLI.
Language packs are installed separately from engine releases and never change
.code-polishy.lock.json. From a repository already using the intended locked
engine release, verify and install a reviewed local source directory:
code-polishy pack verify --source ./code-polishy-example
code-polishy pack install --source ./code-polishy-example
code-polishy pack rootInstallation prints the exact name, semantic version, and content digest to add
under the target configuration's packs array. It performs no download and
executes no pack code. See code-polishy docs read adding-a-language for the
manifest, protocol, trust, and contributor contracts.
A release carries no source checkout, no history, and no build inputs. Installing does not modify the checkout it was built from.
The manifest answers two different questions with two different digests.
releaseDigest names which reviewed commit, which version, which capabilities,
and the exact version of every executable the release carries. Nothing host
specific contributes to it, so Linux, macOS, and Windows releases from the same
commit carry the same value and a target lock can require an exact release
without naming a platform. Their entry lists and contentDigest values differ
because executable formats and other carried bytes are host specific.
contentDigest and the per-entry list name the exact installed bytes on this
host. Every installed file contributes its SHA-256. On hosts that support
release symlinks, every link contributes its exact target: the bundle is linked
together by pnpm's isolated linker, so retargeting one link would otherwise
swap the code a release runs without changing an installed file.
Each manifest version has an exact schema and identity calculation. The engine accepts only its own version. The stable launcher keeps explicit readers for installed manifest versions 2 through 5 so installing a newer release does not strand repositories still locked to an older one. It verifies each older release using that version's original fields and never invents evidence added by a later schema.
Manifest version 4 adds tools.python for the carried CPython
3.12.13+20260728 runtime and tools.vulture for Vulture 2.16. Those fields
contribute only to version 4 identities; a version 3 release remains bound to
the smaller tool inventory it originally recorded. The target configuration
version is a separate contract.
Manifest version 5 adds tools.packaging for PyPA packaging 26.3. That
field contributes only to version 5 identities; launchers continue validating
older manifests against the exact smaller inventory of their own version.
Manifest version 6 adds capabilityCatalogSha256, the SHA-256 of the shipped
docs/capabilities.json. This digest contributes to the host-independent
release identity and must match the catalog's regular-file entry. Discovery
validates the selected catalog against the repository's exact lock; another
installed release or a modified catalog cannot supply its capabilities. Older
releases with no authenticated catalog report discovery evidence unavailable.
code-polishy release-manifest verify --root <release-dir> recomputes the
installed entry evidence. A release that was truncated, changed after
installation, or copied from another host fails verification and is reinstalled
rather than executed. The launcher makes the same native judgment before every
run on Linux, macOS, and Windows.
Every policy-owned carried-Python command uses isolated mode and disables
bytecode generation at one shared command boundary. Version probes, Vulture,
quality checks, architecture checks, doctor, and gates therefore cannot create
__pycache__ or .pyc entries inside the content-addressed release. Installed
release acceptance runs these commands sequentially and verifies the complete
manifest afterward, including rejection of any added entry. Writable caches,
homes, temporary files, and target output remain outside the release tree.
Before it stages anything, the installer asks every tool the release will carry
what version it is and requires the answer to be the version the checked-in pin
beside it names — the Go toolchain, Node, pnpm, ShellCheck, staticcheck,
govulncheck, OSV-Scanner, Ruff, PyPA packaging, Vulture, ty, and carried
CPython. The manifest records those identities, and a present file and a byte
inventory cannot show that a local tool cache holds the version the manifest
would claim. The two Go analyzers are read out of their binaries with the pinned
toolchain rather than asked: govulncheck -version contacts the vulnerability
database, and installation reaches no network. The engine and the launcher are
built here from the reviewed commit rather than acquired, so what they are is
the source revision the manifest already records.
The installer verifies the CPython archive before extraction and the exact
packaging 26.3 and Vulture 2.16 wheels before unpacking their pure-Python
packages into that carried runtime. It removes pip and ensurepip and does
not use a target .venv or target Python installation for either package.
The installer stages a complete release, verifies the staged tree against the manifest it just wrote, and only then moves it into place under one name. A previously installed release is untouched until a verified replacement is ready.
An installation that ends after staging has begun — a step that fails, or an interrupt — removes its own partial tree. A staging tree is never a release a target could run, because no lock can name one, but a release store holds only complete releases.
Before the manifest is written, the installer searches the staged tree for
retired distribution mechanisms that must never reach a target: a
check_policy.sh or .gitmodules entry, a checkout, a retired workflow wrapper,
or policy-owned text that still tells a target to run a submodule command. A
release is the whole Code Polishy interface a target gets, so one of those
reaching a target through a template, canonical guidance, or workflow script is
an installation failure rather than something to find later. The sealed
runtime and bundle are not searched for Code Polishy's own
retired commands; they are third-party bytes, and the bundle inventory and
manifest govern them.
Release directories are named <version>-<releaseDigest>, so releases from
different reviewed commits coexist and each target selects the exact one it
requires. Reinstalling a commit whose release is already installed and verified
keeps the installed bytes rather than replacing them.
A published target repository names the release and complete native archive set
it requires in .code-polishy.lock.json:
{
"lockVersion": 2,
"codePolishyVersion": "0.27.2",
"releaseDigest": "…",
"features": ["javascript-bundle"],
"publication": {
"indexUrl": "https://example.invalid/code-polishy-release-index.json",
"indexSha256": "…",
"archives": [
{
"host": "darwin-arm64",
"url": "https://example.invalid/code-polishy-0.27.2-darwin-arm64.zip",
"sha256": "…",
"size": 123
}
]
}
}The real archives value contains five structured entries rather than the
single example entry above. It carries no credential, channel, or
fallback version. The publication-index digest and copied archive digests are
reviewed repository authority, so the same lock selects one release across all
supported hosts. This authenticates acquired bytes relative to the lock; it is
not authenticated builder provenance.
lock --index URL --sha256 DIGEST verifies that the index describes the
executing installed release and writes this v2 lock without redownloading an
archive. Every new lock requires publication metadata. Move between v2 releases
with the two-phase upgrade:
code-polishy upgrade plan --index <https-index-url> --sha256 <index-sha256>
code-polishy upgrade apply --plan <reported-plan-path>Planning verifies the selected index, installs the host candidate, authenticates
the capability delta, and compares outgoing and incoming diagnostics without
changing repository authority. Applying the plan revalidates its evidence and
replaces managed guidance, wrappers, ignore rules, and the lock in one
rollback-capable transaction with the lock last. New errors can be acknowledged
without fixing them by adding --accept-new-findings. Neither phase edits
application source, runs tests, or runs a merge gate.
When the outgoing release has a v2 lock but predates upgrade, first install the
pinned current-host candidate with the existing local bundle workflow, then
invoke both phases through that incoming release binary directly. The outgoing
lock and guidance still govern until apply replaces the lock; the incoming
release governs afterward.
Current releases do not parse or migrate v1 locks. For a repository still using
one, an AI agent should preserve the working tree, install the exact published
incoming release, and obtain its publication-index URL and SHA-256. It should
then preserve the old lock through Git or a temporary file outside the
repository, remove .code-polishy.lock.json, and invoke the incoming release
directly:
<incoming-code-polishy> lock --index <https-index-url> --sha256 <index-sha256>
<incoming-code-polishy> agents syncThe agent then reviews the intervening changelog and target configuration, performs the checks selected for the upgrade, and commits the v2 lock with the managed adoption updates. This is a deliberate authority replacement, not an automated migration; Git retains the rollback path.
<prefix>/bin/code-polishy is the launcher, and it is the only Code Polishy
command a target runs. It reads the target's lock, resolves the one release that
lock names, and confirms that release records the same version, digest, and
required features and was built for this host.
It then verifies the release itself before running any of it. It recomputes the release the manifest describes from the commit, version, capabilities, and pins recorded in it, so a release cannot be installed or copied under another release's name; it reads every recorded file and confirms the recorded bytes, reads every recorded link and confirms the recorded target, and refuses anything installed under the release that the release does not record. Only then does it hand the release the target and the caller's arguments. The engine reads the schema, templates, pinned versions, workflow scripts, and sealed JavaScript bundle beside it, so checking the engine binary alone would not be checking what runs, and verifying at installation time cannot answer what a release is made of now.
There is no channel, version range, newest-wins rule, or fallback release.
Ordinary launch never downloads. A target that names a release this host does
not have is told to run its repository wrapper setup; it is never given a
different release.
--policy-root is refused, because the lock decides which release runs.
Running a release binary directly does not get around the lock: an installed release refuses to govern a repository whose lock names another release, or a repository with no lock at all. The exceptions are bounded bootstrap and upgrade commands plus read-only version, help, and packaged documentation.
An installed release is not a supported development environment, and the source
runner in this repository's bin/ is not a supported target installation. It is
not a release, so no target lock can name it.
This repository checks in its own .code-polishy.lock.json, so the release it
produces is exercised against a real target rather than only against fixtures:
the launcher resolves that release, verifies every recorded byte, and governs
this repository with the pinned tools the release carries.
A release digest names the commit it was built from, so this repository's lock
names the release of an earlier reviewed commit and never of the commit that
carries the lock: writing the lock changes the tree, and the tree it changes
would build a different release. Refresh it the way any target does — install a
release from the reviewed commit, run lock in this checkout from that release,
and commit the lock as its own reviewed change — and keep that release installed
for as long as the lock names it, because the launcher resolves that one and no
other.
Development still runs the source runner. This repository's AGENTS.md is the
same exact canonical file every target receives, so the installed release
governs the checkout without a guidance exception. agents sync replaces that
whole file when a later locked release changes the canonical contract and
repairs the root .gitignore rules that keep report and test artifacts
workspace-local.
Self-hosting covers one target shape: a Go repository that also owns the sealed
bundle's source. ./scripts/test-installed-release.sh covers the others. It
builds disposable repositories — Go with no JavaScript, a pnpm application, a
pnpm workspace, TypeScript, and React — gives each the lock this checkout
requires, and governs them with the installed launcher. The Go target also runs
the complete non-documentation flow: pre-coding intent capture, review
preparation, red/green proof, finalization, checkpoint, and merge. It verifies
requested and preserved changes and confirms that an unintended change blocks.
Each target is first brought to a clean pass, then given one defect and
required to produce the exact finding for it, because a pass that no defect can
disturb is a check that did not run. The script installs nothing and reaches no
network; it needs an installed release named by the selected lock. --prefix
selects the release store, and --lock can select a temporary candidate lock
without changing this repository's checked-in lock.
What it proves is the release the selected lock names. By default that is this checkout's lock, which must be refreshed before validating a newly published release. A temporary lock can name a clean installed candidate before the public cutover. The script is not part of the ordinary test suite because a release store is outside the checkout and CI normally builds the engine from source.