blitzstrike 1.0.53 → 1.0.54

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/CHANGELOG.md CHANGED
@@ -5,6 +5,22 @@ All notable changes to Blitz Strike are documented here.
5
5
  The format follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/).
7
7
 
8
+ ## [1.0.54] — 2026-09-13
9
+
10
+ ### Added — Autonomous Security Engine (phase 14: budget controller)
11
+
12
+ - **Budget Controller** (`src/mission/budget.ts`, §22):
13
+ - `budgetStatus()` — tracks time / tasks / requests / tokens / cost with
14
+ per-dimension overrun flags.
15
+ - `budgetOverrun()` — detects overruns and returns a specific reason
16
+ (e.g. `budget overrun: tasks, requests`).
17
+ - `consumeTasks()` / `consumeTokens()` — increment consumption counters.
18
+ - `perTaskOverrun()` — enforces the per-task request budget.
19
+ - Extended the `Budget` type with `max_tokens`, `max_cost_usd`,
20
+ `per_task_budget`, `started_at`, and `used_tokens`/`used_cost_usd`.
21
+ - Mission Control now terminates gracefully on ANY budget dimension overrun
22
+ (not just tasks) and records a final budget snapshot in the decision log.
23
+
8
24
  ## [1.0.53] — 2026-09-13
9
25
 
10
26
  ### Added — Autonomous Security Engine (phase 13: model router)
package/dist/index.js CHANGED
@@ -18097,10 +18097,16 @@ function newMission(id, target, scope, mode, budget) {
18097
18097
  max_time_seconds: 3600,
18098
18098
  max_tasks: 200,
18099
18099
  max_requests: 1000,
18100
+ max_tokens: 2000000,
18101
+ max_cost_usd: 5,
18100
18102
  max_parallel_workers: 4,
18101
18103
  risk: "medium",
18104
+ per_task_budget: { max_time_seconds: 60, max_requests: 50 },
18105
+ started_at: Date.now(),
18102
18106
  used_tasks: 0,
18103
18107
  used_requests: 0,
18108
+ used_tokens: 0,
18109
+ used_cost_usd: 0,
18104
18110
  ...budget ?? {}
18105
18111
  },
18106
18112
  discovered_assets: [],
@@ -19134,6 +19140,48 @@ var init_router = __esm(() => {
19134
19140
  };
19135
19141
  });
19136
19142
 
19143
+ // src/mission/budget.ts
19144
+ function clampRatio(used, max) {
19145
+ if (max <= 0)
19146
+ return 0;
19147
+ return Math.max(0, Math.min(1, used / max));
19148
+ }
19149
+ function budgetStatus(budget, now = Date.now()) {
19150
+ const elapsed = Math.max(0, (now - budget.started_at) / 1000);
19151
+ const dims = [
19152
+ ["time", "time (s)", elapsed, budget.max_time_seconds],
19153
+ ["tasks", "tasks", budget.used_tasks, budget.max_tasks],
19154
+ ["requests", "requests", budget.used_requests, budget.max_requests],
19155
+ ["tokens", "tokens", budget.used_tokens, budget.max_tokens],
19156
+ ["cost", "cost (USD)", budget.used_cost_usd, budget.max_cost_usd]
19157
+ ];
19158
+ return dims.map(([key, label, used, max]) => ({
19159
+ key,
19160
+ label,
19161
+ used: Number(used.toFixed(2)),
19162
+ max,
19163
+ overrun: used >= max,
19164
+ ratio: clampRatio(used, max)
19165
+ }));
19166
+ }
19167
+ function budgetOverrun(budget, now = Date.now()) {
19168
+ const dims = budgetStatus(budget, now).filter((d) => d.overrun);
19169
+ if (dims.length === 0)
19170
+ return { overrun: false, reason: null, dimensions: [] };
19171
+ return {
19172
+ overrun: true,
19173
+ reason: `budget overrun: ${dims.map((d) => d.key).join(", ")}`,
19174
+ dimensions: dims.map((d) => d.key)
19175
+ };
19176
+ }
19177
+ function consumeTasks(budget, tasks, requests) {
19178
+ return {
19179
+ ...budget,
19180
+ used_tasks: budget.used_tasks + tasks,
19181
+ used_requests: budget.used_requests + requests
19182
+ };
19183
+ }
19184
+
19137
19185
  // src/mission/control.ts
19138
19186
  import { existsSync as existsSync8, statSync as statSync4 } from "node:fs";
19139
19187
  function scopeAllowed(mission) {
@@ -19204,7 +19252,10 @@ async function executeTask(task, mission, scope) {
19204
19252
  }
19205
19253
  }
19206
19254
  function budgetExhausted(mission) {
19207
- return mission.budget.used_tasks >= mission.budget.max_tasks;
19255
+ return budgetOverrun(mission.budget).overrun;
19256
+ }
19257
+ function budgetReason(mission) {
19258
+ return budgetOverrun(mission.budget).reason ?? "budget_exhausted";
19208
19259
  }
19209
19260
  async function runMission(mission) {
19210
19261
  if (/^https?:\/\//i.test(mission.target) && !scopeAllowed(mission)) {
@@ -19225,7 +19276,7 @@ async function runMission(mission) {
19225
19276
  while (iterations < maxIterations) {
19226
19277
  iterations += 1;
19227
19278
  if (budgetExhausted(m)) {
19228
- m = { ...m, termination_reason: "budget_exhausted" };
19279
+ m = { ...m, termination_reason: budgetReason(m) };
19229
19280
  break;
19230
19281
  }
19231
19282
  const { ready, blocked } = schedule(m.tasks);
@@ -19286,7 +19337,7 @@ async function runMission(mission) {
19286
19337
  }
19287
19338
  }
19288
19339
  }
19289
- m.budget.used_tasks += batch.length;
19340
+ m.budget = consumeTasks(m.budget, batch.length, 0);
19290
19341
  m = saveMission(m);
19291
19342
  }
19292
19343
  return finalize2(m);
@@ -19294,7 +19345,7 @@ async function runMission(mission) {
19294
19345
  function finalize2(mission) {
19295
19346
  let m = mission;
19296
19347
  if (budgetExhausted(m)) {
19297
- m = { ...m, status: "terminated", termination_reason: "budget_exhausted" };
19348
+ m = { ...m, status: "terminated", termination_reason: budgetReason(m) };
19298
19349
  } else {
19299
19350
  m = { ...m, status: "completed", termination_reason: "all tasks resolved" };
19300
19351
  }
@@ -19307,6 +19358,8 @@ function finalize2(mission) {
19307
19358
  if (mem.saved > 0) {
19308
19359
  m = { ...m, memory_refs: [...m.memory_refs, `persisted:${mem.saved} (${mem.deduped} deduped)`] };
19309
19360
  }
19361
+ const budgetSummary = budgetStatus(m.budget).map((d) => `${d.key}=${d.used}/${d.max}`).join(", ");
19362
+ m = { ...m, decision_log: [...m.decision_log, { at: new Date().toISOString(), agent: "budget", decision: `final budget: ${budgetSummary}` }] };
19310
19363
  return saveMission(m);
19311
19364
  }
19312
19365
  async function startMission(target, mode, opts = {}) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "blitzstrike",
3
- "version": "1.0.53",
3
+ "version": "1.0.54",
4
4
  "description": "Blitz Strike — a universal MCP security-audit toolbelt. BLITZ sweeps the attack surface, EAGLE-EYE traces source-to-sink, STRIKE verifies live. 57 attack chains, 130-tool catalog, intelligence data layer. One server, every agent.",
5
5
  "type": "module",
6
6
  "bin": {