tamperward 2.16.4 → 2.16.5

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 CHANGED
@@ -223,9 +223,31 @@ verifier's `--budget`). A clean timeout is `AGENT_TIMEOUT` / exit 124; enforceme
223
223
  cannot-adjudicate still outranks it. **From 2.16.4, `tamperward run` is Linux-only
224
224
  for authoritative lifecycle certification.** Windows, macOS and other non-Linux platforms
225
225
  fail closed before the agent starts because this release has no OS primitive there that can
226
- prove the detached execution domain is drained. Standalone `tamperward check` and
227
- `tamperward verify` remain available on those platforms. Dependency-attestation reuse
228
- remains disabled on all platforms.
226
+ prove the detached execution domain is drained. From **2.16.5**, checkpointed-local
227
+ `tamperward verify` also has an explicit host-shell contract: Linux, macOS and the
228
+ supported POSIX Node platforms use `/bin/sh -c`; Windows local verification fails closed
229
+ before candidate execution rather than depending on an incidental MSYS/Git-for-Windows
230
+ `sh` on PATH. A digest-pinned container verifier is a separate backend and must pass its
231
+ own Docker authority preflight. Dependency-attestation reuse remains disabled on all
232
+ platforms.
233
+
234
+ ### Platform support
235
+
236
+ | Capability | Linux | macOS | Windows |
237
+ | --- | --- | --- | --- |
238
+ | `check` / policy evaluation | Supported | Supported | Supported |
239
+ | Claude hook / Stop adapter | Supported where Claude Code command hooks are available | Same | Same |
240
+ | `watch` / observer telemetry | Supported; backend health is reported | Supported/degraded according to `fs.watch` health | Supported/degraded according to `fs.watch` health |
241
+ | checkpointed-local `verify` | Supported via `/bin/sh` | Supported via `/bin/sh` | **Unsupported; fails before candidate execution** |
242
+ | isolated-container `verify` | Supported when Docker authority preflight passes | Not claimed beyond Docker preflight | Not claimed beyond Docker preflight |
243
+ | authoritative `run` | **Supported only with trusted non-root subreaper backend** | **Unsupported; fails before agent start** | **Unsupported; fails before agent start** |
244
+ | CI coverage for this contract | Full suite + platform contract | Platform-contract job | Platform-contract job |
245
+
246
+ The platform-contract CI job runs on real `ubuntu-latest`, `macos-latest` and
247
+ `windows-latest` hosts. It verifies the declared shell/lifecycle selection and proves
248
+ that Windows local verification refuses before a candidate command can produce a side
249
+ effect. This matrix is intentionally narrower than the Linux adversarial suite; it tests
250
+ the support boundary rather than implying feature parity where none is claimed.
229
251
 
230
252
  `tamperward verify` materialises two temporary copies — they are **not
231
253
  sandboxes**, and both execute agent-controlled code. The visible copy runs the
package/dist/cli/index.js CHANGED
@@ -10218,15 +10218,37 @@ function suiteEnv(scratch) {
10218
10218
  env.YARN_IGNORE_PATH = "1";
10219
10219
  return env;
10220
10220
  }
10221
+ function localVerifierShell(platform = process.platform, command) {
10222
+ switch (platform) {
10223
+ case "linux":
10224
+ case "darwin":
10225
+ case "freebsd":
10226
+ case "openbsd":
10227
+ case "aix":
10228
+ case "sunos":
10229
+ return { executable: "/bin/sh", args: ["-c", command] };
10230
+ default:
10231
+ return null;
10232
+ }
10233
+ }
10221
10234
  function runLocalSuite(dir, cmd, budgetSecs) {
10222
10235
  const t0 = Date.now();
10236
+ const shell = localVerifierShell(process.platform, cmd);
10237
+ if (!shell) {
10238
+ return {
10239
+ exit: null,
10240
+ secs: 0,
10241
+ failure: "backend",
10242
+ reason: `checkpointed-local verifier is unsupported on ${process.platform}; no trusted local shell contract is defined`
10243
+ };
10244
+ }
10223
10245
  const scratch = mkdtempSync3(join16(tmpdir3(), "tw-verify-run-"));
10224
10246
  try {
10225
- const r = runCapturedProcessSync("sh", ["-c", cmd], {
10247
+ const r = runCapturedProcessSync(shell.executable, shell.args, {
10226
10248
  cwd: dir,
10227
10249
  env: suiteEnv(scratch),
10228
10250
  timeoutMs: budgetSecs * 1e3,
10229
- detached: process.platform !== "win32",
10251
+ detached: true,
10230
10252
  killGroupOnFinish: true,
10231
10253
  backstopMs: 3e4
10232
10254
  });
@@ -10339,6 +10361,22 @@ function runVerify(opts) {
10339
10361
  return 2;
10340
10362
  }
10341
10363
  const isolated = verifierBackend.kind === "container";
10364
+ if (!isolated && !localVerifierShell(process.platform, cmd)) {
10365
+ if (opts.json) {
10366
+ out2(JSON.stringify({
10367
+ verdict: "CANNOT_VERIFY",
10368
+ reason: "LOCAL_VERIFIER_UNSUPPORTED_PLATFORM",
10369
+ platform: process.platform,
10370
+ verifier_backend: backendReport(),
10371
+ oracle_assurance: oracleAssuranceReport()
10372
+ }));
10373
+ } else {
10374
+ out2(
10375
+ `verify: checkpointed-local verifier is unsupported on ${process.platform}; no trusted local shell contract is defined. Failing closed before candidate execution.`
10376
+ );
10377
+ }
10378
+ return 2;
10379
+ }
10342
10380
  const dependencyEnvironment = isolated ? null : opts.dependencyEnvironment ?? discoverDependencyEnvironment(cwd, cmd);
10343
10381
  const dependencyReport = () => dependencyEnvironment ? dependencyEnvironmentReport(dependencyEnvironment) : {
10344
10382
  status: "verifier-owned",
@@ -10604,6 +10642,12 @@ var err = (s) => process.stderr.write(s + "\n");
10604
10642
  function authoritativeRunLifecyclePlatform(platform = process.platform) {
10605
10643
  return platform === "linux";
10606
10644
  }
10645
+ function waitForSettleSync(seconds) {
10646
+ if (!Number.isFinite(seconds) || seconds <= 0) return;
10647
+ const ms = Math.ceil(seconds * 1e3);
10648
+ const word = new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT));
10649
+ Atomics.wait(word, 0, 0, ms);
10650
+ }
10607
10651
  function canReuseAdjacentDependencyAttestation(_lifecycleOwned, _platform = process.platform) {
10608
10652
  return false;
10609
10653
  }
@@ -11216,8 +11260,9 @@ function runEnvelope(opts) {
11216
11260
  }
11217
11261
  const lifecyclePlatform = opts.lifecyclePlatformOverride ?? process.platform;
11218
11262
  if (!authoritativeRunLifecyclePlatform(lifecyclePlatform)) {
11263
+ const alternative = lifecyclePlatform === "win32" ? "Use standalone tamperward check; checkpointed-local verify is unsupported on Windows, while container verify must pass its own Docker authority preflight." : "Use standalone tamperward check/verify or an isolated execution domain.";
11219
11264
  err(
11220
- `tamperward run: authoritative agent lifecycle ownership is unavailable on ${lifecyclePlatform}; this release only certifies run on Linux with the trusted subreaper/ECHILD backend. Failing closed before the agent starts. Use standalone tamperward check/verify or an isolated execution domain.`
11265
+ `tamperward run: authoritative agent lifecycle ownership is unavailable on ${lifecyclePlatform}; this release only certifies run on Linux with the trusted subreaper/ECHILD backend. Failing closed before the agent starts. ${alternative}`
11221
11266
  );
11222
11267
  return 2;
11223
11268
  }
@@ -11339,10 +11384,7 @@ tamperward run \u2014 agent exit ${agentExit}; DEPENDENCY_DRIFT \u2192 ENFORCEME
11339
11384
  verifierBackend
11340
11385
  });
11341
11386
  if (opts.settle && opts.settle > 0) {
11342
- try {
11343
- execFileSync9("sleep", [String(opts.settle)]);
11344
- } catch {
11345
- }
11387
+ waitForSettleSync(opts.settle);
11346
11388
  }
11347
11389
  const mutatedDuringAdjudication = treeFingerprint(cwd, protectedIgnored) !== fpBefore;
11348
11390
  if (mutatedDuringAdjudication) {
@@ -11438,7 +11480,7 @@ function lifecyclePlatformCheck(platform = process.platform, linuxPython = platf
11438
11480
  return {
11439
11481
  id: "platform",
11440
11482
  state: "BROKEN",
11441
- detail: "Windows: authoritative tamperward run lifecycle ownership is unavailable; taskkill /T /F is only a best-effort tree fallback, so run fails closed before agent start. Standalone check/verify remain available."
11483
+ detail: "Windows: authoritative tamperward run lifecycle ownership is unavailable; taskkill /T /F is only a best-effort tree fallback, so run fails closed before agent start. Standalone check remains available; checkpointed-local verify is unsupported because this release defines verifier command semantics only through POSIX /bin/sh. A container verifier must pass its own Docker authority preflight."
11442
11484
  };
11443
11485
  }
11444
11486
  return {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tamperward",
3
- "version": "2.16.4",
3
+ "version": "2.16.5",
4
4
  "description": "The deterministic agent-integrity gate. One ruleset, evaluated on the actual diff/commands as a verdict, enforced everywhere a change can be made.",
5
5
  "license": "Apache-2.0",
6
6
  "author": "hexrift",