diff --git a/CHANGELOG.md b/CHANGELOG.md index 4aebd7a..68251c4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ CodeTruss CLI follows semantic versioning. Release artifacts and their SHA-256 checksums are published at . -The current public release is [v0.2.51 on GitHub](https://github.com/CodeTruss/codetruss-cli/releases/tag/v0.2.51), +The current public release is [v0.2.52 on GitHub](https://github.com/CodeTruss/codetruss-cli/releases/tag/v0.2.52), distributed from . The npm `latest` tag is still [`@codetruss/cli@0.2.50`](https://www.npmjs.com/package/@codetruss/cli/v/0.2.50): @@ -16,6 +16,75 @@ were superseded before distribution. No unreleased changes. +## 0.2.52 — 2026-08-08 + +Three corrections to published artifacts. No behaviour changes. + +- **`--yes` never required `--allow`, and this README said it did.** The + sentence read: "Non-interactive `--yes` setup requires explicit `--allow` + values." `resolveAllowGlobs` does close to the opposite. Given no explicit + value it adopts every conventional source directory that exists at the + repository root — `src`, `app`, `apps`, `packages`, `lib`, `components`, + `server`, `client`, `public`, `test`, `tests`, `e2e`, `spec`, `docs` — as + `/**`, prints what it adopted, and continues. It refuses only when none + of the fourteen exist. `codetruss setup --yes --hooks none` on a repository + holding `src/` and `tests/` exits 0 having adopted `src/**, tests/**`. + + A safety claim we overstate is the worst direction to be wrong in. That + sentence invited a reader to believe an unattended run could not adopt a scope + they had not chosen, and it can. The behaviour itself is deliberate and stays: + an unattended run on an ordinary repository should end up protected rather + than halted over glob syntax, the adopted list is printed so the decision + stays auditable, no repository-wide glob is ever adopted, and the genuinely + dangerous decision — trusting repository verification commands — is still + withheld without `--trust-verify`. What was false was the documentation, so + the documentation is what changed, here and in the repository README and + `docs/codetruss-cli-guide.md`, which each carried a version of the same claim. + + The corrected text also names the two ways a detected scope goes wrong. It can + be wider than intended. It is also blind to a source directory outside that + list: on `sindresorhus/ky`, whose sources live in `source/`, `--yes` adopts + `test/**` alone and leaves the entire source tree out of scope, so ordinary + changes read as scope drift. Pass `--allow` whenever the scope matters; + explicit values are used verbatim and nothing is detected. + +- **Correction to the 0.2.51 entry: the commit block is real, but uninstalling + was not the only escape.** That entry said: "Because `codetruss setup` + installs a pre-commit hook, FAILED also blocked the next `git commit`, with + uninstalling as the only escape." A review of this release could not reproduce + the block and the claim was nearly retracted whole. It does reproduce. On a + clean clone of `sindresorhus/ky` at `3419113` with published 0.2.50, after + `codetruss setup --yes --allow "source/**" --allow "test/**"`, appending one + comment line to either `source/index.ts` or `source/utils/merge.ts` and + committing it prints `CodeTruss FAILED: commit blocked`, exits non-zero, and + leaves `HEAD` unmoved. Both configurations block. + + The failed reproduction was a `PATH` artifact, and it is one users will hit. + The installed hook invokes bare `codetruss`, so whichever build resolves first + on `PATH` decides the verdict. With a stale global 0.2.28 resolving ahead of + the 0.2.50 under test, the identical staged change prints `REVIEW_REQUIRED` + and the commit lands with exit 0 — an older CLI, predating the behaviour, + quietly answering for the one being tested. `codetruss setup` already warns + about this by name, and the warning deserved more weight than it got. + + What was genuinely wrong is narrower and is ours: `git commit --no-verify` + escapes a blocking hook, and it did on 0.2.50. Uninstalling was never the only + way out. The 0.2.51 artifact is published and immutable, so its text stands as + shipped and this entry is the correction. + +- **The scoring model has a reviewable diff again.** + `packages/analyzer-engine/src/scoring.ts` carried two raw NUL bytes as map-key + separators inside template literals, so git classified the file as binary. + 0.2.47's rewrite of `deduct()` — adding `dedupeByLocation` and the logarithmic + `occurrenceFactor` decay — therefore rendered as `Bin 5166 -> 8676 bytes, 0 + additions, 0 deletions`. The model behind every number we put in front of a + customer could change with nothing to read. Both separators are now written as + the six-character escape. The runtime strings are identical, the analyzer + suites pass unchanged, and `dist/cli.cjs` built from the corrected source is + byte-for-byte the bundle built from the old source, so no behaviour in this + release turns on it. It was the last tracked source file in the repository + carrying raw NUL bytes. + ## 0.2.51 — 2026-08-08 - **A file CodeTruss could not parse reported the user's change as FAILED.** On diff --git a/packages/analyzer-engine/src/scoring.ts b/packages/analyzer-engine/src/scoring.ts index 57d2c15..e68bc73 100644 Binary files a/packages/analyzer-engine/src/scoring.ts and b/packages/analyzer-engine/src/scoring.ts differ diff --git a/packages/cli/CHANGELOG.md b/packages/cli/CHANGELOG.md index 6553763..6e930fa 100644 --- a/packages/cli/CHANGELOG.md +++ b/packages/cli/CHANGELOG.md @@ -5,6 +5,75 @@ checksums are published at /**`, prints what it adopted, and continues. It refuses only when none + of the fourteen exist. `codetruss setup --yes --hooks none` on a repository + holding `src/` and `tests/` exits 0 having adopted `src/**, tests/**`. + + A safety claim we overstate is the worst direction to be wrong in. That + sentence invited a reader to believe an unattended run could not adopt a scope + they had not chosen, and it can. The behaviour itself is deliberate and stays: + an unattended run on an ordinary repository should end up protected rather + than halted over glob syntax, the adopted list is printed so the decision + stays auditable, no repository-wide glob is ever adopted, and the genuinely + dangerous decision — trusting repository verification commands — is still + withheld without `--trust-verify`. What was false was the documentation, so + the documentation is what changed, here and in the repository README and + `docs/codetruss-cli-guide.md`, which each carried a version of the same claim. + + The corrected text also names the two ways a detected scope goes wrong. It can + be wider than intended. It is also blind to a source directory outside that + list: on `sindresorhus/ky`, whose sources live in `source/`, `--yes` adopts + `test/**` alone and leaves the entire source tree out of scope, so ordinary + changes read as scope drift. Pass `--allow` whenever the scope matters; + explicit values are used verbatim and nothing is detected. + +- **Correction to the 0.2.51 entry: the commit block is real, but uninstalling + was not the only escape.** That entry said: "Because `codetruss setup` + installs a pre-commit hook, FAILED also blocked the next `git commit`, with + uninstalling as the only escape." A review of this release could not reproduce + the block and the claim was nearly retracted whole. It does reproduce. On a + clean clone of `sindresorhus/ky` at `3419113` with published 0.2.50, after + `codetruss setup --yes --allow "source/**" --allow "test/**"`, appending one + comment line to either `source/index.ts` or `source/utils/merge.ts` and + committing it prints `CodeTruss FAILED: commit blocked`, exits non-zero, and + leaves `HEAD` unmoved. Both configurations block. + + The failed reproduction was a `PATH` artifact, and it is one users will hit. + The installed hook invokes bare `codetruss`, so whichever build resolves first + on `PATH` decides the verdict. With a stale global 0.2.28 resolving ahead of + the 0.2.50 under test, the identical staged change prints `REVIEW_REQUIRED` + and the commit lands with exit 0 — an older CLI, predating the behaviour, + quietly answering for the one being tested. `codetruss setup` already warns + about this by name, and the warning deserved more weight than it got. + + What was genuinely wrong is narrower and is ours: `git commit --no-verify` + escapes a blocking hook, and it did on 0.2.50. Uninstalling was never the only + way out. The 0.2.51 artifact is published and immutable, so its text stands as + shipped and this entry is the correction. + +- **The scoring model has a reviewable diff again.** + `packages/analyzer-engine/src/scoring.ts` carried two raw NUL bytes as map-key + separators inside template literals, so git classified the file as binary. + 0.2.47's rewrite of `deduct()` — adding `dedupeByLocation` and the logarithmic + `occurrenceFactor` decay — therefore rendered as `Bin 5166 -> 8676 bytes, 0 + additions, 0 deletions`. The model behind every number we put in front of a + customer could change with nothing to read. Both separators are now written as + the six-character escape. The runtime strings are identical, the analyzer + suites pass unchanged, and `dist/cli.cjs` built from the corrected source is + byte-for-byte the bundle built from the old source, so no behaviour in this + release turns on it. It was the last tracked source file in the repository + carrying raw NUL bytes. + ## 0.2.51 — 2026-08-08 - **A file CodeTruss could not parse reported the user's change as FAILED.** On diff --git a/packages/cli/README.md b/packages/cli/README.md index aabfe82..a3b8556 100644 --- a/packages/cli/README.md +++ b/packages/cli/README.md @@ -25,8 +25,18 @@ pre-commit plus Claude/Codex hooks, and runs a health check. It never defaults to a repository-wide allow rule, never treats `--yes` as command trust, and never uploads anything. Codex asks for one final project-hook approval in `/hooks`. -Non-interactive `--yes` setup requires explicit `--allow` values and still -requires `--trust-verify` before it can trust detected repository commands. +Non-interactive `--yes` setup does not require `--allow`. With no explicit +value it adopts every conventional source directory that exists at the +repository root — `src`, `app`, `apps`, `packages`, `lib`, `components`, +`server`, `client`, `public`, `test`, `tests`, `e2e`, `spec`, `docs` — as +`/**`, prints what it adopted, and continues; it refuses only when none of +them exist, and then asks for an explicit `--allow`. So an unattended run gets a +scope derived from the repository rather than one you chose: possibly wider than +you want, and blind to a source directory outside that list (`source/**`, for +one), which makes ordinary changes read as out of scope. Pass `--allow` whenever +the scope matters — explicit values are used verbatim and nothing is detected. +`--trust-verify` is still required before `--yes` can trust detected repository +commands. A 14-day local-only design-partner cohort is open without repository access, an account, or receipt sync. The consent request is: diff --git a/packages/cli/package.json b/packages/cli/package.json index 2699234..3a26b2d 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,6 +1,6 @@ { "name": "@codetruss/cli", - "version": "0.2.51", + "version": "0.2.52", "description": "Local-first scope, quality, and verification receipts for coding agents", "license": "SEE LICENSE IN LICENSE", "type": "module", diff --git a/packages/cli/test/unparsed-file-coverage.test.ts b/packages/cli/test/unparsed-file-coverage.test.ts index b258209..3a3474b 100644 Binary files a/packages/cli/test/unparsed-file-coverage.test.ts and b/packages/cli/test/unparsed-file-coverage.test.ts differ diff --git a/public/downloads/codetruss-cli-0.2.52.sbom.cdx.json b/public/downloads/codetruss-cli-0.2.52.sbom.cdx.json new file mode 100644 index 0000000..280aaf0 --- /dev/null +++ b/public/downloads/codetruss-cli-0.2.52.sbom.cdx.json @@ -0,0 +1,170 @@ +{ + "$schema": "https://cyclonedx.org/schema/bom-1.6.schema.json", + "bomFormat": "CycloneDX", + "serialNumber": "urn:uuid:4c318a44-4d62-55be-95fe-0240ae7f3d90", + "specVersion": "1.6", + "version": 1, + "metadata": { + "component": { + "type": "application", + "bom-ref": "pkg:npm/%40codetruss/cli@0.2.52", + "name": "@codetruss/cli", + "version": "0.2.52", + "description": "Local-first scope, quality, and verification receipts for coding agents", + "licenses": [ + { + "license": { + "name": "CodeTruss CLI Proprietary License" + } + } + ], + "purl": "pkg:npm/%40codetruss/cli@0.2.52" + }, + "properties": [ + { + "name": "codetruss:distribution", + "value": "single-file JavaScript bundle" + }, + { + "name": "codetruss:runtimeDependencies", + "value": "0" + } + ] + }, + "components": [ + { + "type": "library", + "bom-ref": "pkg:npm/%40codetruss/analyzer-engine@0.1.0", + "name": "@codetruss/analyzer-engine", + "version": "0.1.0", + "licenses": [ + { + "license": { + "name": "CodeTruss CLI Proprietary License" + } + } + ], + "purl": "pkg:npm/%40codetruss/analyzer-engine@0.1.0", + "properties": [ + { + "name": "codetruss:bundled", + "value": "true" + } + ] + }, + { + "type": "library", + "bom-ref": "pkg:npm/balanced-match@4.0.4", + "name": "balanced-match", + "version": "4.0.4", + "licenses": [ + { + "license": { + "id": "MIT" + } + } + ], + "purl": "pkg:npm/balanced-match@4.0.4", + "properties": [ + { + "name": "codetruss:bundled", + "value": "true" + } + ] + }, + { + "type": "library", + "bom-ref": "pkg:npm/brace-expansion@5.0.9", + "name": "brace-expansion", + "version": "5.0.9", + "licenses": [ + { + "license": { + "id": "MIT" + } + } + ], + "purl": "pkg:npm/brace-expansion@5.0.9", + "properties": [ + { + "name": "codetruss:bundled", + "value": "true" + } + ] + }, + { + "type": "library", + "bom-ref": "pkg:npm/minimatch@10.2.6", + "name": "minimatch", + "version": "10.2.6", + "licenses": [ + { + "license": { + "id": "BlueOak-1.0.0" + } + } + ], + "purl": "pkg:npm/minimatch@10.2.6", + "properties": [ + { + "name": "codetruss:bundled", + "value": "true" + } + ] + }, + { + "type": "library", + "bom-ref": "pkg:npm/yaml@2.9.0", + "name": "yaml", + "version": "2.9.0", + "licenses": [ + { + "license": { + "id": "ISC" + } + } + ], + "purl": "pkg:npm/yaml@2.9.0", + "properties": [ + { + "name": "codetruss:bundled", + "value": "true" + } + ] + } + ], + "dependencies": [ + { + "ref": "pkg:npm/%40codetruss/analyzer-engine@0.1.0", + "dependsOn": [] + }, + { + "ref": "pkg:npm/%40codetruss/cli@0.2.52", + "dependsOn": [ + "pkg:npm/%40codetruss/analyzer-engine@0.1.0", + "pkg:npm/minimatch@10.2.6", + "pkg:npm/yaml@2.9.0" + ] + }, + { + "ref": "pkg:npm/balanced-match@4.0.4", + "dependsOn": [] + }, + { + "ref": "pkg:npm/brace-expansion@5.0.9", + "dependsOn": [ + "pkg:npm/balanced-match@4.0.4" + ] + }, + { + "ref": "pkg:npm/minimatch@10.2.6", + "dependsOn": [ + "pkg:npm/brace-expansion@5.0.9" + ] + }, + { + "ref": "pkg:npm/yaml@2.9.0", + "dependsOn": [] + } + ] +} diff --git a/public/downloads/codetruss-cli-0.2.52.tgz b/public/downloads/codetruss-cli-0.2.52.tgz new file mode 100644 index 0000000..2b40831 Binary files /dev/null and b/public/downloads/codetruss-cli-0.2.52.tgz differ diff --git a/public/downloads/codetruss-cli-0.2.52.tgz.sha256 b/public/downloads/codetruss-cli-0.2.52.tgz.sha256 new file mode 100644 index 0000000..3074a26 --- /dev/null +++ b/public/downloads/codetruss-cli-0.2.52.tgz.sha256 @@ -0,0 +1 @@ +5afc2a563358f1f7dd41eaf2484dc7913e326d9e7072f0d8c5bdeb1bb77792dd codetruss-cli-0.2.52.tgz diff --git a/public/downloads/codetruss-cli-latest.json b/public/downloads/codetruss-cli-latest.json index c55b013..fc61468 100644 --- a/public/downloads/codetruss-cli-latest.json +++ b/public/downloads/codetruss-cli-latest.json @@ -1,13 +1,13 @@ { "name": "@codetruss/cli", - "version": "0.2.51", - "url": "/downloads/codetruss-cli-0.2.51.tgz", + "version": "0.2.52", + "url": "/downloads/codetruss-cli-0.2.52.tgz", "latestUrl": "/downloads/codetruss-cli-latest.tgz", - "sha256": "0dbd333a638376aa68e4a2f330c6d59cd0e852700104a7dd5444232a2278a862", - "sbomUrl": "/downloads/codetruss-cli-0.2.51.sbom.cdx.json", - "sbomSha256": "4f01e0111543c4d624e365d1b889377bb2a560048549eac78bb52d0eaedc9ed7", + "sha256": "5afc2a563358f1f7dd41eaf2484dc7913e326d9e7072f0d8c5bdeb1bb77792dd", + "sbomUrl": "/downloads/codetruss-cli-0.2.52.sbom.cdx.json", + "sbomSha256": "0667253d5059b5aa5373c3dc6266efae87919b28179724ecd26dc6747f167d89", "node": ">=20.9.0", "repository": "https://github.com/CodeTruss/codetruss-cli", - "releaseUrl": "https://github.com/CodeTruss/codetruss-cli/releases/tag/v0.2.51", - "attestationCommand": "gh attestation verify codetruss-cli-0.2.51.tgz --repo CodeTruss/codetruss-cli" + "releaseUrl": "https://github.com/CodeTruss/codetruss-cli/releases/tag/v0.2.52", + "attestationCommand": "gh attestation verify codetruss-cli-0.2.52.tgz --repo CodeTruss/codetruss-cli" } diff --git a/public/downloads/codetruss-cli-latest.sbom.cdx.json b/public/downloads/codetruss-cli-latest.sbom.cdx.json index 1abef22..280aaf0 100644 --- a/public/downloads/codetruss-cli-latest.sbom.cdx.json +++ b/public/downloads/codetruss-cli-latest.sbom.cdx.json @@ -1,15 +1,15 @@ { "$schema": "https://cyclonedx.org/schema/bom-1.6.schema.json", "bomFormat": "CycloneDX", - "serialNumber": "urn:uuid:adb8b3be-45ad-577d-bf89-efd2410b1e21", + "serialNumber": "urn:uuid:4c318a44-4d62-55be-95fe-0240ae7f3d90", "specVersion": "1.6", "version": 1, "metadata": { "component": { "type": "application", - "bom-ref": "pkg:npm/%40codetruss/cli@0.2.51", + "bom-ref": "pkg:npm/%40codetruss/cli@0.2.52", "name": "@codetruss/cli", - "version": "0.2.51", + "version": "0.2.52", "description": "Local-first scope, quality, and verification receipts for coding agents", "licenses": [ { @@ -18,7 +18,7 @@ } } ], - "purl": "pkg:npm/%40codetruss/cli@0.2.51" + "purl": "pkg:npm/%40codetruss/cli@0.2.52" }, "properties": [ { @@ -139,7 +139,7 @@ "dependsOn": [] }, { - "ref": "pkg:npm/%40codetruss/cli@0.2.51", + "ref": "pkg:npm/%40codetruss/cli@0.2.52", "dependsOn": [ "pkg:npm/%40codetruss/analyzer-engine@0.1.0", "pkg:npm/minimatch@10.2.6", diff --git a/public/downloads/codetruss-cli-latest.tgz b/public/downloads/codetruss-cli-latest.tgz index 0f69844..2b40831 100644 Binary files a/public/downloads/codetruss-cli-latest.tgz and b/public/downloads/codetruss-cli-latest.tgz differ diff --git a/public/downloads/codetruss-cli-latest.tgz.sha256 b/public/downloads/codetruss-cli-latest.tgz.sha256 index 938921c..5baae22 100644 --- a/public/downloads/codetruss-cli-latest.tgz.sha256 +++ b/public/downloads/codetruss-cli-latest.tgz.sha256 @@ -1 +1 @@ -0dbd333a638376aa68e4a2f330c6d59cd0e852700104a7dd5444232a2278a862 codetruss-cli-latest.tgz +5afc2a563358f1f7dd41eaf2484dc7913e326d9e7072f0d8c5bdeb1bb77792dd codetruss-cli-latest.tgz diff --git a/release-reference.json b/release-reference.json index 2b39a47..2f7804f 100644 --- a/release-reference.json +++ b/release-reference.json @@ -1,8 +1,8 @@ { "schemaVersion": 1, - "version": "0.2.51", - "websiteArchive": "https://codetruss.com/downloads/codetruss-cli-0.2.51.tgz", - "archiveSha256": "0dbd333a638376aa68e4a2f330c6d59cd0e852700104a7dd5444232a2278a862", - "sbomSha256": "4f01e0111543c4d624e365d1b889377bb2a560048549eac78bb52d0eaedc9ed7", - "bundleSha256": "1dd21a129123693dc6dc3b7b6706ca1abf40b97eafc75da5e04e41c0af2722dd" + "version": "0.2.52", + "websiteArchive": "https://codetruss.com/downloads/codetruss-cli-0.2.52.tgz", + "archiveSha256": "5afc2a563358f1f7dd41eaf2484dc7913e326d9e7072f0d8c5bdeb1bb77792dd", + "sbomSha256": "0667253d5059b5aa5373c3dc6266efae87919b28179724ecd26dc6747f167d89", + "bundleSha256": "6db4f9ef9e94a4fb379b785be51f5b8b932cbd4c251032851866e0892e4cc332" }