Repository navigation
Releases
Codifide Harness v3.2.1
Changelog
Versions follow semantic versioning. The version is in VERSION. Pin installs to a tag.
[3.2.1] - 2026-11-12
A fix to the example CI workflow. The steering files, hook files, installer and the four enforcement scripts are unchanged.
Fixed
templates/enforcement/workflow.example.yml: onpull_request,actions/checkoutchecked out GitHub's syntheticrefs/pull/N/mergecommit. That commit has noGenerated-ByorReview-Leveltrailers, socheck-review-level.shfailed every PR that touched a governance file, even withcodifide-enforcer-change-approvedapplied. The checkout now usesref: ${{ github.event.pull_request.head.sha || github.sha }}. Found on a downstream PR, where the same one-line change made the check pass. If you installed 3.2.0, the installer will not overwrite your workflow (it is a policy file): add the line by hand.
Changed
- The whitepaper is retitled "Codifide Harness: How We Govern AI-Powered Development in Healthcare" (it no longer uses the Stage-Gate® mark as its headline); citations in
articles/updated. README.md: install commands name 3.2.1; the Kiro exit-2 check and the signed tag are stated.templates/enforcement/README.md: the Kiro row now records one manual check in the Kiro IDE on macOS, where exit 2 blocked a write to a protected path and allowed a write elsewhere. Also: the guard fails closed on every write if thepython3onPATHcannot run.
Verification status
- The enforcement suite has a new check that the example checks out the PR head; it fails against the 3.2.0 file. The fix has not run on GitHub from this repository; it ran on two downstream repositories (the site and the private swarm), where governance PRs then passed.
- The
v3.2.1tag is the first signed tag (SSH key).SHA256SUMSis not separately signed.
[3.2.0] - 2026-11-11
A local installer, an upgrade and an uninstall path, and release automation. The steering files, the hook files and the four enforcement scripts are unchanged from 3.1.0; this release adds the way to get them into a repository and to keep them current.
Added
install.sh: copies a pinned release into a repository. Dry run by default (--applywrites). Per-host targets:kiro,claude,cursor,copilot,codex. Refuses to run unless it is a clean checkout of the tag that matchesVERSION, or an unpacked release tarball whoseRELEASEfile names that tag (--i-know-this-is-unpinnedoverrides and is recorded). Writes.codifide/harness-versionand.codifide/harness-manifest(a hash for every file it installed). Uses no network, makes no commit, and does not change git configuration.- Policy files are never overwritten:
.codifide/immutable-paths,.codifide/allowed-licenses, the enforcement workflow,CLAUDE.md,AGENTS.mdand the Copilot instructions file are created only when absent, and a merge snippet is printed when they exist..claude/settings.jsonis never written; the snippet is printed. install.sh upgrade: re-run from a newer tag. Shows a diff, replaces only files that still match the manifest, stops (writing nothing) on a locally edited harness file unless--force, and removes files the new release no longer ships if you have not edited them.install.sh uninstall: manifest-driven; removes only files that still match the recorded hash, leaves everything else, and prunes directories it emptied.- Every path (from the release and from the manifest in your repository) is checked before any write: relative, from a fixed allow-list, no symbolic link on the way. A write failure rolls back everything the run wrote.
tools/build-release.shand.github/workflows/release.yml: build the tarball (git archiveof the tag plus aRELEASEfile) andSHA256SUMSon a pushedv*tag, run both test suites first, signSHA256SUMSonly if aRELEASE_SIGNING_KEYsecret exists, and create a DRAFT release. The workflow uses no third-party actions and nopull_requesttriggers.tests/test-installer.sh: the installer suite (see the README for the count).
Verification status (stated plainly)
- Verified by the installer suite, in throwaway repositories on macOS with bash 3.2: dry run writes nothing, the pin rules, each host's file layout, no-clobber, manifest hashes, idempotent re-run, upgrade, uninstall (a pristine tree is restored byte for byte), path-traversal, symlink and hostile-manifest cases, no network client or git write is called, rollback after a failed write, and the release build and an install from the built tarball.
- NOT verified end to end: any host actually loading what the installer wrote. Kiro
inclusion: autoloading and exit-2 blocking, Claude Code readingCLAUDE.mdand the merged hook, Cursor loading the.mdcrules, Copilot reading its instructions file, and Codex readingAGENTS.mdwere not run. The Cursor output is checked against the converter, not against Cursor. - The release workflow ran once on GitHub for 3.2.0: both suites, the build and the checksum passed; the release step failed (see below). No release has been signed; the 3.1.0 release is unsigned and this one stays unsigned until a signing key is configured.
- A cross-vendor review (gpt-6.1-sol) of the installer found 3 major and 5 minor reproducible issues; all are fixed with regression tests: a forged manifest line can no longer make a policy or stub file deletable, a failed backup stops and rolls back, a hand-written
RELEASEfile no longer vouches for a dirty git checkout, files are re-checked just before each write, the temporary file is created withmktempand verified, release files are not read through links, and the release workflow scopes the signing key and token to their steps and removes the key file on failure. The fixes themselves have not been re-reviewed. - Release: the release workflow's final step failed on its first run (
gh release createhad no git remote because the workflow checks out without a remote); the 3.2.0 assets were built locally from the tag withtools/build-release.sh. Fixed after the tag by passing--repo.
Not built (by decision)
Host plugins, a Kiro Power, an MCP server, a VS Code extension, npm or pip packages, curl | bash, auto-update, telemetry, a composite Action.
[3.1.0] - 2026-11-11
Security and distribution hardening of the enforcement layer. Driven by a read-only assessment and a Grok 4.7 cold adversarial review; every finding is either fixed with a regression test or stated as a documented limit in templates/enforcement/README.md.
Changed (behaviour you may notice)
check-immutable-paths.sh: the verifier approval (CODIFIDE_VERIFIER_CHANGE_APPROVED_BY) no longer waives edits to.codifide/,.github/workflows/,CODEOWNERS,.kiro/hooks/or.claude/settings.json. Those needCODIFIDE_ENFORCER_CHANGE_APPROVED_BY.check-licenses.sh: reads the policy from the base branch (--base REF,CODIFIDE_BASE, ororigin/main). Falls back to the working tree with a warning only when no base ref exists and none was requested. Pass--basein CI. CycloneDX entries with several licenses are read as AND.ORnow means either side may be chosen.check-review-level.sh:docs/files are R1 only with a document extension; binary files count 100 lines each toward the size rule; more migration, schema, Terraform, session, oauth, jwt, password, login, middleware, rbac, acl, iam and policy paths raise the floor; matching is case-insensitive.- Guard: empty input and an unreadable list now block.
Fixed
- Guard allowed a case variant of a protected path (
Verifiers/check.py) on case-insensitive filesystems. - Guard dropped any string of 1,024 characters or more, so a long
a/../path reached a protected file. - Guard dropped a path ending in a newline.
- Guard did not resolve hard links to protected files.
- Any unexpected guard exit code other than 2 was a possible "allow"; an EXIT trap now converts it to 2, and the hook files run
bash <guard> || exit 2. - CI check missed protected paths with non-ASCII or newline characters in the name (git quotes them), a file named like a protected directory, case variants, and symlinks added into protected paths.
- License check: policy came from the PR's own tree;
*in a license expression expanded to file names; a policy line of*allowed everything;MIT Licenseand similar names were rejected;A OR Bwas treated as AND; SPDX tag-value expressions were truncated to the first word. - Review-level check: wrong file names for git-quoted paths; R1 allowlist accepted code under
docs/. - Guard resolved
..before symlinks (src/link/../check.py), judged the target of a symlink instead of its own name (deletingverifiers/link.py), ignored a hard link whose other name lives outside the repo, allowed a recursive delete of an ancestor of a protected directory, and dropped any string with an interior newline. Symlinks are now resolved component by component and every candidate is checked three ways; interior-newline and NUL-truncated strings and JSON object keys are checked too. - CI immutable check: a workflow or other enforcement-path edit was not reported unless the list named it; a symlink to another symlink (or through a directory symlink) escaped the one-hop check. The tree is now followed across any number of hops.
- Review-level check: a root commit (orphan history merged in) was never checked (
git diff-tree --root). - License check: nested CycloneDX components were skipped; partial parser output was accepted; an SPDX package with no license line was dropped;
MIT WITHwith no exception id was accepted. - Iteration 3 review (gpt-6.1-sol), all with regression tests: a symlink into
.codifide/was waived by the verifier approval (now classified by its target); a symlink target differing only in case from a directory symlink escaped the CI check; NFD spellings of a protected NFC file name passed the guard; a hard link to a newline...
Codifide Harness v3.2.0
This release is NOT cryptographically signed. Verify the download with SHA256SUMS (shasum -a 256 -c SHA256SUMS). Signed releases start once a signing key is configured.
What's new in 3.2.0
A local installer plus upgrade and uninstall paths. The steering files, hook files and four enforcement scripts are unchanged from 3.1.0.
install.sh: copies this pinned release into a repository. Dry run by default (--applywrites). Hosts:kiro,claude,cursor,copilot,codex. Refuses to run unless it is a clean checkout of a matching tag or an unpacked release tarball. Writes.codifide/harness-versionand.codifide/harness-manifest. No network, no commits, no git config changes.- Policy files (
.codifide/immutable-paths,CLAUDE.md,AGENTS.md, the enforcement workflow and others) are created only when absent..claude/settings.jsonis never written; merge snippets are printed instead. install.sh upgradeandinstall.sh uninstall: manifest-driven; they only touch files that still match the recorded hash.tools/build-release.shand a tag-triggered release workflow.
Verification status
- Installer suite: 367 checks pass; enforcement suite: 245 cases pass (macOS, bash 3.2).
- One cross-vendor review (gpt-6.1-sol) found 11 issues; 10 were reproduced, and 8 of those (3 major) are fixed with regression tests. A second reviewer approved the fixes; they have not had a second cold external review.
- NOT verified end to end: any host loading what the installer writes (Kiro, Claude Code, Cursor, Copilot, Codex).
- The release workflow's final step failed on its first run (
gh release createhad no git remote). These assets were built locally from thev3.2.0tag withtools/build-release.sh; the workflow fix lands after this tag.
Codifide Harness 3.1.0
Security and distribution hardening of the enforcement layer. Driven by a read-only assessment and a Grok 4.7 cold adversarial review; every finding is either fixed with a regression test or stated as a documented limit in templates/enforcement/README.md.
Changed (behaviour you may notice)
check-immutable-paths.sh: the verifier approval (CODIFIDE_VERIFIER_CHANGE_APPROVED_BY) no longer waives edits to.codifide/,.github/workflows/,CODEOWNERS,.kiro/hooks/or.claude/settings.json. Those needCODIFIDE_ENFORCER_CHANGE_APPROVED_BY.check-licenses.sh: reads the policy from the base branch (--base REF,CODIFIDE_BASE, ororigin/main). Falls back to the working tree with a warning only when no base ref exists and none was requested. Pass--basein CI. CycloneDX entries with several licenses are read as AND.ORnow means either side may be chosen.check-review-level.sh:docs/files are R1 only with a document extension; binary files count 100 lines each toward the size rule; more migration, schema, Terraform, session, oauth, jwt, password, login, middleware, rbac, acl, iam and policy paths raise the floor; matching is case-insensitive.- Guard: empty input and an unreadable list now block.
Fixed
- Guard allowed a case variant of a protected path (
Verifiers/check.py) on case-insensitive filesystems. - Guard dropped any string of 1,024 characters or more, so a long
a/../path reached a protected file. - Guard dropped a path ending in a newline.
- Guard did not resolve hard links to protected files.
- Any unexpected guard exit code other than 2 was a possible "allow"; an EXIT trap now converts it to 2, and the hook files run
bash <guard> || exit 2. - CI check missed protected paths with non-ASCII or newline characters in the name (git quotes them), a file named like a protected directory, case variants, and symlinks added into protected paths.
- License check: policy came from the PR's own tree;
*in a license expression expanded to file names; a policy line of*allowed everything;MIT Licenseand similar names were rejected;A OR Bwas treated as AND; SPDX tag-value expressions were truncated to the first word. - Review-level check: wrong file names for git-quoted paths; R1 allowlist accepted code under
docs/. - Guard resolved
..before symlinks (src/link/../check.py), judged the target of a symlink instead of its own name (deletingverifiers/link.py), ignored a hard link whose other name lives outside the repo, allowed a recursive delete of an ancestor of a protected directory, and dropped any string with an interior newline. Symlinks are now resolved component by component and every candidate is checked three ways; interior-newline and NUL-truncated strings and JSON object keys are checked too. - CI immutable check: a workflow or other enforcement-path edit was not reported unless the list named it; a symlink to another symlink (or through a directory symlink) escaped the one-hop check. The tree is now followed across any number of hops.
- Review-level check: a root commit (orphan history merged in) was never checked (
git diff-tree --root). - License check: nested CycloneDX components were skipped; partial parser output was accepted; an SPDX package with no license line was dropped;
MIT WITHwith no exception id was accepted. - Iteration 3 review (gpt-6.1-sol), all with regression tests: a symlink into
.codifide/was waived by the verifier approval (now classified by its target); a symlink target differing only in case from a directory symlink escaped the CI check; NFD spellings of a protected NFC file name passed the guard; a hard link to a newline-named protected file passed (find output was newline-split); license entries were joined without parentheses (MIT OR GPLANDGPLpassed); aLicensevalue on a later csv row was dropped as a header; an SPDXConcludedlicense was ignored afterDeclared; a merge resolved with--ourshad an empty combined diff and so an R1 floor; an approval marker inside a file containing a NUL byte was not scanned; the example workflow had the license step commented out. - Iteration 4 review (gpt-6.1-sol), all with regression tests: a relative path was resolved against the repository root, not the hook's working directory (
check.pyfromverifiers/passed), so relative paths are now judged against the root, the hook cwd and the payload cwd, and the hook metadatacwdis no longer treated as a write target;CODIFIDE_ROOTcould point the guard at a decoy list, so a root that is not the real top level now blocks; an NFD alias of a protected NFC name passed the CI check on git that does not precompose, so non-ASCII changed paths are matched in both forms; a plain-list license row with a missing license was dropped, so it is now a malformed report (exit 2) and SPDX tag-value lines are no longer read as list rows. - Iteration 5 review (gpt-6.1-sol), all with regression tests: the guard honoured
GIT_DIR/GIT_WORK_TREE, so a decoy work tree chose the list that was read (allGIT_*variables are now dropped); a delete of/was allowed (an ancestor of the repository is now blocked); a payloadcwdsuch assrc/link/..was normalised before the symlink was resolved;docs/CODEOWNERSwas not an enforcer path;.claude/,.cursor/and.codex/agent settings could be changed at R2 (now governance, R3); CycloneDXmetadata.component.componentswas not scanned; a plain-list row with an empty package name was dropped; a plain row mixed into an SPDX tag-value report was ignored (now exit 2). - Iteration 6 (a bounded fix pass after the fifth gpt-6.1-sol review; these fixes are not re-reviewed), all with regression tests: the three CI scripts now drop every
GIT_*variable, soGIT_DIR/GIT_WORK_TREEcannot point them at a decoy repository; a symlink target or file name ending in a newline lost the newline in$(...)(guard and CI), so such a link bypassed a protected*?pattern (results now travel in variables,readlink -n, sentinel for decoded values); the CI symlink traversal now folds NFC/NFD spellings of a path component (fail closed withoutpython3); the guard's hard-link and directory scans block whenfindcannot read part of the repository; an SPDX<text>comment could overwrite aPackageLicenseConcluded/Declaredvalue; CycloneDX nestedcomponentsthat is not an array was silently skipped (now exit 2); a symlink named.codifide,.kiro,.claude,.cursor,.codexor.githubonly got R2 (the directory entries themselves are now R3); theworkflow_okdocumentation test matched words anywhere (comments included) and now requiresrun:steps that execute each script. - Stale text: the case count, the gate count in CONTRIBUTING and the whitepaper, the old version footer, a counsel marker in CONTRIBUTING and NOTICE, unqualified coverage and timing claims in the whitepaper and an article.
Added
templates/hooks/real hook files (Kiro x4, Claude Code guard).templates/cursor/to-mdc.shCursor.mdcconverter (Cursor ignores plain.mdrules).templates/enforcement/workflow.example.ymlcomplete workflow: trusted base copies, first-run bootstrap, push tripwire, two scoped labels.VERSION,CHANGELOG.md,.gitattributes(LF endings), SPDX headers on scripts.- Documented limits and compensating controls; Windows/WSL and
jq/python3prerequisites. - Regression tests for each fix (245 cases), and documentation-consistency tests.
- README "Scope and limits": the guard is a seatbelt, the base-branch CI checks plus branch protection are the gate, one table of documented limits, and a statement that the scripts are defense in depth, not a proof.
Verification. shasum -a 256 -c SHA256SUMS. This tag is annotated but not cryptographically signed; signed tags start with the next release.
Enforcement suite: 245 cases, ALL PASS (bash 5 and bash 3.2).