testguard-cli 0.1.0__tar.gz → 0.1.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/.github/dependabot.yml +1 -2
- testguard_cli-0.1.1/.github/scripts/install-smoke.mjs +39 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/.github/scripts/sync-release-version.mjs +1 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/.github/workflows/auto-merge.yml +1 -1
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/.github/workflows/ci.yml +8 -1
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/.github/workflows/release.yml +2 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/.github/workflows/scheduled-release.yml +1 -1
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/.npmrc +2 -2
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/AGENTS.md +3 -1
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/CHANGELOG.md +18 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/CONTRIBUTING.md +5 -3
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/PKG-INFO +4 -4
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/README.md +3 -3
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/SECURITY.md +3 -1
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/action.yml +1 -1
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/package-lock.json +8 -8
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/package.json +6 -3
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/packaging/homebrew/testguard.rb +3 -3
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/pyproject.toml +1 -1
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/.gitattributes +0 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/.github/workflows/supply-chain.yml +0 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/.gitignore +0 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/.npmignore +0 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/.pre-commit-hooks.yaml +0 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/CLAUDE.md +0 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/CODE_OF_CONDUCT.md +0 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/LICENSE +0 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/PRIVACY.md +0 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/SUPPORT.md +0 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/bench/README.md +0 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/cli/testguard.mjs +0 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/fixtures/known-answer/.gitignore +0 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/fixtures/known-answer/README.md +0 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/fixtures/known-answer/expected.json +0 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/fixtures/known-answer/package.json +0 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/fixtures/known-answer/src/export.mjs +0 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/fixtures/known-answer/src/redact.mjs +0 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/fixtures/known-answer/test/flaky.test.mjs +0 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/fixtures/known-answer/test/redact.test.mjs +0 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/fixtures/known-answer/testguard.claims.json +0 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/fixtures/known-answer/vitest.config.mjs +0 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/spec/GATE-SEMANTICS.md +0 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/spec/README.md +0 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/spec/conformance/examples/baseline.json +0 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/spec/conformance/examples/brief.json +0 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/spec/conformance/examples/calibration.json +0 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/spec/conformance/examples/claims.json +0 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/spec/conformance/examples/evidence.json +0 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/spec/conformance/examples/ignore.json +0 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/spec/conformance/invalid/baseline.bad-fingerprint-key.json +0 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/spec/conformance/invalid/baseline.zero-count.json +0 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/spec/conformance/invalid/brief.text-without-heading.json +0 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/spec/conformance/invalid/brief.unknown-verdict-key.json +0 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/spec/conformance/invalid/calibration.p-outside-ci.json +0 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/spec/conformance/invalid/calibration.positives-exceed-n.json +0 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/spec/conformance/invalid/claims.absolute-path.json +0 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/spec/conformance/invalid/claims.duplicate-fault-id.json +0 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/spec/conformance/invalid/claims.missing-provenance.json +0 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/spec/conformance/invalid/claims.noop-fault.json +0 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/spec/conformance/invalid/claims.occurrence-exceeds-hits.json +0 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/spec/conformance/invalid/claims.parent-traversal.json +0 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/spec/conformance/invalid/evidence.flaky-defender-without-flakiness.json +0 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/spec/conformance/invalid/evidence.killed-by-non-assertion.json +0 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/spec/conformance/invalid/evidence.killed-on-red-baseline.json +0 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/spec/conformance/invalid/evidence.killed-without-n-runs.json +0 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/spec/conformance/invalid/evidence.rank-extra-property.json +0 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/spec/conformance/invalid/evidence.unknown-verdict.json +0 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/spec/conformance/invalid/evidence.unverifiable-without-reason.json +0 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/spec/conformance/invalid/evidence.wrong-fingerprint.json +0 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/spec/conformance/invalid/ignore.missing-reason.json +0 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/spec/conformance/invalid/ignore.short-reason.json +0 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/spec/conformance/schemas.test.mjs +0 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/spec/lib/fingerprint.mjs +0 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/spec/lib/validate.mjs +0 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/spec/schemas/baseline.schema.json +0 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/spec/schemas/brief.schema.json +0 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/spec/schemas/calibration.schema.json +0 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/spec/schemas/claims.schema.json +0 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/spec/schemas/common.schema.json +0 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/spec/schemas/evidence.schema.json +0 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/spec/schemas/ignore.schema.json +0 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/src/baseline/baseline.mjs +0 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/src/brief/brief.mjs +0 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/src/claims/annotations.mjs +0 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/src/claims/load.mjs +0 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/src/cli.mjs +0 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/src/commands/baseline.mjs +0 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/src/commands/brief.mjs +0 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/src/commands/claims.mjs +0 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/src/commands/probe.mjs +0 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/src/evidence/writer.mjs +0 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/src/git.mjs +0 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/src/probe/classify.mjs +0 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/src/probe/inject.mjs +0 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/src/probe/probe.mjs +0 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/src/probe/rank.mjs +0 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/src/probe/runner-vitest.mjs +0 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/src/probe/worktree.mjs +0 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/src/render.mjs +0 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/src/util/glob.mjs +0 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/src/util/hash.mjs +0 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/test/annotations.test.mjs +0 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/test/baseline.test.mjs +0 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/test/brief.test.mjs +0 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/test/classify.test.mjs +0 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/test/glob.test.mjs +0 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/test/inject.test.mjs +0 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/test/probe.fixture.test.mjs +0 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/test/runner-vitest.test.mjs +0 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/test/worktree.test.mjs +0 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/test/writer.test.mjs +0 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/testguard.claims.json +0 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/testguard_cli/__init__.py +0 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/testguard_cli/wrapper.py +0 -0
- {testguard_cli-0.1.0 → testguard_cli-0.1.1}/vitest.config.mjs +0 -0
|
@@ -7,8 +7,7 @@ updates:
|
|
|
7
7
|
groups:
|
|
8
8
|
all-npm:
|
|
9
9
|
patterns: ["*"]
|
|
10
|
-
#
|
|
11
|
-
# runner). The published package has zero runtime dependencies.
|
|
10
|
+
# One runtime dependency (ajv, exact-pinned) plus vitest for tests.
|
|
12
11
|
- package-ecosystem: "pip"
|
|
13
12
|
directory: "/"
|
|
14
13
|
schedule:
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Prove the package works AS INSTALLED, not as checked out: pack it, install
|
|
4
|
+
* the tarball into a scratch project with production dependencies only, and
|
|
5
|
+
* run the CLI from there. This is the gate that would have caught 0.1.0,
|
|
6
|
+
* which shipped with its schema validator's dependency declared as a
|
|
7
|
+
* devDependency and crashed on startup for every npm/npx/pip/brew user.
|
|
8
|
+
*/
|
|
9
|
+
import { execFileSync } from 'node:child_process';
|
|
10
|
+
import { mkdtempSync, mkdirSync, rmSync, cpSync, readdirSync } from 'node:fs';
|
|
11
|
+
import { tmpdir } from 'node:os';
|
|
12
|
+
import { join, resolve } from 'node:path';
|
|
13
|
+
|
|
14
|
+
const root = resolve(process.argv[1], '..', '..', '..');
|
|
15
|
+
const run = (cmd, args, cwd) => execFileSync(cmd, args, { cwd, encoding: 'utf8', stdio: ['ignore', 'pipe', 'inherit'] });
|
|
16
|
+
const npm = process.platform === 'win32' ? 'npm.cmd' : 'npm';
|
|
17
|
+
|
|
18
|
+
const scratch = mkdtempSync(join(tmpdir(), 'testguard-install-smoke-'));
|
|
19
|
+
try {
|
|
20
|
+
const packDir = join(scratch, 'pack');
|
|
21
|
+
mkdirSync(packDir);
|
|
22
|
+
run(npm, ['pack', '--pack-destination', packDir, '--ignore-scripts'], root);
|
|
23
|
+
const tgz = join(packDir, readdirSync(packDir).find((f) => f.endsWith('.tgz')));
|
|
24
|
+
|
|
25
|
+
const consumer = join(scratch, 'consumer');
|
|
26
|
+
cpSync(join(root, 'fixtures', 'known-answer'), consumer, { recursive: true, filter: (s) => !/node_modules|\.flake-counter|\.testguard/.test(s) });
|
|
27
|
+
run(npm, ['init', '-y'], consumer);
|
|
28
|
+
run(npm, ['install', '--omit=dev', '--ignore-scripts', '--no-audit', '--no-fund', tgz], consumer);
|
|
29
|
+
|
|
30
|
+
const bin = join(consumer, 'node_modules', '.bin', process.platform === 'win32' ? 'testguard.cmd' : 'testguard');
|
|
31
|
+
const version = run(bin, ['--version'], consumer).trim();
|
|
32
|
+
const claims = run(bin, ['claims', '.'], consumer);
|
|
33
|
+
if (!/^\d+\.\d+\.\d+/.test(version)) throw new Error(`unexpected --version output: ${version}`);
|
|
34
|
+
if (!claims.includes('8 claims')) throw new Error(`claims did not list the fixture:\n${claims}`);
|
|
35
|
+
const deps = Object.keys(JSON.parse(run(npm, ['ls', '--omit=dev', '--json', '--depth=0'], consumer)).dependencies ?? {});
|
|
36
|
+
console.log(`install smoke OK — testguard ${version} runs from the installed tarball; consumer deps: ${deps.join(', ')}`);
|
|
37
|
+
} finally {
|
|
38
|
+
rmSync(scratch, { recursive: true, force: true });
|
|
39
|
+
}
|
|
@@ -20,6 +20,7 @@ const surfaces = [
|
|
|
20
20
|
['pyproject.toml', /^version = "[^"]+"/m, `version = "${version}"`],
|
|
21
21
|
['action.yml', /(\n version:\n description: [^\n]*\n required: false\n default: ')[^']*(')/, `$1${version}$2`],
|
|
22
22
|
['packaging/homebrew/testguard.rb', /testguard-cli-\d+\.\d+\.\d+\.tgz/g, `testguard-cli-${version}.tgz`],
|
|
23
|
+
['README.md', /raccioly\/testguard@v\d+\.\d+\.\d+/g, `raccioly/testguard@v${version}`],
|
|
23
24
|
];
|
|
24
25
|
|
|
25
26
|
let drift = 0;
|
|
@@ -46,7 +46,7 @@ jobs:
|
|
|
46
46
|
|
|
47
47
|
const { data: files } = await github.rest.pulls.listFiles({ owner, repo, pull_number: num, per_page: 300 });
|
|
48
48
|
const paths = files.map((f) => f.filename);
|
|
49
|
-
const RELEASE_SURFACES = new Set(['package.json', 'package-lock.json', 'pyproject.toml', 'CHANGELOG.md', 'action.yml', 'packaging/homebrew/testguard.rb']);
|
|
49
|
+
const RELEASE_SURFACES = new Set(['package.json', 'package-lock.json', 'pyproject.toml', 'CHANGELOG.md', 'action.yml', 'packaging/homebrew/testguard.rb', 'README.md']);
|
|
50
50
|
|
|
51
51
|
if (author === 'dependabot[bot]') {
|
|
52
52
|
const m = /from (\d+)\.(\d+)\.\S+ to (\d+)\.(\d+)\./.exec(pr.title || '');
|
|
@@ -30,7 +30,7 @@ jobs:
|
|
|
30
30
|
with:
|
|
31
31
|
node-version: ${{ matrix.node-version }}
|
|
32
32
|
|
|
33
|
-
- name: Install
|
|
33
|
+
- name: Install
|
|
34
34
|
run: npm ci
|
|
35
35
|
|
|
36
36
|
# ── Syntax-check EVERY source, not just what the entry point eagerly
|
|
@@ -38,6 +38,13 @@ jobs:
|
|
|
38
38
|
- name: Syntax-check all sources
|
|
39
39
|
run: find cli src spec -name '*.mjs' -print0 | xargs -0 -n1 node --check
|
|
40
40
|
|
|
41
|
+
# ── Install-from-tarball smoke: the package must run as INSTALLED, with
|
|
42
|
+
# production dependencies only. 0.1.0 shipped unrunnable because the
|
|
43
|
+
# schema validator's dependency was a devDependency; the suite, which
|
|
44
|
+
# runs from the checkout, could not see it. ──
|
|
45
|
+
- name: Install smoke (pack → install --omit=dev → run)
|
|
46
|
+
run: npm run test:install
|
|
47
|
+
|
|
41
48
|
- name: Python wrapper imports (PyPI surface)
|
|
42
49
|
run: python3 -c "import testguard_cli.wrapper; print('testguard_cli.wrapper OK')"
|
|
43
50
|
|
|
@@ -77,6 +77,8 @@ jobs:
|
|
|
77
77
|
node-version: 24
|
|
78
78
|
- run: npm ci
|
|
79
79
|
- run: npm test
|
|
80
|
+
- name: Install smoke — the tarball must run with production deps only
|
|
81
|
+
run: npm run test:install
|
|
80
82
|
- name: Self-probe must be fully defended before anything ships
|
|
81
83
|
run: node cli/testguard.mjs probe . --budget 180000 --out "$RUNNER_TEMP/self-evidence.json" --quiet
|
|
82
84
|
- name: Version surfaces are in sync
|
|
@@ -102,7 +102,7 @@ jobs:
|
|
|
102
102
|
# Only release surfaces may change in a release PR.
|
|
103
103
|
CHANGED=$(git diff --name-only HEAD --)
|
|
104
104
|
for f in $CHANGED; do
|
|
105
|
-
case "$f" in package.json|package-lock.json|pyproject.toml|CHANGELOG.md|action.yml|packaging/homebrew/testguard.rb) ;;
|
|
105
|
+
case "$f" in package.json|package-lock.json|pyproject.toml|CHANGELOG.md|action.yml|packaging/homebrew/testguard.rb|README.md) ;;
|
|
106
106
|
*) echo "::error::unexpected file in release diff: $f"; exit 1;;
|
|
107
107
|
esac
|
|
108
108
|
done
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Supply-chain hardening.
|
|
2
2
|
# ignore-scripts: never run a dependency's install/postinstall scripts — the
|
|
3
|
-
# main supply-chain attack vector. TestGuard
|
|
4
|
-
# its
|
|
3
|
+
# main supply-chain attack vector. TestGuard's one runtime dependency (ajv)
|
|
4
|
+
# and its devDependency (vitest) work without install scripts.
|
|
5
5
|
# audit-level: surface moderate-and-above advisories.
|
|
6
6
|
ignore-scripts=true
|
|
7
7
|
audit-level=moderate
|
|
@@ -6,7 +6,8 @@ Read this before changing anything. It is short on purpose.
|
|
|
6
6
|
|
|
7
7
|
A CLI that proves a test suite defends the claims a project makes, by
|
|
8
8
|
injecting the faults those claims forbid and reporting every one the tests
|
|
9
|
-
miss. **Not a test generator.** Node ≥ 20, ESM,
|
|
9
|
+
miss. **Not a test generator.** Node ≥ 20, ESM, one exact-pinned runtime
|
|
10
|
+
dependency (`ajv`).
|
|
10
11
|
The shared formats under `spec/` are a contract other tools adopt; the CLI is
|
|
11
12
|
their first consumer.
|
|
12
13
|
|
|
@@ -16,6 +17,7 @@ their first consumer.
|
|
|
16
17
|
npm test # unit + fixture acceptance (~15s)
|
|
17
18
|
npm run test:spec # conformance suite only
|
|
18
19
|
npm run self:probe # TestGuard probes its own claims; must exit 0
|
|
20
|
+
npm run test:install # the packed tarball must run with production deps only
|
|
19
21
|
node cli/testguard.mjs claims fixtures/known-answer
|
|
20
22
|
```
|
|
21
23
|
|
|
@@ -7,6 +7,24 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.1.1] - 2026-09-17
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
|
|
14
|
+
- **0.1.0 did not run when installed.** `ajv`, which validates every document
|
|
15
|
+
against the spec, was declared as a devDependency, so `testguard` crashed on
|
|
16
|
+
startup from npm, `npx`, `pip` and Homebrew. It is now an exact-pinned
|
|
17
|
+
runtime dependency — the project's one dependency.
|
|
18
|
+
- CI and the release job now pack the tarball, install it into a scratch
|
|
19
|
+
project with production dependencies only, and run the CLI from there
|
|
20
|
+
(`npm run test:install`). The suite alone runs from the checkout and could
|
|
21
|
+
not see this class of defect.
|
|
22
|
+
|
|
23
|
+
### Changed
|
|
24
|
+
|
|
25
|
+
- Homebrew formula carries the sha256 of the published tarball; description
|
|
26
|
+
shortened to satisfy `brew audit --strict`.
|
|
27
|
+
|
|
10
28
|
## [0.1.0] - 2026-09-17
|
|
11
29
|
|
|
12
30
|
First release. A claim verifier, not a test generator.
|
|
@@ -8,9 +8,10 @@ follow from that.
|
|
|
8
8
|
|
|
9
9
|
```bash
|
|
10
10
|
git clone https://github.com/raccioly/testguard && cd testguard
|
|
11
|
-
npm install
|
|
11
|
+
npm install
|
|
12
12
|
npm test # ~15s: unit tests + probing the fixture end to end
|
|
13
13
|
npm run self:probe # TestGuard's own claims, probed by TestGuard
|
|
14
|
+
npm run test:install # pack → install with prod deps only → run; what 0.1.0 lacked
|
|
14
15
|
```
|
|
15
16
|
|
|
16
17
|
Node ≥ 20. Python ≥ 3.8 only if you touch `testguard_cli/`.
|
|
@@ -41,8 +42,9 @@ Node ≥ 20. Python ≥ 3.8 only if you touch `testguard_cli/`.
|
|
|
41
42
|
load failure, or an exit code count as detection.
|
|
42
43
|
5. **N-run confirmation everywhere** — baseline, probe, and escalation
|
|
43
44
|
attribution. A single run is never evidence.
|
|
44
|
-
6. **
|
|
45
|
-
discussion first.
|
|
45
|
+
6. **One runtime dependency** (`ajv`, exact-pinned). Adding another needs a
|
|
46
|
+
very good reason and a discussion first. `npm run test:install` proves
|
|
47
|
+
the package runs as installed with production dependencies only.
|
|
46
48
|
7. **No client-identifying material.** Fixtures and examples use neutral
|
|
47
49
|
domains. Benchmarks against real codebases live outside this repository
|
|
48
50
|
(`bench/README.md`).
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: testguard-cli
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.1
|
|
4
4
|
Summary: Proves a test suite actually defends the claims a project makes: injects the faults those claims forbid and reports every one the tests miss. Python wrapper for the Node.js CLI (requires Node.js 20+).
|
|
5
5
|
Project-URL: Homepage, https://github.com/raccioly/testguard
|
|
6
6
|
Project-URL: Documentation, https://github.com/raccioly/testguard#readme
|
|
@@ -29,7 +29,7 @@ Description-Content-Type: text/markdown
|
|
|
29
29
|
[](https://pypi.org/project/testguard-cli/)
|
|
30
30
|
[](https://nodejs.org)
|
|
31
31
|
[](./LICENSE)
|
|
32
|
-
[](./package.json)
|
|
33
33
|
|
|
34
34
|
> Proves that a test suite actually defends the claims a project makes — by
|
|
35
35
|
> injecting the faults those claims say cannot happen, and reporting every
|
|
@@ -67,7 +67,7 @@ on known-broken code. The largest gap was a compliance-critical path with
|
|
|
67
67
|
| npm | `npm i -D testguard-cli` then `npx testguard probe` |
|
|
68
68
|
| pip | `pip install testguard-cli` then `testguard probe` (needs Node ≥ 20) |
|
|
69
69
|
| Homebrew | `brew tap raccioly/tap && brew install testguard` |
|
|
70
|
-
| GitHub Action | `uses: raccioly/testguard@v0.1.
|
|
70
|
+
| GitHub Action | `uses: raccioly/testguard@v0.1.1` — see [`action.yml`](./action.yml) |
|
|
71
71
|
| pre-commit | `repo: https://github.com/raccioly/testguard`, hooks `testguard-claims`, `testguard-probe` |
|
|
72
72
|
|
|
73
73
|
## How it works
|
|
@@ -147,7 +147,7 @@ through every verdict.
|
|
|
147
147
|
|
|
148
148
|
**v0.1.** Four commands, vitest runner, hand-authored faults. The contract
|
|
149
149
|
spine — six JSON Schemas shared with the other Guard tools — is under
|
|
150
|
-
[`spec/`](spec/).
|
|
150
|
+
[`spec/`](spec/). One exact-pinned runtime dependency (`ajv`, for schema validation); Node ≥ 20.
|
|
151
151
|
|
|
152
152
|
Not yet: test generation (the two-gate acceptance loop), other runners,
|
|
153
153
|
mechanical fault producers, and calibration of fault classes against real
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
[](https://pypi.org/project/testguard-cli/)
|
|
6
6
|
[](https://nodejs.org)
|
|
7
7
|
[](./LICENSE)
|
|
8
|
-
[](./package.json)
|
|
9
9
|
|
|
10
10
|
> Proves that a test suite actually defends the claims a project makes — by
|
|
11
11
|
> injecting the faults those claims say cannot happen, and reporting every
|
|
@@ -43,7 +43,7 @@ on known-broken code. The largest gap was a compliance-critical path with
|
|
|
43
43
|
| npm | `npm i -D testguard-cli` then `npx testguard probe` |
|
|
44
44
|
| pip | `pip install testguard-cli` then `testguard probe` (needs Node ≥ 20) |
|
|
45
45
|
| Homebrew | `brew tap raccioly/tap && brew install testguard` |
|
|
46
|
-
| GitHub Action | `uses: raccioly/testguard@v0.1.
|
|
46
|
+
| GitHub Action | `uses: raccioly/testguard@v0.1.1` — see [`action.yml`](./action.yml) |
|
|
47
47
|
| pre-commit | `repo: https://github.com/raccioly/testguard`, hooks `testguard-claims`, `testguard-probe` |
|
|
48
48
|
|
|
49
49
|
## How it works
|
|
@@ -123,7 +123,7 @@ through every verdict.
|
|
|
123
123
|
|
|
124
124
|
**v0.1.** Four commands, vitest runner, hand-authored faults. The contract
|
|
125
125
|
spine — six JSON Schemas shared with the other Guard tools — is under
|
|
126
|
-
[`spec/`](spec/).
|
|
126
|
+
[`spec/`](spec/). One exact-pinned runtime dependency (`ajv`, for schema validation); Node ≥ 20.
|
|
127
127
|
|
|
128
128
|
Not yet: test generation (the two-gate acceptance loop), other runners,
|
|
129
129
|
mechanical fault producers, and calibration of fault classes against real
|
|
@@ -18,7 +18,9 @@ You will get an acknowledgement within 48 hours and a timeline for a fix.
|
|
|
18
18
|
|
|
19
19
|
TestGuard is a local CLI with a deliberately small surface:
|
|
20
20
|
|
|
21
|
-
- **
|
|
21
|
+
- **One runtime dependency, exact-pinned:** `ajv`, which validates every
|
|
22
|
+
document the tool reads or writes against the spec. Install scripts are
|
|
23
|
+
disabled (`.npmrc`). `vitest` is development-only.
|
|
22
24
|
- **No network access.** Nothing is uploaded, fetched, or reported anywhere.
|
|
23
25
|
- **No credentials.** There is nothing to authenticate to.
|
|
24
26
|
- **Writes are confined** to `.testguard/` in the probed project and to
|
|
@@ -1,15 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "testguard-cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "testguard-cli",
|
|
9
|
-
"version": "0.1.
|
|
9
|
+
"version": "0.1.1",
|
|
10
10
|
"license": "MIT",
|
|
11
|
+
"dependencies": {
|
|
12
|
+
"ajv": "8.20.0"
|
|
13
|
+
},
|
|
14
|
+
"bin": {
|
|
15
|
+
"testguard": "cli/testguard.mjs"
|
|
16
|
+
},
|
|
11
17
|
"devDependencies": {
|
|
12
|
-
"ajv": "^8.20.0",
|
|
13
18
|
"vitest": "^5.0.1"
|
|
14
19
|
},
|
|
15
20
|
"engines": {
|
|
@@ -418,7 +423,6 @@
|
|
|
418
423
|
"version": "8.20.0",
|
|
419
424
|
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz",
|
|
420
425
|
"integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==",
|
|
421
|
-
"dev": true,
|
|
422
426
|
"license": "MIT",
|
|
423
427
|
"dependencies": {
|
|
424
428
|
"fast-deep-equal": "^3.1.3",
|
|
@@ -493,14 +497,12 @@
|
|
|
493
497
|
"version": "3.1.3",
|
|
494
498
|
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
|
|
495
499
|
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
|
|
496
|
-
"dev": true,
|
|
497
500
|
"license": "MIT"
|
|
498
501
|
},
|
|
499
502
|
"node_modules/fast-uri": {
|
|
500
503
|
"version": "3.1.8",
|
|
501
504
|
"resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.8.tgz",
|
|
502
505
|
"integrity": "sha512-GZMtZUTNRpOVIECoXwLNZS5xUGE+mVNbTB8h/7Rwh2TFWcBQiPzTgyZi05BF9UMZKkLJv8XBRJTlU7zg8+ZfMg==",
|
|
503
|
-
"dev": true,
|
|
504
506
|
"funding": [
|
|
505
507
|
{
|
|
506
508
|
"type": "github",
|
|
@@ -551,7 +553,6 @@
|
|
|
551
553
|
"version": "1.0.0",
|
|
552
554
|
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
|
|
553
555
|
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
|
|
554
|
-
"dev": true,
|
|
555
556
|
"license": "MIT"
|
|
556
557
|
},
|
|
557
558
|
"node_modules/lightningcss": {
|
|
@@ -938,7 +939,6 @@
|
|
|
938
939
|
"version": "2.0.2",
|
|
939
940
|
"resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
|
|
940
941
|
"integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
|
|
941
|
-
"dev": true,
|
|
942
942
|
"license": "MIT",
|
|
943
943
|
"engines": {
|
|
944
944
|
"node": ">=0.10.0"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "testguard-cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "Proves a test suite defends the claims a project makes: injects the faults those claims forbid and reports every one the tests fail to detect.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -28,7 +28,8 @@
|
|
|
28
28
|
"test:spec": "vitest run spec/conformance",
|
|
29
29
|
"self:probe": "node cli/testguard.mjs probe . --budget 180000",
|
|
30
30
|
"release:sync": "node .github/scripts/sync-release-version.mjs",
|
|
31
|
-
"prepublishOnly": "node cli/testguard.mjs --version && node .github/scripts/sync-release-version.mjs --check"
|
|
31
|
+
"prepublishOnly": "node cli/testguard.mjs --version && node .github/scripts/sync-release-version.mjs --check",
|
|
32
|
+
"test:install": "node .github/scripts/install-smoke.mjs"
|
|
32
33
|
},
|
|
33
34
|
"keywords": [
|
|
34
35
|
"testing",
|
|
@@ -45,7 +46,6 @@
|
|
|
45
46
|
"quality-gate"
|
|
46
47
|
],
|
|
47
48
|
"devDependencies": {
|
|
48
|
-
"ajv": "^8.20.0",
|
|
49
49
|
"vitest": "^5.0.1"
|
|
50
50
|
},
|
|
51
51
|
"bin": {
|
|
@@ -62,5 +62,8 @@
|
|
|
62
62
|
},
|
|
63
63
|
"publishConfig": {
|
|
64
64
|
"access": "public"
|
|
65
|
+
},
|
|
66
|
+
"dependencies": {
|
|
67
|
+
"ajv": "8.20.0"
|
|
65
68
|
}
|
|
66
69
|
}
|
|
@@ -11,10 +11,10 @@
|
|
|
11
11
|
# and set `sha256` from the published tarball:
|
|
12
12
|
# curl -sL https://registry.npmjs.org/testguard-cli/-/testguard-cli-<VER>.tgz | shasum -a 256
|
|
13
13
|
class Testguard < Formula
|
|
14
|
-
desc "Proves a test suite defends the claims a project makes
|
|
14
|
+
desc "Proves a test suite defends the claims a project makes"
|
|
15
15
|
homepage "https://github.com/raccioly/testguard"
|
|
16
|
-
url "https://registry.npmjs.org/testguard-cli/-/testguard-cli-0.1.
|
|
17
|
-
sha256 "
|
|
16
|
+
url "https://registry.npmjs.org/testguard-cli/-/testguard-cli-0.1.1.tgz"
|
|
17
|
+
sha256 "fb7de3fa96886ca55a860bb6b2ed03dea1a6df13fb9fa7ad1bb12d860f9a971a"
|
|
18
18
|
license "MIT"
|
|
19
19
|
|
|
20
20
|
depends_on "node"
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "testguard-cli"
|
|
7
|
-
version = "0.1.
|
|
7
|
+
version = "0.1.1"
|
|
8
8
|
description = "Proves a test suite actually defends the claims a project makes: injects the faults those claims forbid and reports every one the tests miss. Python wrapper for the Node.js CLI (requires Node.js 20+)."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = { text = "MIT" }
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{testguard_cli-0.1.0 → testguard_cli-0.1.1}/spec/conformance/invalid/baseline.zero-count.json
RENAMED
|
File without changes
|
{testguard_cli-0.1.0 → testguard_cli-0.1.1}/spec/conformance/invalid/brief.text-without-heading.json
RENAMED
|
File without changes
|
{testguard_cli-0.1.0 → testguard_cli-0.1.1}/spec/conformance/invalid/brief.unknown-verdict-key.json
RENAMED
|
File without changes
|
{testguard_cli-0.1.0 → testguard_cli-0.1.1}/spec/conformance/invalid/calibration.p-outside-ci.json
RENAMED
|
File without changes
|
|
File without changes
|
{testguard_cli-0.1.0 → testguard_cli-0.1.1}/spec/conformance/invalid/claims.absolute-path.json
RENAMED
|
File without changes
|
{testguard_cli-0.1.0 → testguard_cli-0.1.1}/spec/conformance/invalid/claims.duplicate-fault-id.json
RENAMED
|
File without changes
|
{testguard_cli-0.1.0 → testguard_cli-0.1.1}/spec/conformance/invalid/claims.missing-provenance.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{testguard_cli-0.1.0 → testguard_cli-0.1.1}/spec/conformance/invalid/claims.parent-traversal.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{testguard_cli-0.1.0 → testguard_cli-0.1.1}/spec/conformance/invalid/evidence.unknown-verdict.json
RENAMED
|
File without changes
|
|
File without changes
|
{testguard_cli-0.1.0 → testguard_cli-0.1.1}/spec/conformance/invalid/evidence.wrong-fingerprint.json
RENAMED
|
File without changes
|
{testguard_cli-0.1.0 → testguard_cli-0.1.1}/spec/conformance/invalid/ignore.missing-reason.json
RENAMED
|
File without changes
|
{testguard_cli-0.1.0 → testguard_cli-0.1.1}/spec/conformance/invalid/ignore.short-reason.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|