#314 scrubbed BRAVE_API_KEY per test file, which leaves the next research
test free to reintroduce the leak. A bun test preload now deletes every
setting the research providers and the gateway backend read, for every run
started from the repo root. Tests that need one still set their own value.
- scripts/test-preload.ts: the scrub.
- bunfig.toml: [test] preload.
- core/test/clean-room.test.ts: a probe suite started with all six settings
exported must see none of them.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The 2.0.0-2.3.0 entries described the Phase 6-9 mechanisms as working
flows ("stop needing a human passphrase", "hot-swap its own binaries").
A symbol search over packages/*/src finds no caller for the machine key,
the staging pipeline, the prompt optimizer, the canary runner or lease
acquisition, and run-dag plus the canary live in the private fleet package.
- CHANGELOG: each intro now names what is reachable; 2.3.0 lists reachable,
library-only and not-in-npm pieces, and records that 1.6.1-2.2.0 were
never published and ship in 2.3.0.
- README status line: same correction.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
With BRAVE_API_KEY exported in the developer shell, fires-research and
research booted hosts whose provider chain reached the live Brave API
before the local SearXNG fake: six tests went red and each run spent the
real key. Both files now remove BRAVE_API_KEY and FIRECRAWL_API_KEY for
their lifetime and restore them afterwards, as failover-chain.test.ts
already does. The degradation block closes through bootHost's handle so
the restore runs there too.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
`bun run check` could not pass in a checkout that holds the gitignored
review/ reference repos. `biome check .` stopped on their nested root
configs, and the bare `packages/web` test filter also matched
review/*/packages/web, so third-party suites ran and the workspace suite
never started. CI and ticket worktrees have no review/, which hid it.
- package.json: the test script passes ./packages/<dir> paths, not filters.
- bunfig.toml: test discovery starts at packages/.
- biome.json: force-ignore review, evals/results and nested checkout roots.
- tsconfig.base.json: exclude review and evals/results.
- core/test/clean-room.test.ts: runs the real root config against a tree
with planted intruders, one test per layer.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
SonarCloud quality gate: extract roadmap task parsing (S3776),
flatten the result printer (S4624), plain comparisons (S1940), and
shared stuck-test fixtures to drop duplication under the gate.
Merge-time fallout, one group: audit tests that pinned pre-remediation
behavior, flipped to the enforced/fixed behavior per area (precedents:
a50ced8, 1112441, S5 9289804). No product changes.
- scout-194 (core + opencode): #257 enforcement — NK advisory-skip
claims in record paths; (a) rewritten to refusal-then-skip; (b)/(c)
keep documenting the open validation hole; legacy cache reads take
state (#251).
- gates-seeded (opencode): #223.2 — provisioned run driven to BUILD by
test-only state surgery (visibility sealState pattern) so finding
shapes run.
- web-json-headers: #282 fixed by S5 — absence pins flipped to presence
(file pre-authorized the flip).
- control-matrix (core): #216 G1 — uniform text-layer deny; backstop
set removed. (opencode symlink test stays red here: btrfs has no
overlay mounts so the sandbox falls back and the write lands —
environmental, unchanged by this work; CI runners enforce EROFS.)
- domainpacks-packs: #252 — dead SECONDARY_MEDIA weights gone, assert
absence.
- queereye-audit193: #266 hasOwn refusals + #270.1 missing-probes report.
- lsp-audit197: #277.2 injector scoping — lsp:none stays silent.
- slash-commands: #274 — deep args reach the deep flow.
- stage-order: #223.2 — direct + tool refusal pins.
- fires-domainpacks: #252 scorer clamp — tiered peer fixtures clear
0.7 honestly ((1+1+0.3)/3).
- evidence-187: #251 — legacy-reader line dropped (refusal above).
- S8 strictness: the named areas are green; config-layers 17/17, no
darkharvest/hooks/lsp JSON or needle fixtures exist under those
names — nothing left to apply.
Full suite: 1892 pass / 1 fail (the btrfs symlink env test above);
docs:check 0, deps:check 0, per-package tsc 0, biome 0.
Refs #179, Refs #257, Refs #223, Refs #282, Refs #216, Refs #252, Refs #266, Refs #270, Refs #277, Refs #274, Refs #251, Refs #190, Refs #187, Refs #194
Add/add conflict with the remediation branch: the audit side pauses the
dashboard RPC at each headline state (#199.2, #248.2/.3/.5, es_status);
the remediation side proves additive registration, server-computed
footer content and a project-tree-clean setup (#276). Fully disjoint
suites: concatenated with merged imports, the remediation fixture in
its own describe block so no lets, hooks or helpers were renamed.
visibility.test.ts 15/15, biome clean.
Refs #199, Refs #248, Refs #276
Content conflict on the #269.2 default-run pin: the branch captures the
default result/ideas before the grill run and asserts byte-equality
after; main asserted the hardcoded b001/17 shortlist. The branch form
is strictly stronger (true before/after isolation, no shared-harness
assumption), so the resolution keeps it and drops main's version. The
nested-refusal test arrives via the main side without conflict.
brainstorm.test.ts 5/5, biome clean.
Refs #191, Refs #269
Content conflict in the shell-policy screen: the branch pins a direct
named `es research export` denial for every agent kind (#255) where
main has the single-build-agent line. The loop subsumes the line, so
the resolution keeps the loop and drops the line.
Refs #189
Add/add conflicts with the remediation branch on both files. Unions keep
every test from both suites: pr-guard keeps the remediation refusal-order
proofs plus the audit bare-remote no-ref-moved proof (audit duplicate
guard tests dropped as subsumed); release.test.ts keeps the remediation
fast bare-remote fixture plus the audit full RELEASE-run end-to-end (its
sync git shim renamed to gitSync beside core's async git).
pr-guard.test.ts 6/6, release.test.ts 5/5, biome clean.
Refs #202, Refs #238
Add/add conflict with the remediation branch: both sides created
packages/cli/test/mcp-identity.test.ts. Union keeps every test from
both suites except three: the two exact-duplicate list/stdio tests
(subsumed by stronger twins) and the audit side's "server ignores
legacy ES_AGENT" assertion, which pins pre-remediation behavior — the
remediation pin order (ES_MCP_AGENT, else ES_AGENT, else defaultAgent)
reads it, proven by the pin-order test kept above.
mcp-identity.test.ts 32/32, biome clean.
Refs #201, Refs #230, Refs #232
Follow-up to the negative-cache fix: caching positives is stale the
other way — a PATH shim's finally-restore leaves the cached hit behind
and the next gate run spawns a binary that is gone (CI: cli.test.ts
gates run failed with `Executable not found in $PATH: gitleaks`).
installed() is a live PATH probe now; a probe is microseconds and gate
runs call it a handful of times. The unit test pins both directions
(miss→shim→seen→removed→miss).
TDD: CI run 38105290150 is the red witness for the stale-positive
direction; gates-seeded.test.ts 13/13 green locally after.
Refs #185
CI check on this PR failed its 2 gitleaks shape tests with empty
findings while the same file is green locally. Root cause is product,
not env: installed() cached the first answer per binary forever, so any
earlier gate run on a machine without gitleaks (CI runners) pinned
false and the PATH-shimmed shape tests below silently skipped the
scanner. Only positive answers are cached now; misses re-probe.
TDD: new unit test (miss, then shim onto PATH) red on the old cache,
green after. gates-seeded.test.ts 13/13. The 5 gates.test.ts failures
in this worktree are pre-existing env reds (btrfs sandbox, runner
tooling), identical with and without this change.
Refs #185
#212a: no `opencode` peer range can exist — verified 2026-10-11 that no
such npm package exists (registry 404; the host ships as @opencode/*
scope + platform binaries). Pinned: no manifest field names a bare
`opencode` dep, so the S7 triple-pin stays the mechanism by decision,
not by oversight.
#212c: published src trees are clean (only private web has src tests;
fleet+web privacy already pinned), and a new layout test fails on any
stray src test/spec file the manifest-string check cannot see —
proven red with a planted file. scripts/pack-smoke.sh exit 0 on this
tree and a tarball scan shows no test files (only product spec*.js).
TDD: planted-file mutation red; pack-pins.test.ts 6/6 green after
restore. #212.2/.4/.5 (names/versions, publish parsing, runtime
matrix) route to S9 per the file's standing note.
Refs #178
Co-Authored-By: Claude Opus 5.5 <[email protected]>
#263: the "eight lenses / forced outlier" wording already landed in the
brainstorm prompt + skill assets; the same claims in code said it
unconditionally. Mirrored verbatim: registry brainstormer description
(eight-lens registry; six by default, four lean for callable runs),
capability detail + schema header/field (forced outlier whenever the
shortlist has ≥2 slots). docs:gen regenerated CAPABILITIES.md
(committed together); docs:check, assets + capabilities suites, tsc
and biome green. No prompt touched, so no snapshot/version bump.
Refs #178, Refs #191
Co-Authored-By: Claude Opus 5.5 <[email protected]>
#277.3: the capability detail and the registry header said "lsp config
key", reading as an ES config key — but ES layers strict-reject it
(schema is .strict(), no top-level lsp; only lspAfterEdit). Both now
name v2's opencode.json explicitly. Regenerated docs/CAPABILITIES.md
via docs:gen (committed together); docs:check, capabilities suite,
tsc and biome green.
Refs #178
Co-Authored-By: Claude Opus 5.5 <[email protected]>
#240.3 takes the "document the gap" fork deliberately: pinning the
machine-scoped global layer into the per-project hash baseline would
drift whenever the human edits global settings for another project.
The PINNED comment states the design (global writes stay guarded by
the human-only config-set gate), and a control-baseline test pins it:
snapshots cover .factory/ files only, and a write to the global layer
(hermetic XDG) leaves the snapshot equal and verification clean.
TDD: pinning the global file turns the boundary test red; policy 61/61
green after restore. No behavior change.
Refs #178
Co-Authored-By: Claude Opus 5.5 <[email protected]>
#275.2 takes the "downgrade the claim" fork deliberately: sandboxing npm
through bwrap is unsound here (the fetch needs the network; bwrap is not
universally available, so a "preferred" sandbox would silently no-op).
The header now states the actual stack, and a fake-npm test pins it:
exact name@version fetch, SRI verification, install with
--no-save/--ignore-scripts/--no-audit/--no-fund, a scrubbed child env
(canary absent, registry override present), and pack/install confined
to scratch/target cwds. No product change beyond the header comment.
TDD: dropping --ignore-scripts turns the new pin red; lsp.test.ts 7/7
green after restore.
Refs #178
Co-Authored-By: Claude Opus 5.5 <[email protected]>
#251 ctor: the stateDir parameter is required and the unsealed branches
are gone from seal/sealed/writeIndex/readIndex. Production already
always sealed (researchCache defaults to the global state dir; the
src-wide misuse-guard test keeps it that way), so no product call site
changes — tsc green in all 6 packages.
Every legacy test construction is reworked so no test exercises the
removed path (grep-verified zero one-arg or explicit-undefined sites):
- research.test.ts: shared cache takes state; the forged-plant leg
hand-writes bytes (as put() lays them out minus the seal) and gains
an index-cannot-launder pin; the legacy-reader assertion is gone.
- source-seal.test.ts H3: the pre-sealing dossier is laid out directly
with its legacy ok-witness (writeDossier always verifies now and
could never produce one); exportBrief still refuses it.
- scout.test.ts, render.test.ts, fires-research.test.ts: pass state
(fires-research strips the seal when planting, premise unchanged).
- evidence-seal.test.ts: the unsealed-writes-no-sidecar leg is dropped
with the mode it tested.
- fleet evidence.test.ts rig: the "unsealed" explorer case is
hand-written bytes; seal-status assertions unchanged.
TDD witnesses: engine-seal/source-seal/evidence suites green
(research+seal+render+scout+fleet 70/70, fires-research 6/6); the
misuse-guard and full check suites re-verify at close-out. #251.1
(verifier fuzz corpus in CI) is out of scope here — it needs CI work.
Refs #178, Refs #52
Co-Authored-By: Claude Opus 5.5 <[email protected]>
#269.1: lens (es-lens-inversion) and critic seats cannot launch nested
subagents — same delegate call the grill completes at depth 1 errors
here with the host's tool-absent denial (empty spawns compiled to
wildcard-deny; the tool is never offered). The grill-vs-lens pair in
the same file is the live discriminator: subagent:completed for the
grill, subagent:error for lens/critic.
#269.2: the grill run's shortlist lands under runs/grill-fanout/ while
the human default run is re-read and asserted unchanged (the
brainstormer's b001/17 shortlist). Note: the issue asks for an
"undefined" default check, but this file boots one shared harness and
an earlier test completes default — so "untouched" is pinned as
unchanged, with the reason in the comment.
TDD (test-only, no product change): brainstorm.test.ts 5/5 green.
Refs #178, Refs #108
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Six items, test-only, no product change:
- STALE_AFTER_MS pinned to 600_000 with the stuck hint starting exactly
at the boundary (one ms under stays "in progress").
- Dashboard lead order asserted by index (headline before header).
- Non-RESEARCH stages print no research line (researchLine undefined).
- status/runs (text, --json, --all) snapshot-pinned read-only over
.factory and the state dir; a planted write turns the pin red.
- DONE-without-PR headline plus SPEC/RELEASE wording.
- Explicit es runs / es watch allow lines in the shell policy
(read-only views for build, factory and user agents); otherRunHint
window boundary (just inside / exactly at / outside), DONE,
equal-timestamp, same-root and stale-local edges.
TDD witnesses: planted-write mutation red, full files green after
restore (liveness+policy 80/80, cli 85/85).
Refs #178
Co-Authored-By: Claude Opus 5.5 <[email protected]>
#222.1: masked-input.tsx was proven only by the #118 spike prototype and a
scripted seam in approve-tui.test.ts. New masked-input.test.ts renders the
shipped component headlessly (test/render/masked-input.tsx, same
testRender+mockInput harness as panels): type 8 / backspace to 7 / retype
to 8 / Enter submits exactly s3cr3t-P; bracketed paste with an embedded
newline submits atomically stripped; Esc cancels with no submit. The
submit buffer is zeroed (live-ref length 0) and the post-submit frame is
bare; 11 captured frames contain no probe secret.
TDD (test-only, no product change): echoing plaintext instead of bullets
turns the leak audit red. Subprocess exit 0, 70 expects green after
restore.
#222.2 remainder: the attempts.ts bucket comment already matches
(842a8ad); only the ADR I4 normative line still said "per surface" —
now per-state-dir with the shared CLI/TUI bucket. #222.3 already holds:
ChannelSchema is cli/tui/web and I5 records it; no "terminal" channel
prose remains.
Refs #178, Refs #118, Refs #119
Co-Authored-By: Claude Opus 5.5 <[email protected]>
#221.2: approve, rebaseline and reseal had dedicated pipe tests; the rest
of the confirmHuman funnel did not. New "per-verb pipe refusal" block:
trust, waive, factory resume (seeded HALTED, stays halted), factory pr,
gates install-git, lsp install typescript (refuses before consent or
install), and audit open all refuse with exit 3 — which comes only from
the NotInteractive catch, so each assertion proves the terminal gate was
reached — and write nothing. es key seal gets the same pipe case
(direct NotInteractive throw, no key minted).
TDD (test-only, no product change): weakening the gate (throw to
return-undefined) turns all 7 new tests red; full cli.test.ts 83/83 green
after restore.
Refs #178
Co-Authored-By: Claude Opus 5.5 <[email protected]>
#221.1: an expired but validly-signed waiver planted at gate time waives
nothing (no waiver/invalid, secret still fires, waived 0, passed false);
a live-expiry control on the identical record waives, pinning the refusal
to the expiry. recordWaiver refuses past expiries, so the record is
hand-aged under the real human key.
#221.3: a forged trust entry is not trust — replayed/made-up/missing
signatures and a foreign-key signature all fail isTrusted and surface
trust/untrusted at gate time without running the command; the signature's
project+kind binding is pinned (moved entry verifies for neither), with a
control that the untouched entry in the same file still verifies.
Also makes the #227 stop-launch control test assert explicitly
(resolves.toBeUndefined), closing Sonar S2699 on PR #290.
TDD (test-only, no product change): mutation witnesses — weakening
isWaiverActive (&& to ||) turns #221.1 red; trusting any hash-matching
entry turns #221.3 red. Targeted suites green after restore.
Refs #178, Refs #227
Co-Authored-By: Claude Opus 5.5 <[email protected]>
#220.2 asked for a `patch` branch in evaluate(). The v2 host has no such
permission action: its patch tool asserts `edit` once with every target
(add, update, delete, move) as the resources, so the existing edit branch
is the allow side. No product change beyond a comment saying so.
What was missing is the proof, on both sides. The host offers `patch`
only to a model id containing `gpt-`; the testkit's `fake/scripted` never
gets the tool, so the patch legs in plugin.test.ts pass on "Tool is not
available for this request", not on the policy. The testkit now takes a
`model` id, and patch-scope.test.ts runs on `gpt-scripted`:
- before(): in-scope patch passes; out-of-scope add/delete/move and
control-file targets refuse (seat and user agent)
- evaluate(): multi-resource edit is allowed for an in-scope seat, denied
with the target's reason otherwise; an unknown `patch` action fails closed
- real host: in-scope seat patches land, mixed/move/control-file/read-only
patches are refused by the policy text and write nothing
Mutation-checked: dropping before()'s patch loop or evaluate()'s deny
turns the matching tests red.
Refs #178
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The section regex added for #270 (`/## Slots\n([\s\S]*?)(?:\n## |\s*$)/`)
was quadratic on a whitespace run that does not reach the end of the file:
CodeQL js/polynomial-redos on PR #290 (1.2s at 40k tabs, 7.6s at 100k).
The bytes come from the bundle on disk, not from the renderer.
Cut the section with indexOf/trimEnd instead. Same result on the three
pinned edge cases and on 200k generated inputs against the old regex.
TDD: linear-time regression test (1s bound) red at 7579ms, green at ~0ms.
Refs #178, Refs #270
Co-Authored-By: Claude Opus 5.5 <[email protected]>