Commit Graph
100 Commits
Author SHA1 Message Date
3e19454bd4 feat(ops): add portable strict War Room preflight (#56)
* feat(ops): add portable War Room preflight command

Add npm run ops:preflight that checks operational readiness before
launching a War Room mission: API health, active mission status,
pending action receipts, local-agent/provider configuration, and
arsenal tool availability. Follows same pattern as scripts/doctor.mjs.

Supports --json for machine-readable output and --strict to fail
on warnings.

Fixes #35

Signed-off-by: Shivam Singh <shivamsingh-007@users.noreply.github.com>

* chore: revert package-lock.json churn to reduce diff noise

Restores package-lock.json to upstream main version.
Removes unintended npm-version lockfile rewrite (peer flips, @emnapi/* entry shifts).

* fix(ops-preflight): correct response-shape reads for mission, approvals, and agent checks

Three bugs identified by jmagly in review:
1. Mission-active: API returns {active: boolean}, not {phase}
2. Pending-approvals: API returns {approvals: [...]}, not a flat array
3. Local-agent: API returns {connected: [...]} (array), not a boolean

All three verified against live endpoints per review feedback.

Signed-off-by: Shivam Singh <shivamsingh-007@users.noreply.github.com>

* fix(ops): harden portable preflight checks

Signed-off-by: Joseph Magly <1159087+jmagly@users.noreply.github.com>

---------

Signed-off-by: Shivam Singh <shivamsingh-007@users.noreply.github.com>
Signed-off-by: Joseph Magly <1159087+jmagly@users.noreply.github.com>
Co-authored-by: Shivam Singh <shivamsingh-007@users.noreply.github.com>
Co-authored-by: Joseph Magly <1159087+jmagly@users.noreply.github.com>
2026-07-15 21:59:27 -04:00
Joseph MaglyandWibias 916c260fd8 feat: add safe cross-platform upstream updater (#98)
* feat: add safe upstream update scripts

* fix(updater): use portable PowerShell temp path

---------

Co-authored-by: Wibias <37517432+Wibias@users.noreply.github.com>
2026-07-15 19:56:25 -04:00
Junaid Y. SheikhandClaude Opus 4.8 266655abcf fix(ui): separate tour control and add theme switcher (#22)
Two War Room UI fixes (docs/index.html):

1. The floating "guided tour" relaunch button (#t3mpTourRelaunch) was
   position:fixed pinned bottom-left, landing on top of the sidebar
   "Connected" status pill and hiding its first character. Moved it to
   bottom-right (the conventional help-FAB corner) so it collides with
   nothing.

2. Added a theme switcher in the sidebar footer with four themes: Storm
   (the existing teal/green default, visually unchanged), Ember (amber),
   Crimson (red), and Void (violet). The choice persists in localStorage
   and is applied before first paint to avoid a flash of the default theme.

   To make themes reskin the whole UI rather than only the ~87 var(--accent)
   sites, the dominant hardcoded brand colors (#00ff88 / #2fffd2 / #00d4ff
   and their rgba() forms) were converted to CSS variables -- but only
   inside <style> and inline style="..." attributes, where var() is valid.
   Bare JS string literals and SVG fill= attributes are left as-is; most are
   semantic status colors (green=ready, red=error) that should stay fixed.

No JS logic changed; the page renders and all scripts run unchanged.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 19:51:58 -04:00
Joseph MaglyandPazificateur69 cf0090adf4 feat(arsenal): add source and supply-chain parsers (#97)
Follow-up to the JSON-scanner parser layer: wire semgrep, gitleaks, trivy and
grype into parseToolOutput so their findings become structured, gate-verifiable
evidence instead of raw text (they were parserStatus:'planned').

- semgrep  (scan --json)          → one finding per rule match; ERROR/WARNING/INFO
                                     mapped to severity; CWE token pulled from
                                     metadata (e.g. "CWE-78: …" → CWE-78); refs → remediation.
- trivy    (fs --format json)     → one finding per package vuln; CVE + CweIDs +
                                     "upgrade <pkg> to <fixed>" remediation.
- grype    (dir:. -o json)        → one finding per match; CVE + package coordinates.
- gitleaks (detect --report json --redact) → one high finding per secret. Defence in
                                     depth: the details are run through redactString()
                                     so a raw secret can NEVER reach a finding / the vault,
                                     even though the adapter already passes --redact.

Broadens the severity map to cover scanner vocabularies (ERROR/WARNING, CRITICAL…
NEGLIGIBLE, moderate) onto the five canonical levels. Flips parserStatus to
'structured' for the four tools. Extends parsers.test.ts + fixtures: field mapping,
the gitleaks redaction guarantee, and the end-to-end gate pass for every new scanner.

Stacked on the parser layer (#42); pairs with the scanner-invocation fix (#40) that
gives these tools the JSON-emitting arg templates. Until #40 lands the parsers simply
degrade to [] (no JSON to parse) — no misbehaviour. Secret scanners beyond gitleaks
and SARIF-style tools remain a follow-up.

Co-authored-by: Pazificateur69 <agagliardi@guardiaschool.fr>
2026-07-15 19:45:58 -04:00
Pazificateur69 f8c283377c feat(arsenal): parse scanner JSON into structured findings (#42)
The generic adapter factory returned raw stdout only (`adapter-tools.ts` success
path), so 35 catalogued scanners with `parserStatus: 'planned'` never populated the
structured `ToolResult.findings` channel — their output was dropped on the floor and
the agent could neither verify nor chain on it. The whole downstream pipe already
exists and is honest-by-construction: the agent loop stamps `provenance:'tool'` + the
raw output, the operator materialises each finding with output-evidence, and the live
gate (`evidence/gate.ts`) marks it verified.

Add `src/arsenal/parsers.ts` — `parseToolOutput(toolId, rawStdout) → ToolFinding[]`
for the five scanners that already emit machine-readable JSON via their existing arg
templates (zero template changes): nuclei (-jsonl), httpx (-json), dalfox (--format
json), ffuf (-of json), katana (-jsonl). Parsers are pure, dependency-free, and NEVER
throw: empty/garbled/unknown input yields `[]`, never a fabricated finding (same
discipline as stub-honesty / no-phantom-tools). The factory attaches parsed findings
while ALWAYS keeping the raw stdout as `output` — the evidence of record the gate checks.

- nuclei/dalfox emit CWE, which the tool channel dropped: add optional `cwe?: string[]`
  to `ToolFinding` and thread it through the operator's finding materialisation.
- flip `parserStatus: 'planned' → 'structured'` for httpx, dalfox, katana (nuclei/ffuf
  were already structured).

Adds `src/__tests__/parsers.test.ts` + fixtures: per-scanner field mapping, the
honesty contract (empty/garbled/adversarial → [], no throw), a factory-wiring check
that a minted adapter returns findings while preserving raw stdout, and an end-to-end
assertion that every parsed finding PASSES `gateLiveFinding` with provenance='tool'.

The minted-adapter path is gated behind T3MP3ST_FULL_ARSENAL, so the benchmarked
default arsenal is untouched. Supply-chain JSON tools (semgrep/gitleaks/trivy/grype)
and secret scanners (need redaction) are a clean follow-up.
2026-07-15 19:43:51 -04:00
Reuben BowlbyandClaude 0f3213b310 docs: add contribution receipt template (#29)
Co-authored-by: Claude (agent) <238336761+hummbl-dev@users.noreply.github.com>
2026-07-15 19:42:38 -04:00
adrianwandCodex 089591b18f feat(scan): add live progress and recon bootstrap (#81)
* Add live scan progress view

* Make local-agent recon report real tool progress

* Feed recon bootstrap into local agent ReAct loop

* Remove stale local-agent JSON tool parser

* Label backend-seeded scan progress

---------

Co-authored-by: Codex <codex@openai.com>
2026-07-15 19:42:20 -04:00
Junaid Y. SheikhandClaude Opus 4.8 8959a288e5 fix(ui): reset War Room after declined or aborted hunt (#63)
* fix(ui): reset War Room to idle when a hunt is declined or aborted

A declined-approval hunt ("hunt not started") — or the red-X abort — left the
War Room stuck advertising an active run: the ENGAGE button stayed on the
"ENGAGING…" spinner (disabled), the LIVE fidelity banner kept claiming "real
tools probing the target", and the narration rail kept showing "Looking at your
target". completeMission() only toggled the button's display, never restoring
its label/disabled/opacity, and never cleared the fidelity banner or narration
rail; abortMission() had the same gap and no-op'd entirely when nothing was
"running" (so the red X did nothing on a declined hunt).

Add resetEngageUI(): restores the ENGAGE button (▶ ENGAGE, enabled) and clears
the fidelity banner (setFidelity('off')) + narration rail. Route both
completeMission() and abortMission() through it, and let the red X clear a
leftover engaging/probing UI even when missionRunning is already false.

Client-side only; no behavior change to an actually-running mission.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(ui): clear stale substatus when the red X resets an idle War Room

Review nit: the idle-abort branch set cmdMissionName='STANDBY' but left
cmdMissionStatus unchanged, so after an approval-declined the header could read
STANDBY with a stale red "approval declined" line beneath it. Reset the
substatus to the initial idle state ("Awaiting orders", #666) too.

Verified: abort after a decline now shows STANDBY / "Awaiting orders" (grey).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 19:41:11 -04:00
Junaid Y. SheikhandClaude Opus 4.8 168f7df62c fix(ui): route OBSIDIVM benchmarks through any backend (#64)
* fix(ui): route OBSIDIVM benchmarks through any backend, not OpenRouter-only

The OBSIDIVM benchmark/self-improvement UI ran its own client-side,
OpenRouter-only LLM path: getApiKey() read only the OpenRouter key, every
call hardcoded openrouter.ai, and the gate hard-blocked with "Configure
OpenRouter API key first" — so a configured Venice key was ignored and a
connected local agent was never used.

Add a client-side backend resolver (OpenRouter key -> Venice key -> connected
agent -> server LLM) and route all benchmark executors, judges, and gates
through it:

- resolveLLMBackend() + LLM_BACKEND_HINT; safeLLMCall()/_safeLLMCallOnce()
  become backend-aware (Venice uses api.venice.ai with a Venice-valid model;
  OpenRouter unchanged). _backendCall() routes keyless backends through the
  existing server endpoints: /api/agents/local/dispatch (drives the connected
  Claude Code/Codex/Hermes agent) and /api/llm/chat (server LLM).
- runLiveBenchmark, ctfCallLLM, the self-improvement analyzer, and the config
  optimizer now call safeLLMCall instead of a hardcoded openrouter.ai fetch.
- Live-Test / improvement-loop gates and runLLMJudge accept any backend.

Client-side only; no server changes (endpoints already existed). The
recon-only SPECTRA helper is intentionally left OpenRouter-only (out of scope).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(ui): keyless routing must use the API base URL (cross-origin) + model consistency

Addresses review feedback on the OBSIDIVM backend-routing PR.

1. Relative keyless URLs broke the primary cross-origin deployment. _backendCall
   fetched '/api/agents/local/dispatch' and '/api/llm/chat' as RELATIVE URLs, but
   when the static War Room (GitHub Pages docs/) talks to a separate backend the
   app sets T3MP3ST_API.baseUrl = http://<host>:3333. There the relative fetches
   hit the Pages origin → 404/CORS, so the headline local-agent / server-LLM
   routing silently failed (worked only same-origin). Fix: prefix
   `${T3MP3ST_API.baseUrl}` on both; empty base stays relative for same-origin.
   Verified: with baseUrl set, both now resolve to http://<host>:3333/api/...

2. Model default consistency. Four benchmark fallbacks read
   'anthropic/claude-opus-4.8', out of step with the state default, the <option>,
   renderModels and saveApiKey (all 'claude-opus-4.6'). Reverted to 4.6 to match.

(The /api/agents/local/dispatch server route exists — src/server.ts.)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(ui): backend-aware gates on the last OpenRouter-only benchmark paths

Addresses the re-review on this PR: two flows this PR claims support Venice /
connected local agent / server LLM still hard-gated on an OpenRouter key.

1. runSingleBenchTest() (single benchmark click): replaced the getApiKey()
   length check with `resolveLLMBackend().kind === 'none'` (+ LLM_BACKEND_HINT),
   matching runBenchmarks('live'). A Venice-only / agent / server backend can now
   click-run a single test instead of being blocked before safeLLMCall().

2. Self-improvement auto-apply:
   - autoApplyForLoop() now falls back to applyFallbackImprovements() only when
     NO backend exists (resolveLLMBackend().kind === 'none'), not merely when the
     OpenRouter key is empty — so the optimizer step uses Venice/agent/server.
   - autoApplyRecommendations() entry gate uses the backend check.
   - The Auto-Apply button show/hide (displayAnalysis) uses `hasBackend =
     resolveLLMBackend().kind !== 'none'` instead of an OpenRouter-only key test.

Verified: gates pass for venice/agent/server, block only when kind==='none';
node --check clean on the inline scripts.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 19:40:46 -04:00
Junaid Y. SheikhandClaude Opus 4.8 8e436d0da2 fix(ui): preserve server-reported live agent count (#71)
The Settings agent card's render() set window.__t3mpLiveAgents from CLIENT-side
pings only (Object.keys(pingStatus).filter(ok)). Agents connected server-side —
via autoReconnect (ping:false) or a status?check=1 re-ping — are live on the
server even though this client never pinged them, so every re-render reset the
count to 0. Since upstream's t3mpHasBackend() is now `llmAvailable || live > 0`,
that clobber made the War Room show "No LLM backbone — connect an agent before
hunting" on localhost even with a genuinely-live local agent (repro: 3 agents
connected, hermes lastPing.ok on the server, yet hasBackend=false after any
detect/render).

Fix: live = max(client-pinged-ok, server-reported-live), reading the server's
own agent state (window.__t3mpServerAgents, refreshed via status?check=1). The
summary and the global now both reflect reality and re-renders no longer break
the gate. Verified: hasBackend stays true across detect/connect re-renders.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 19:40:26 -04:00
Lyubomir Bozhinov 5b4ac700ad fix(agents): detect local CLIs via well-known install dirs (#83)
A T3MP3ST server launched from Finder, the desktop app, or any non-interactive
shell inherits launchd's minimal PATH (/usr/bin:/bin:/usr/sbin:/sbin). The
local-agent detector resolved `claude`/`codex`/`hermes` against that PATH via
execFile, so an installed, authed CLI in ~/.local/bin (Claude Code's native
installer), Homebrew, npm-global, or a version-manager shim (mise/nvm/fnm) threw
ENOENT and was reported installed:false — the Settings "Connect Local Agents"
checkboxes went dead and it read like a UI bug.

Add resolveBin(): pure-fs (no shell) resolution over PATH plus a curated set of
well-known install dirs under the real agent home (agentHome(), so a HOME
redirect can't hide them), with an executable-file access check and fail-open to
the bare name — an unresolved name yields the same ENOENT → installed:false as
before, so true-absence detection is unchanged. Route the detector and both spawn
sites (runLocalAgent, localAgentChat) through it, so a CLI detected under a
minimal PATH also actually spawns. Bound the keychain auth-probe with a 2s
timeout so a locked/headless keychain (the same non-interactive launch context)
can't hang detection.

POSIX/macOS-scoped: resolveBin short-circuits on win32 — Windows resolution
(where.exe / .cmd shims) is handled by the complementary open PR #18.

Verified on macOS: RED->GREEN unit + integration tests (resolver, detector
wiring, and both spawn sites), and manual QA driving the real Web UI under a
reproduced minimal PATH (Claude Code flips from "Not installed" to detected).

Refs #78 — fixes the macOS/POSIX variant. The original report was a Windows
Sandbox environment (PR #18's domain), so this intentionally does not auto-close
that issue.
2026-07-15 19:39:59 -04:00
Joseph Magly db2d270af5 fix(server): avoid caller cwd dotenv loading (#96) 2026-07-15 19:39:12 -04:00
Joseph Magly 51f610f3a5 fix(local-agents): support current Codex exec CLI (#95) 2026-07-15 19:09:34 -04:00
Joseph Magly 4b81bf6436 fix(local): honor server LLM for keyless missions 2026-07-15 18:13:27 -04:00
Joseph Magly 600f43b8b1 fix(local): merge system prompts for vLLM 2026-07-15 18:13:00 -04:00
Eddy 25f86b0c66 fix: reject curl destination override flags
* fix: reject curl destination override flags

* fix: block additional curl target bypass forms
2026-07-15 18:12:35 -04:00
Joseph Magly 84fcef5428 fix: clarify local LLM setup 2026-07-15 18:12:12 -04:00
Joseph Magly 6a2834e6c9 docs: add PR delivery procedure 2026-07-15 18:11:02 -04:00
Joseph Magly e1ced2307a Merge pull request #93 from jmagly/feat/t3mp3st-maintainer-addon
chore(aiwg): add T3MP3ST maintainer addon
2026-07-15 17:21:42 -04:00
Joseph Magly ec91b0d08d docs(aiwg): add public input threat preflight 2026-07-15 17:16:14 -04:00
Joseph Magly 40199beff2 chore(aiwg): restrict tracked aiwg paths to addons 2026-07-15 17:05:45 -04:00
Joseph Magly 751707bac1 docs(aiwg): add maintainer output templates 2026-07-15 17:01:29 -04:00
Joseph Magly 400e9e6d24 chore(aiwg): add T3MP3ST maintainer addon 2026-07-15 16:43:49 -04:00
pliny ae32cf5051 Merge pull request #54 from Pazificateur69/feat/arsenal-re-analysis-invocations
feat(arsenal): real invocations for the reverse-engineering / mobile / smart-contract analysis loadout
2026-07-09 08:51:34 -04:00
pliny 30aa72d98c Merge pull request #58 from jmagly/fix/readme-tempest-config-command
docs(readme): fix local-LLM setup command (npx tempest config → npx tempest)
2026-07-09 08:50:54 -04:00
pliny 808ce114fc Merge pull request #57 from jmagly/fix/gemini-native-provider
feat(llm): native Google Gemini provider via OpenAI-compatible endpoint
2026-07-09 08:50:39 -04:00
Joseph Magly 267eefcc46 docs(readme): fix local-LLM setup command (npx tempest config → npx tempest)
The quickstart tells users to run `npx tempest config` to switch to the local
provider, but there is no `config` subcommand — the CLI exposes `interactive`
(default), `setup`, `status`, `test`, and `models`. The "Change default
provider" flow lives in the default `interactive` command, so the correct
invocation is `npx tempest`.
2026-07-08 13:19:03 -04:00
Joseph Magly 5e40e60f47 feat(llm): native Google Gemini provider via OpenAI-compatible endpoint
Add a first-class `gemini` provider so operators can drive missions with a
direct GEMINI_API_KEY, instead of only reaching Gemini through OpenRouter.

Gemini is wired exactly like xAI: dispatched through OpenAIAdapter against
Google's OpenAI-compatible surface. The base URL is
https://generativelanguage.googleapis.com/v1beta/openai — the `/openai`
segment is required because OpenAIAdapter posts to `${baseUrl}/chat/completions`;
without it requests hit `/v1beta/chat/completions`, which Google does not serve.

Wires the provider through the type union, adapter factory, config
(interface, defaults, model catalog, key env map, getLLMConfig, fallback
chain, redaction, .env template), and adds regression tests pinning the
`/openai` base-URL segment.
2026-07-08 11:59:18 -04:00
pliny f94ca45b1c Merge pull request #1 from 5stars217/codex/local-agent-home
[codex] Respect real home for local agent auth
2026-07-08 10:25:45 -04:00
Pazificateur69 353ea33a23 feat(arsenal): real invocations for the reverse-engineering / mobile / smart-contract analysis loadout
The Kali+ adapter factory only carries bespoke ARG_TEMPLATES for the network
and source/supply-chain scanners. The reverse-engineering, mobile and
smart-contract analysers catalogued by the cloud/mobile/binary-RE loadouts fall
through to DEFAULT_TEMPLATE and spawn a bare `<binary> <file>` — a broken
invocation for a subcommand/flag-driven tool, and for radare2 one that drops
into an INTERACTIVE prompt and hangs the agent loop until the timeout burns out.

Add conservative, read-only ARG_TEMPLATES (mirroring each catalog commandHint)
for objdump, readelf, checksec, r2, exiftool, myth (mythril), apkleaks, slither
and mobsfscan. File-oriented tools resolve their artifact through a new
`artifactPath` helper that refuses an absent path or an inherited http(s) URL by
throwing, which the handler turns into a clean {success:false} result (never a
bare `objdump ''`). No intrusive or code-executing flag is added — risk stays
where the catalog put it, and the existing option-looking-target / scope gates
still apply.

Add an invocation-honesty guard test (sibling of the tool-count honesty test):
every mintable adapter must be either templated or explicitly filed under one
fall-through reason — POSITIONAL_TARGET_OK, OPERATOR_DRIVEN, or KNOWN_DEBT — so a
newly catalogued subcommand tool can never silently ship a broken positional
invocation, and the remaining debt (feroxbuster, osv-scanner, hashcat, apktool,
yara) is tracked in the open rather than hidden.

All offline gate checks pass (lint typecheck test doctor verify-claims
test:no-fitting test:no-self-fitting test:gate prompt:audit smoke
test:arsenal-tools arsenal:smoke).
2026-07-08 10:28:23 +02:00
Codex 23713fa177 Document local agent timeout tuning 2026-07-07 16:05:20 -04:00
Codex 75b7ca02ef Honor local agent timeout defaults 2026-07-07 16:05:20 -04:00
Codex e53c61e712 Increase local agent timeouts 2026-07-07 16:05:20 -04:00
Codex d9a4c47241 Show backend failure reason in UI refusal 2026-07-07 16:04:40 -04:00
Codex 73d888f4a1 Expose stalled local agent failures 2026-07-07 16:04:40 -04:00
Codex 49d0827650 Block phase progress without live backend 2026-07-07 16:04:40 -04:00
Codex f502bfbd42 Treat local agent API failures as unhealthy 2026-07-07 16:04:40 -04:00
Codex fb0feb0028 Report stale local agent backends 2026-07-07 16:04:40 -04:00
pliny a122c567f1 Merge pull request #46 from alameya/local-openai-compatible-wire
fix(llm): support versioned OpenAI-compatible endpoints + optional bearer for local provider
2026-07-07 12:59:36 -04:00
pliny a1d1b615c3 Merge pull request #49 from kaimi-/patch-1
Update auth detection for Hermes agent
2026-07-07 11:56:06 -04:00
pliny 5a5700cb9d Merge pull request #36 from M3NT8L-One/codex/provenance-docs-20260706
docs: explain verified provenance setup
2026-07-07 11:34:25 -04:00
pliny d2bafe97d0 Merge pull request #27 from mane/fix/redact-report-secrets
fix: redact secrets in markdown reports
2026-07-07 11:33:13 -04:00
pliny b3fcdcc7b4 Merge pull request #40 from Pazificateur69/fix/arsenal-scanner-invocation
fix(arsenal): run real scanner invocations for source/supply-chain tools
2026-07-07 11:32:49 -04:00
pliny e59e5debab Update README.md 2026-07-07 11:32:21 -04:00
Sergey Belov 4a0103f9f7 Update auth detection for Hermes agent 2026-07-07 13:00:26 +03:00
yaraul 2613daef49 fix(llm): support versioned OpenAI-compatible endpoints + optional bearer for local provider
Two issues blocked OpenAI-compatible servers that aren't Ollama-on-/v1:

1. LocalAdapter.isOpenAIWire matched only a literal /v1 path, so versioned
   endpoints like Zhipu/z.ai's /api/paas/v4 silently fell through to Ollama's
   native /api/chat wire format and failed. Match any /vN instead of literally /v1.

2. The `local` provider was treated as always-keyless, so servers that require
   a bearer (Zhipu/z.ai, Together, ...) could never authenticate. Read an
   optional key from TEMPEST_LOCAL_API_KEY (ZAI_API_KEY / ZHIPUAI_API_KEY as
   aliases), wire it through getApiKey/hasApiKey so `tempest test` and the
   mission engine accept a configured local provider, and document the options
   in the env template.

The key is read from env in-memory and never persisted into the store, matching
the existing env-key hardening invariant (api-key-env-static).

Adds src/__tests__/local-openai-wire-static.test.ts pinning both fixes.
Verified end-to-end against z.ai's GLM models (glm-4.5-air / 4.6 / 5.2).
2026-07-06 19:51:18 +03:00
pliny c040afd977 Merge pull request #30 from younger-plinius/feat/cloud-mobile-binary-loadouts
feat: cloud / mobile / binary-RE offensive loadouts (arsenal + detection benchmarks)
2026-07-06 12:35:07 -04:00
pliny 2f20ee5820 Merge pull request #33 from M3NT8L-One/codex/mission-stop-completion-20260706
fix(mission): stop command loop on terminal state
2026-07-06 11:48:23 -04:00
pliny 4ccf9952c8 Merge pull request #26 from mane/fix/redact-whitebox-source-context
fix: redact secrets from whitebox source context
2026-07-06 11:35:36 -04:00
pliny 56bfd29e33 Merge pull request #25 from mane/fix/config-env-export-consistency
fix: keep API key setup and export in sync
2026-07-06 11:35:13 -04:00