tamperward 2.16.1 → 2.16.3

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.
Files changed (3) hide show
  1. package/README.md +41 -9
  2. package/dist/cli/index.js +2992 -2717
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -144,6 +144,18 @@ Before starting the agent, the envelope
144
144
  3. records the installed `node_modules` content fingerprint, where one exists; and
145
145
  4. refuses an already-dirty tree unless the operator explicitly accepts the risk.
146
146
 
147
+ **2.16.3 deliberately disables the 2.16.2 run→verify dependency-attestation reuse.**
148
+ The envelope still takes a complete dependency checkpoint immediately before `runVerify`,
149
+ and the nested verifier independently takes its own entry checkpoint. A clean local run
150
+ therefore performs **6 complete dependency snapshots and 0 reused snapshots** on every
151
+ platform and lifecycle outcome. The optimization is not re-enabled merely because Linux
152
+ established descendant ownership: an independent verifier-entry read is a clearer trust
153
+ boundary than coupling dependency integrity to same-UID lifecycle supervision. The checks
154
+ after visible execution, after pristine execution, and at the envelope's final quiescence
155
+ boundary remain independent full reads as well. Set `TAMPERWARD_DIAGNOSTICS=1` to report
156
+ `full_snapshots`, `reused_snapshots`, aggregate snapshot wall time, lifecycle ownership,
157
+ and `entry_reuse=no`.
158
+
147
159
  The hooks then steer the agent while it works: they read live state, deny known
148
160
  weakening operations, detect protected-tree drift, and sweep the turn's net
149
161
  changes. The `Stop` hook runs that sweep — it does **not** invoke `verify`.
@@ -184,15 +196,35 @@ After the runtime exits its exit code is treated as untrusted, and the envelope
184
196
  checks that post-agent `HEAD` still descends from the entry commit; the committed
185
197
  changes over `entry...HEAD`; staged, unstaged and untracked non-ignored worktree
186
198
  changes; dependency drift and whether the tree stayed quiescent; and the
187
- verification outcome. For agent runtimes that may hang, `--agent-budget <seconds>`
188
- adds an operator-owned wall-clock boundary around the **agent itself** (separate from
189
- the verifier's `--budget`). On expiry TamperWard terminates the owned process tree,
190
- then still performs the same post-timeout adjudication. A clean timeout is
191
- `AGENT_TIMEOUT` / exit 124; any enforcement failure or cannot-adjudicate result
192
- still outranks that runtime status. On POSIX the agent starts in its own process
193
- group; on Linux the timeout also enumerates the agent's `/proc` descendant tree so
194
- a child that escaped the group with `setsid()` is terminated before adjudication.
195
- Windows uses `taskkill /T /F` as the explicit process-tree fallback.
199
+ verification outcome. Since **2.16.3**, every wrapped agent goes through a lifecycle
200
+ supervisor even when no runtime budget is requested. Ordinary POSIX descendants remain in
201
+ an owned process group. On Linux the stronger boundary uses a fixed, non-caller-writable
202
+ system `python3` launched with isolated startup (`-I -S -E`), supervisor cwd `/`, and a
203
+ minimal supervisor environment; the agent receives its separately frozen original cwd and
204
+ environment. The supervisor sets `PR_SET_CHILD_SUBREAPER`, so orphaned descendants from
205
+ double-fork/`setsid()` are reparented to it by the kernel. Before adjudication begins it
206
+ kills the agent process group plus adopted children and does not report lifecycle ownership
207
+ until `waitpid(-1, WNOHANG)` reaches the kernel **ECHILD** condition. An unreadable child
208
+ list, failed kill, abnormal supervisor exit, unavailable trusted interpreter, or drain
209
+ deadline fails closed before adjudication. The same-UID result file is evidence only after
210
+ normal supervisor completion, so forging it and killing the supervisor cannot manufacture a
211
+ trusted lifecycle result.
212
+
213
+ Linux therefore requires Python 3 with the standard `ctypes`/process modules available at
214
+ a fixed trusted system path; TamperWard does not resolve this supervisor through candidate
215
+ `PATH`, `PYTHONPATH`, user site-packages, or candidate cwd. **Linux `tamperward run`
216
+ also refuses to start when the caller's uid or effective uid is 0/root.** Root can write
217
+ ordinary system interpreter paths, so the same-UID trust argument used by this lifecycle
218
+ backend is not meaningful there. `tamperward doctor` reports this explicitly as a
219
+ BROKEN platform posture rather than misdiagnosing it as a missing Python installation.
220
+ `--agent-budget <seconds>`
221
+ adds an operator-owned wall-clock boundary around the same lifecycle (separate from the
222
+ verifier's `--budget`). A clean timeout is `AGENT_TIMEOUT` / exit 124; enforcement or
223
+ cannot-adjudicate still outranks it. Windows retains `taskkill /T /F`; other non-Linux
224
+ platforms retain process-group/fingerprint/quiescence safeguards but do not claim the Linux
225
+ subreaper boundary. A detached process that escapes those weaker platform controls remains
226
+ an explicit residual tracked in **#379**, not part of the Linux guarantee.
227
+ Dependency-attestation reuse remains disabled on all platforms.
196
228
 
197
229
  `tamperward verify` materialises two temporary copies — they are **not
198
230
  sandboxes**, and both execute agent-controlled code. The visible copy runs the