tamperward 2.17.1 → 2.19.0
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.
- package/README.md +78 -3
- package/dist/cli/index.js +612 -93
- package/package.json +4 -2
- package/schemas/check-v1.schema.json +104 -0
- package/schemas/doctor-v1.schema.json +95 -0
- package/schemas/run-v1.schema.json +508 -0
- package/schemas/verify-v1.schema.json +606 -0
package/README.md
CHANGED
|
@@ -240,6 +240,7 @@ platforms.
|
|
|
240
240
|
| `watch` / observer telemetry | Supported; backend health is reported | Supported/degraded according to `fs.watch` health | Supported/degraded according to `fs.watch` health |
|
|
241
241
|
| checkpointed-local `verify` | Supported via `/bin/sh` | Supported via `/bin/sh` | **Unsupported; fails before candidate execution** |
|
|
242
242
|
| isolated-container `verify` | Supported when Docker authority preflight passes | Not claimed beyond Docker preflight | Not claimed beyond Docker preflight |
|
|
243
|
+
| advisory `trace-verify` | **Supported with `strace` + `tar`** | **Unsupported; reports no parity** | **Unsupported; reports no parity** |
|
|
243
244
|
| authoritative `run` | **Supported only with trusted non-root subreaper backend** | **Unsupported; fails before agent start** | **Unsupported; fails before agent start** |
|
|
244
245
|
| CI coverage for this contract | Full suite + platform contract | Platform-contract job | Platform-contract job |
|
|
245
246
|
|
|
@@ -430,6 +431,30 @@ restored `"test": "sh scripts/test.sh"` will happily call a script nothing
|
|
|
430
431
|
restored. It bounds the class rather than closing it — see
|
|
431
432
|
[the threat model](./docs/THREAT-MODEL-pristine-run.md).
|
|
432
433
|
|
|
434
|
+
From **2.18.0**, Linux can turn that residual into an auditable observation with
|
|
435
|
+
`tamperward trace-verify`. It materialises the caller-selected trusted base, runs the
|
|
436
|
+
known-good verifier under `strace`, repeats the trace (two runs by default), unions the
|
|
437
|
+
file/exec observations, and reports:
|
|
438
|
+
- tracked repository inputs the verifier actually read or executed;
|
|
439
|
+
- likely config inputs;
|
|
440
|
+
- external dependency/runtime paths;
|
|
441
|
+
- paths seen in only some runs as **dynamic**;
|
|
442
|
+
- whether each tracked input is already covered by the same pristine-verification
|
|
443
|
+
surface used by `verify`;
|
|
444
|
+
- exact uncovered paths as candidate `verify.inputs` entries for **human review**.
|
|
445
|
+
|
|
446
|
+
It is advisory only: it never edits `.tamperward.yml`, never widens a glob, and never
|
|
447
|
+
treats absence from one or several traces as proof a path can never be read. Use a
|
|
448
|
+
known-good base; `trace-verify` observes what those executions did, it does not prove
|
|
449
|
+
the base or external runtime/dependencies are trustworthy. macOS and Windows report the
|
|
450
|
+
feature unsupported rather than implying parity.
|
|
451
|
+
|
|
452
|
+
Example:
|
|
453
|
+
|
|
454
|
+
```bash
|
|
455
|
+
npx tamperward trace-verify --base main --cmd "npm test" --runs 3
|
|
456
|
+
```
|
|
457
|
+
|
|
433
458
|
From **2.16.0**, verifier suite output is diagnostic evidence instead of discarded
|
|
434
459
|
noise. Both visible and pristine stages continuously drain stdout/stderr through a
|
|
435
460
|
trusted supervisor, retain only the final **16 KiB per stream**, and count the total
|
|
@@ -448,6 +473,7 @@ The four primitives:
|
|
|
448
473
|
npx tamperward check --staged # pre-commit view
|
|
449
474
|
npx tamperward check --diff "main...HEAD" # CI view over the PR's commit range
|
|
450
475
|
npx tamperward verify --base main # pristine-suite re-execution
|
|
476
|
+
npx tamperward trace-verify --base main --runs 2 # advisory observed-input discovery (Linux)
|
|
451
477
|
npx tamperward run --agent-budget 1800 -- <agent command...> # optional agent-runtime bound
|
|
452
478
|
```
|
|
453
479
|
|
|
@@ -456,6 +482,50 @@ deliberately refuses `backend: container` before launching the agent because the
|
|
|
456
482
|
would share the host identity that controls Docker. Use isolated `tamperward verify`
|
|
457
483
|
from trusted CI, or after an externally isolated agent hands off the frozen candidate.
|
|
458
484
|
|
|
485
|
+
### Machine-readable verdict API
|
|
486
|
+
|
|
487
|
+
From **2.19.0**, the public JSON verdict surfaces are versioned independently of the
|
|
488
|
+
npm package version. `check --json`, `verify --json`, `run --json`, and
|
|
489
|
+
`doctor --json` include top-level `"schema_version": 1`. TamperWard publishes the
|
|
490
|
+
corresponding JSON Schema Draft 2020-12 documents in the npm package and repository:
|
|
491
|
+
|
|
492
|
+
- [`schemas/check-v1.schema.json`](./schemas/check-v1.schema.json)
|
|
493
|
+
- [`schemas/verify-v1.schema.json`](./schemas/verify-v1.schema.json)
|
|
494
|
+
- [`schemas/run-v1.schema.json`](./schemas/run-v1.schema.json)
|
|
495
|
+
- [`schemas/doctor-v1.schema.json`](./schemas/doctor-v1.schema.json)
|
|
496
|
+
|
|
497
|
+
Schema major **1** is deliberately additive: consumers should ignore fields they do not
|
|
498
|
+
understand. Adding new evidence/diagnostic fields does not require a schema bump.
|
|
499
|
+
Removing or renaming a required field, changing its type, or changing the meaning of a
|
|
500
|
+
discriminator requires `schema_version: 2` and new `*-v2.schema.json` files; the v1
|
|
501
|
+
files remain published for existing integrations.
|
|
502
|
+
|
|
503
|
+
`run --json` owns stdout after the wrapped agent starts and emits one final envelope
|
|
504
|
+
document, including post-agent early convictions such as `OBJECT_REWRITE`,
|
|
505
|
+
`HISTORY_REWRITE`, `DEPENDENCY_DRIFT`, or lifecycle cannot-adjudicate. In this mode the
|
|
506
|
+
agent's own stdout is routed to stderr (its stderr is unchanged), so stdout carries
|
|
507
|
+
exactly one document however noisy the agent is. The document's `complete` field says
|
|
508
|
+
whether the full post-agent adjudication ran: `true` documents carry `head`,
|
|
509
|
+
`checks.{diff,worktree,verify}` and `observer`; early convictions and lifecycle refusals
|
|
510
|
+
are `complete: false`. A `CANNOT_ADJUDICATE` document always names which layer could not
|
|
511
|
+
judge in `reason` (`AGENT_LIFECYCLE_NOT_OWNED`, `VERIFY_CANNOT_VERIFY`,
|
|
512
|
+
`CHECK_DIFF_UNJUDGEABLE`, `CHECK_WORKTREE_UNJUDGEABLE`). Argument, trusted-base, policy,
|
|
513
|
+
dirty-start, and other **pre-agent/preflight** failures still fail closed on stderr at
|
|
514
|
+
exit 2 because no agent adjudication occurred.
|
|
515
|
+
|
|
516
|
+
`verify --json` never falls back to prose: every fail-closed exit before a verdict exists
|
|
517
|
+
is a `CANNOT_VERIFY` document whose `reason` is one of the enumerated codes in the schema
|
|
518
|
+
(`POLICY_ERROR`, `NO_SUITE_COMMAND`, `VERIFIER_BACKEND_UNAVAILABLE`, `WORKTREE_CHANGED`,
|
|
519
|
+
`PRISTINE_INTEGRITY_CHANGED`, …) with a human `detail` beside it and, once a suite
|
|
520
|
+
execution was in flight, the `stage` it happened in. The reason vocabularies for both
|
|
521
|
+
`verify` and `run` are defined once in the source and asserted equal to the schema enums
|
|
522
|
+
by the test suite, so a new code cannot ship without the contract.
|
|
523
|
+
|
|
524
|
+
The JSON schemas describe **data shape**, not process status. Exit codes are a separate
|
|
525
|
+
public protocol and are documented in the table immediately below. Consumers should
|
|
526
|
+
validate both independently: schema validation answers “can I parse this verdict?”;
|
|
527
|
+
the process exit answers “did the gate allow, block, time out, or fail to adjudicate?”
|
|
528
|
+
|
|
459
529
|
### CLI reference
|
|
460
530
|
|
|
461
531
|
Every flag below is what the command's parser actually reads (`src/cli/main.ts`,
|
|
@@ -470,8 +540,9 @@ option can never be reinterpreted as the agent command.
|
|
|
470
540
|
| --- | --- |
|
|
471
541
|
| `check` | one view — `--staged` · `--worktree` · `--diff <base>...<head>` — plus `--format text\|json\|github\|auto` (default `auto`) · `--json` (alias for `--format json`) · `--cwd <dir>` |
|
|
472
542
|
| `verify` | `--base <rev>` (default `HEAD`) · `--cmd <suite command>` · `--budget <seconds>` · `--json` · `--keep` (keep the two materialised copies and report their paths) · `--require-ancestor` (refuse a base that is not an ancestor of `HEAD`) · `--cwd <dir>` |
|
|
543
|
+
| `trace-verify` | Linux-only advisory discovery: `--base <rev>` (default `HEAD`) · `--cmd <suite command>` · `--budget <seconds>` · `--runs <positive integer>` (default 2) · `--json` · `--cwd <dir>` |
|
|
473
544
|
| `doctor` | `--base <rev>` (trusted policy revision) · `--workflow <path>` · `--cwd <dir>` · `--json` · `--github` · `--repo <owner/repo>` · `--branch <name>` — read-only installation/authority posture plus CI verifier outer-time validation |
|
|
474
|
-
| `run` | `--base <rev>` · `--cmd <suite command>` · `--budget <seconds>` (per verifier suite) · `--agent-budget <seconds>` (optional wrapped-agent wall clock) · `--observe-transients` (start a session-scoped transient observer) · `--allow-dirty` · `--settle <seconds>` (wait before the final quiescence check) · `--allow-dep-drift` · `--cwd <dir>` · then `-- <agent command...>` |
|
|
545
|
+
| `run` | `--base <rev>` · `--cmd <suite command>` · `--budget <seconds>` (per verifier suite) · `--agent-budget <seconds>` (optional wrapped-agent wall clock) · `--json` (one versioned final envelope document) · `--observe-transients` (start a session-scoped transient observer) · `--allow-dirty` · `--settle <seconds>` (wait before the final quiescence check) · `--allow-dep-drift` · `--cwd <dir>` · then `-- <agent command...>` |
|
|
475
546
|
| `allow` | `<rule>` · `--file <path>` · `--reason "<why>"` (required) · `--cwd <dir>` |
|
|
476
547
|
| `init` | `--cwd <dir>` · `--dry-run` · `--force-workflow` |
|
|
477
548
|
| `watch` | `--dir <dir>` · `--log <file>` — a daemon; it runs until signalled |
|
|
@@ -483,6 +554,7 @@ option can never be reinterpreted as the agent command.
|
|
|
483
554
|
| --- | --- | --- | --- | --- |
|
|
484
555
|
| `check` | no blocking finding | at least one blocking finding | cannot evaluate: policy parse error, malformed `--diff` range, no view given, not a git repository, or an unresolvable revision — any failure the gate cannot recover from is one clean `tamperward: …` line on stderr at exit 2, never a stack trace at exit 1 | — |
|
|
485
556
|
| `verify` | `VERIFIED` — visible and pristine both green; or a `MASKED_FAILURE` cleared by an out-of-band `verify@<head-sha>` approval | `MASKED_FAILURE` (visible green, pristine red) or `SUITE_RED` | cannot verify, failing closed: no suite command, unresolvable base, `--require-ancestor` refused, budget exceeded, or the working or dependency tree moved during the run | — |
|
|
557
|
+
| `trace-verify` | all requested known-good traces exited 0; advisory report emitted | one or more traced verifier runs were non-zero/incomplete; report still emitted | unsupported platform, missing tracer/materialiser, bad base/policy/options, or tracing failure | — |
|
|
486
558
|
| `doctor` | configured verify job(s) have sufficient static outer time for the trusted policy | — | missing/invalid workflow, no verify job, missing/malformed/insufficient timeout, or trusted policy cannot be loaded | — |
|
|
487
559
|
| `run` | enforcement clean and the agent exited 0 — another non-zero agent exit is passed through unchanged | any blocking finding or masked failure, including a non-quiescent process after timeout | cannot adjudicate: dirty start, policy error, verify cannot run | `AGENT_TIMEOUT`: `--agent-budget` expired and post-timeout enforcement was clean |
|
|
488
560
|
| `hook claude` / `sweep claude` | always — a deny is JSON on stdout at exit 0, never exit 2 | — | only for an unsupported agent name | — |
|
|
@@ -591,8 +663,11 @@ and the posts in [docs/blog/](./docs/blog/index.md).
|
|
|
591
663
|
## Stability
|
|
592
664
|
|
|
593
665
|
The public surface is the CLI and its **exit codes**, the hook wire format, the
|
|
594
|
-
`.tamperward.yml` schema, and the
|
|
595
|
-
|
|
666
|
+
`.tamperward.yml` schema, and the versioned `check` / `verify` / `run` / `doctor`
|
|
667
|
+
machine-output schemas under `schemas/`. No `main`, no `exports` — it is a binary,
|
|
668
|
+
not a library. The machine-output schema major is intentionally independent of the npm
|
|
669
|
+
version: additive fields stay compatible within the major; breaking shape/semantic
|
|
670
|
+
changes require a new schema major. The version answers one question: *can taking this
|
|
596
671
|
upgrade turn a green build red without me changing anything?* **Patch never can** —
|
|
597
672
|
bypass fixes and false-positive fixes ship as patches so they reach you automatically.
|
|
598
673
|
Rule graduations (`warn` → `block`) are **opt-in**: they gate on the `version:` field in
|