blitzstrike 1.0.48 → 1.0.50
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 +28 -0
- package/dist/index.js +120 -3
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,34 @@ 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.50] — 2026-09-13
|
|
9
|
+
|
|
10
|
+
### Added — Autonomous Security Engine (phase 10: cross-agent memory)
|
|
11
|
+
|
|
12
|
+
- **Cross-agent Memory** (`src/mission/memory.ts`, §20):
|
|
13
|
+
- `persistMissionMemory()` — persists confirmed findings (verified),
|
|
14
|
+
rejected findings, and failed approaches (with `future_policy`) into the
|
|
15
|
+
long-term memory store; pending hypotheses are NOT persisted (unverified).
|
|
16
|
+
- `recallForTarget()` — retrieves memory relevant to a target, to seed a
|
|
17
|
+
fresh mission.
|
|
18
|
+
- Mission Control's `finalize` now persists reusable knowledge and records the
|
|
19
|
+
saved/deduped count in `memory_refs`.
|
|
20
|
+
|
|
21
|
+
## [1.0.49] — 2026-09-13
|
|
22
|
+
|
|
23
|
+
### Added — Autonomous Security Engine (phase 9: failure recovery)
|
|
24
|
+
|
|
25
|
+
- **Failure Recovery** (`src/mission/recovery.ts`, §17):
|
|
26
|
+
- `diagnoseError()` — categorizes failures (network / permission /
|
|
27
|
+
missing_tool / invalid_args / scope / unknown).
|
|
28
|
+
- `recoveryDecision()` — network → retry (bounded); missing_tool → route to an
|
|
29
|
+
alternative agent; scope / permission / invalid_args → record (no retry).
|
|
30
|
+
- `AGENT_ALTERNATIVES` — fallback specialization per agent type.
|
|
31
|
+
- `recordFailure()` — a failed-approach record with a `future_policy` so the
|
|
32
|
+
autonomous system never blindly repeats the same mistake.
|
|
33
|
+
- Mission Control now routes task failures through the recovery engine and
|
|
34
|
+
persists `failed_approaches` into the mission state.
|
|
35
|
+
|
|
8
36
|
## [1.0.48] — 2026-09-13
|
|
9
37
|
|
|
10
38
|
### Added — Autonomous Security Engine (phase 8: coverage-driven scheduler)
|
package/dist/index.js
CHANGED
|
@@ -17903,7 +17903,8 @@ function newMission(id, target, scope, mode, budget) {
|
|
|
17903
17903
|
coverage: { dimensions: {} },
|
|
17904
17904
|
memory_refs: [],
|
|
17905
17905
|
termination_reason: null,
|
|
17906
|
-
decision_log: []
|
|
17906
|
+
decision_log: [],
|
|
17907
|
+
failed_approaches: []
|
|
17907
17908
|
};
|
|
17908
17909
|
}
|
|
17909
17910
|
|
|
@@ -18654,6 +18655,95 @@ var init_coverage = __esm(() => {
|
|
|
18654
18655
|
};
|
|
18655
18656
|
});
|
|
18656
18657
|
|
|
18658
|
+
// src/mission/recovery.ts
|
|
18659
|
+
function diagnoseError(error) {
|
|
18660
|
+
const e = error.toLowerCase();
|
|
18661
|
+
if (/network|connect|timeout|econn|enotfound|unreachable|dns|resolve|refused|abort/i.test(e))
|
|
18662
|
+
return "network";
|
|
18663
|
+
if (/permission|eacces|denied|forbidden|401|403/i.test(e))
|
|
18664
|
+
return "permission";
|
|
18665
|
+
if (/not (installed|found)|no such|command not found|missing tool/i.test(e))
|
|
18666
|
+
return "missing_tool";
|
|
18667
|
+
if (/invalid|argument|usage|required|schema|type/i.test(e))
|
|
18668
|
+
return "invalid_args";
|
|
18669
|
+
if (/scope|authorized|out of scope|unauthorized/i.test(e))
|
|
18670
|
+
return "scope";
|
|
18671
|
+
return "unknown";
|
|
18672
|
+
}
|
|
18673
|
+
function recoveryDecision(task, error) {
|
|
18674
|
+
const category = diagnoseError(error);
|
|
18675
|
+
switch (category) {
|
|
18676
|
+
case "network":
|
|
18677
|
+
return task.attempts < 3 ? { action: "retry", reason: "transient network failure — retry", alternative_agent: null } : { action: "record", reason: "persistent network failure", alternative_agent: null };
|
|
18678
|
+
case "missing_tool":
|
|
18679
|
+
return { action: "alternative", reason: "tool unavailable — try alternative", alternative_agent: AGENT_ALTERNATIVES[task.agent_type]?.[0] ?? null };
|
|
18680
|
+
case "invalid_args":
|
|
18681
|
+
return { action: "record", reason: "invalid arguments — cannot auto-recover", alternative_agent: null };
|
|
18682
|
+
case "scope":
|
|
18683
|
+
return { action: "record", reason: "out of scope — do not retry", alternative_agent: null };
|
|
18684
|
+
case "permission":
|
|
18685
|
+
return { action: "record", reason: "permission denied — cannot auto-recover", alternative_agent: null };
|
|
18686
|
+
default:
|
|
18687
|
+
return task.attempts < 2 ? { action: "retry", reason: "unknown failure — retry once", alternative_agent: null } : { action: "record", reason: "unknown failure — give up", alternative_agent: null };
|
|
18688
|
+
}
|
|
18689
|
+
}
|
|
18690
|
+
function recordFailure(task, error) {
|
|
18691
|
+
const category = diagnoseError(error);
|
|
18692
|
+
return {
|
|
18693
|
+
technique: `${task.agent_type}:${task.objective}`,
|
|
18694
|
+
target: task.objective,
|
|
18695
|
+
category,
|
|
18696
|
+
reason: error,
|
|
18697
|
+
attempts: task.attempts,
|
|
18698
|
+
future_policy: category === "scope" ? "do not retry — out of scope" : category === "missing_tool" ? "route to an alternative agent next time" : category === "network" ? "retry with backoff" : "lower priority for this technique"
|
|
18699
|
+
};
|
|
18700
|
+
}
|
|
18701
|
+
var AGENT_ALTERNATIVES;
|
|
18702
|
+
var init_recovery = __esm(() => {
|
|
18703
|
+
AGENT_ALTERNATIVES = {
|
|
18704
|
+
commander: [],
|
|
18705
|
+
recon: ["api", "web"],
|
|
18706
|
+
web: ["api", "recon"],
|
|
18707
|
+
api: ["recon", "web"],
|
|
18708
|
+
source: ["analysis"],
|
|
18709
|
+
auth: ["analysis", "source"],
|
|
18710
|
+
mobile: ["source"],
|
|
18711
|
+
cloud: ["source"],
|
|
18712
|
+
analysis: ["source"],
|
|
18713
|
+
validator: ["reviewer"],
|
|
18714
|
+
reviewer: ["validator"],
|
|
18715
|
+
reporter: []
|
|
18716
|
+
};
|
|
18717
|
+
});
|
|
18718
|
+
|
|
18719
|
+
// src/mission/memory.ts
|
|
18720
|
+
function recordHypothesisOutcome(type, target, status, evidence) {
|
|
18721
|
+
return remember(`finding:${type}`, `[${status}] ${type} @ ${target}: ${evidence}`, status === "validated" ? "signature" : "lesson", [type.toLowerCase(), status], "mission", status === "validated").saved === true;
|
|
18722
|
+
}
|
|
18723
|
+
function recordFailedApproach(fa) {
|
|
18724
|
+
return remember(`failed:${fa.technique}`, `${fa.technique} failed (${fa.category}): ${fa.reason} — ${fa.future_policy}`, "lesson", ["failed", fa.category], "mission", false).saved === true;
|
|
18725
|
+
}
|
|
18726
|
+
function persistMissionMemory(mission) {
|
|
18727
|
+
let attempted = 0;
|
|
18728
|
+
let saved = 0;
|
|
18729
|
+
for (const h of mission.hypotheses) {
|
|
18730
|
+
if (h.status !== "validated" && h.status !== "rejected")
|
|
18731
|
+
continue;
|
|
18732
|
+
attempted += 1;
|
|
18733
|
+
if (recordHypothesisOutcome(h.type, h.target, h.status, h.evidence))
|
|
18734
|
+
saved += 1;
|
|
18735
|
+
}
|
|
18736
|
+
for (const fa of mission.failed_approaches) {
|
|
18737
|
+
attempted += 1;
|
|
18738
|
+
if (recordFailedApproach(fa))
|
|
18739
|
+
saved += 1;
|
|
18740
|
+
}
|
|
18741
|
+
return { saved, deduped: attempted - saved };
|
|
18742
|
+
}
|
|
18743
|
+
var init_memory2 = __esm(() => {
|
|
18744
|
+
init_memory();
|
|
18745
|
+
});
|
|
18746
|
+
|
|
18657
18747
|
// src/mission/control.ts
|
|
18658
18748
|
import { existsSync as existsSync8, statSync as statSync4 } from "node:fs";
|
|
18659
18749
|
function scopeAllowed(mission) {
|
|
@@ -18774,8 +18864,29 @@ async function runMission(mission) {
|
|
|
18774
18864
|
m = { ...m, report: r.output };
|
|
18775
18865
|
}
|
|
18776
18866
|
} else {
|
|
18777
|
-
const
|
|
18778
|
-
|
|
18867
|
+
const rec = recoveryDecision(r.task, r.error ?? "unknown error");
|
|
18868
|
+
const stamp = { at: new Date().toISOString(), agent: r.task.agent_type, decision };
|
|
18869
|
+
if (rec.action === "retry") {
|
|
18870
|
+
const retried = setTask(m.tasks, r.task.task_id, { status: "retry", error: r.error ?? null });
|
|
18871
|
+
m = { ...m, tasks: retried, decision_log: [...m.decision_log, stamp] };
|
|
18872
|
+
} else if (rec.action === "alternative" && rec.alternative_agent) {
|
|
18873
|
+
const failed = setTask(m.tasks, r.task.task_id, { status: "failed", error: r.error ?? null });
|
|
18874
|
+
const alt = createTask({ objective: `[alternative] ${r.task.objective}`, agent_type: rec.alternative_agent, risk: r.task.risk, priority: r.task.priority - 1 });
|
|
18875
|
+
m = {
|
|
18876
|
+
...m,
|
|
18877
|
+
tasks: [...failed, alt],
|
|
18878
|
+
decision_log: [...m.decision_log, stamp],
|
|
18879
|
+
failed_approaches: [...m.failed_approaches, recordFailure(r.task, r.error ?? "")]
|
|
18880
|
+
};
|
|
18881
|
+
} else {
|
|
18882
|
+
const failed = setTask(m.tasks, r.task.task_id, { status: "failed", error: r.error ?? null });
|
|
18883
|
+
m = {
|
|
18884
|
+
...m,
|
|
18885
|
+
tasks: failed,
|
|
18886
|
+
decision_log: [...m.decision_log, stamp],
|
|
18887
|
+
failed_approaches: [...m.failed_approaches, recordFailure(r.task, r.error ?? "")]
|
|
18888
|
+
};
|
|
18889
|
+
}
|
|
18779
18890
|
}
|
|
18780
18891
|
}
|
|
18781
18892
|
m.budget.used_tasks += batch.length;
|
|
@@ -18795,6 +18906,10 @@ function finalize2(mission) {
|
|
|
18795
18906
|
tasks: allResolved(m.tasks) ? 1 : 0,
|
|
18796
18907
|
hypotheses_validated: m.hypotheses.length > 0 ? m.hypotheses.filter((h) => h.status === "validated").length / m.hypotheses.length : 0
|
|
18797
18908
|
};
|
|
18909
|
+
const mem = persistMissionMemory(m);
|
|
18910
|
+
if (mem.saved > 0) {
|
|
18911
|
+
m = { ...m, memory_refs: [...m.memory_refs, `persisted:${mem.saved} (${mem.deduped} deduped)`] };
|
|
18912
|
+
}
|
|
18798
18913
|
return saveMission(m);
|
|
18799
18914
|
}
|
|
18800
18915
|
async function startMission(target, mode, opts = {}) {
|
|
@@ -18816,6 +18931,8 @@ var init_control = __esm(() => {
|
|
|
18816
18931
|
init_agents();
|
|
18817
18932
|
init_planner();
|
|
18818
18933
|
init_coverage();
|
|
18934
|
+
init_recovery();
|
|
18935
|
+
init_memory2();
|
|
18819
18936
|
MODE_PROFILES = {
|
|
18820
18937
|
web: { agents: ["recon", "web", "api", "auth", "validator", "reviewer", "reporter"], verify: true, risk: "medium" },
|
|
18821
18938
|
api: { agents: ["recon", "api", "auth", "validator", "reviewer", "reporter"], verify: true, risk: "medium" },
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "blitzstrike",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.50",
|
|
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": {
|