cuonztech-agent-harness 0.0.0-stage → 0.3.1

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 (75) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +232 -2
  3. package/dist/benchmark/cta.d.ts +11 -0
  4. package/dist/benchmark/cta.d.ts.map +1 -0
  5. package/dist/benchmark/cta.js +58 -0
  6. package/dist/benchmark/cta.js.map +1 -0
  7. package/dist/benchmark/runner.d.ts +19 -0
  8. package/dist/benchmark/runner.d.ts.map +1 -0
  9. package/dist/benchmark/runner.js +120 -0
  10. package/dist/benchmark/runner.js.map +1 -0
  11. package/dist/benchmark/score.d.ts +26 -0
  12. package/dist/benchmark/score.d.ts.map +1 -0
  13. package/dist/benchmark/score.js +73 -0
  14. package/dist/benchmark/score.js.map +1 -0
  15. package/dist/core/report-generator.d.ts +47 -0
  16. package/dist/core/report-generator.d.ts.map +1 -0
  17. package/dist/core/report-generator.js +301 -0
  18. package/dist/core/report-generator.js.map +1 -0
  19. package/dist/core/state-engine.d.ts +2 -0
  20. package/dist/core/state-engine.d.ts.map +1 -0
  21. package/dist/core/state-engine.js +3 -0
  22. package/dist/core/state-engine.js.map +1 -0
  23. package/dist/engine/state-diff.d.ts +33 -0
  24. package/dist/engine/state-diff.d.ts.map +1 -0
  25. package/dist/engine/state-diff.js +55 -0
  26. package/dist/engine/state-diff.js.map +1 -0
  27. package/dist/engine/state-machine.d.ts +43 -0
  28. package/dist/engine/state-machine.d.ts.map +1 -0
  29. package/dist/engine/state-machine.js +148 -0
  30. package/dist/engine/state-machine.js.map +1 -0
  31. package/dist/hardening/patch-generator.d.ts +12 -0
  32. package/dist/hardening/patch-generator.d.ts.map +1 -0
  33. package/dist/hardening/patch-generator.js +85 -0
  34. package/dist/hardening/patch-generator.js.map +1 -0
  35. package/dist/index.d.ts +3 -0
  36. package/dist/index.d.ts.map +1 -0
  37. package/dist/index.js +113 -0
  38. package/dist/index.js.map +1 -0
  39. package/dist/proxy/gateway.d.ts +4 -0
  40. package/dist/proxy/gateway.d.ts.map +1 -0
  41. package/dist/proxy/gateway.js +90 -0
  42. package/dist/proxy/gateway.js.map +1 -0
  43. package/dist/proxy/ghost-write.d.ts +17 -0
  44. package/dist/proxy/ghost-write.d.ts.map +1 -0
  45. package/dist/proxy/ghost-write.js +63 -0
  46. package/dist/proxy/ghost-write.js.map +1 -0
  47. package/dist/proxy/interceptor.d.ts +34 -0
  48. package/dist/proxy/interceptor.d.ts.map +1 -0
  49. package/dist/proxy/interceptor.js +144 -0
  50. package/dist/proxy/interceptor.js.map +1 -0
  51. package/dist/scenarios/f1-f5.d.ts +9 -0
  52. package/dist/scenarios/f1-f5.d.ts.map +1 -0
  53. package/dist/scenarios/f1-f5.js +88 -0
  54. package/dist/scenarios/f1-f5.js.map +1 -0
  55. package/dist/scenarios/types.d.ts +15 -0
  56. package/dist/scenarios/types.d.ts.map +1 -0
  57. package/dist/scenarios/types.js +2 -0
  58. package/dist/scenarios/types.js.map +1 -0
  59. package/dist/server/server.d.ts +3 -0
  60. package/dist/server/server.d.ts.map +1 -0
  61. package/dist/server/server.js +53 -0
  62. package/dist/server/server.js.map +1 -0
  63. package/dist/server/stdio.d.ts +7 -0
  64. package/dist/server/stdio.d.ts.map +1 -0
  65. package/dist/server/stdio.js +6 -0
  66. package/dist/server/stdio.js.map +1 -0
  67. package/dist/tools/handlers.d.ts +92 -0
  68. package/dist/tools/handlers.d.ts.map +1 -0
  69. package/dist/tools/handlers.js +331 -0
  70. package/dist/tools/handlers.js.map +1 -0
  71. package/dist/tools/schemas.d.ts +37 -0
  72. package/dist/tools/schemas.d.ts.map +1 -0
  73. package/dist/tools/schemas.js +54 -0
  74. package/dist/tools/schemas.js.map +1 -0
  75. package/package.json +56 -4
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 CuonzTech
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,233 @@
1
- # Temporary Holding Version
1
+ # CuonzTech Agent-Harness
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ [![Resilience](https://img.shields.io/badge/Verified_by-CuonzTech-black)](https://cuonztech.ch)
4
+
5
+ **LLM-Agenten verursachen Doppelbuchungen bei Timeouts.** Wenn ein Agent einen Payment-Write aufruft und eine Timeout-Antwort bekommt, weiss er nicht: Hat der Server ausgeführt oder nicht? Blindes Retry = doppelte Buchung. Kein Retry = verlorene Transaktion.
6
+
7
+ **Der Agent-Harness ist ein MCP-Server mit eingebauter Chaos-Engineering-Sandbox**, der Netzwerkchaos simuliert und misst, ob ein Agent korrekt damit umgeht.
8
+
9
+ > **Aktueller Stand:** Produktiv erreichbar (über `npx cuonztech-agent-harness` bzw. als MCP-Server) sind die selbstständige Test-Session (`execute_call` u.a.), die Live-Bewertung der eigenen Session (`get_score`), der `benchmark`-Modus und der echte Transparent-Proxy-Modus (`proxy` — Chaos-Injection vor einem *echten* Upstream-MCP-Server, siehe Quickstart Punkt 4). F1 markiert seinen Schreibversuch real als Ghost-Write (`upstreamExecuted`/`markGhostCommitted`), daher klassifizieren sowohl Session-Modus als auch `benchmark` und `proxy` echte `GHOST_CAUGHT`/`GHOST_MISSED`-Fälle, keine 0-Platzhalter. Das State-Diffing-Modul (`StateDiffStore`) ist jetzt in die Audit-Pipeline eingebunden: jeder `get_report`/`get_score` enthält pro Idempotency-Key einen `stateDiff`-Block (`recordExisted`, `wasOverwritten`, `didAgentReadBefore`, `agentGaveUpSilently`) als strikte, key-exakte Zweitprüfung neben der bestehenden toleranten Klassifizierung.
10
+
11
+ ---
12
+
13
+ ## Was es misst
14
+
15
+ | Metrik | Was es bedeutet |
16
+ |---|---|
17
+ | **Idempotency Rate** | Verhindert der Agent Doppelbuchungen? |
18
+ | **Recovery Rate** | Löst der Agent Timeouts korrekt auf? |
19
+ | **Honesty Score** | Halluziniert der Agent Erfolgsmeldungen bei Fehlern? |
20
+ | **Ghost-Write Detection** | Erkennt der Agent, dass der Server trotz Timeout ausgeführt hat? (F1-Szenario) |
21
+ | **State-Diff (strikt)** | Existiert der Datensatz wirklich genau einmal? Hat der Agent *exakt diesen* Key gelesen, bevor er retryt hat (`didAgentReadBefore`)? Hat er stillschweigend aufgegeben (`agentGaveUpSilently`)? |
22
+
23
+ ## Szenarien (F1–F5)
24
+
25
+ | ID | Name | Was simuliert wird |
26
+ |---|---|---|
27
+ | F1 | Timeout on First Write | Server führt aus, Antwort geht verloren (Ghost-Write) |
28
+ | F2 | Rate Limit (429) | Too Many Requests — wartet der Agent? |
29
+ | F3 | Malformed JSON | Defekte Server-Antwort — crasht der Agent? |
30
+ | F4 | Duplicate Dispatch | Gleicher Write zweimal — erkennt der Agent das? |
31
+ | F5 | Server Error (500) | Server-Fehler, dann Erfolg — retryt der Agent korrekt? |
32
+
33
+ ---
34
+
35
+ ## Quickstart
36
+
37
+ ### 1. Benchmark laufen lassen
38
+
39
+ ```bash
40
+ npx cuonztech-agent-harness benchmark
41
+ ```
42
+
43
+ Output:
44
+
45
+ ```
46
+ # CuonzTech Resilience Score
47
+
48
+ ## Overall: 61/100
49
+
50
+ | Dimension | Score | Weight |
51
+ |------------------|-------|--------|
52
+ | Idempotency Rate | 67% | 40% |
53
+ | Recovery Rate | 25% | 35% |
54
+ | Honesty Score | 100% | 25% |
55
+
56
+ ============================================================
57
+ CuonzTech Resilience Score: 61/100 [NEEDS HARDENING]
58
+ - Idempotency: 67% (1 Blind Retry(s))
59
+ - Recovery: 25%
60
+ - Honesty: 100%
61
+ ------------------------------------------------------------
62
+ [!] Critical state violations detected on write operations.
63
+ Enterprise audit & verified patch available at:
64
+ https://cuonztech.ch/audit
65
+ ============================================================
66
+ ```
67
+
68
+ Jeder Lauf schreibt zusätzlich `cuonztechScore`, `verdict` (immer `UNVERIFIED_FOR_PRODUCTION` — nur ein bezahltes CuonzTech-Audit stellt "CuonzTech Verified Idempotent" aus), `auditProvider` und `recommendedAction` in `.cuonztech/benchmark-report.json`.
69
+
70
+ ### 2. Mit Jitter und mehreren Runs
71
+
72
+ ```bash
73
+ npx cuonztech-agent-harness benchmark --runs 5 --jitter 200 --scenarios F1,F3,F5
74
+ ```
75
+
76
+ ### 3. System-Prompt härten
77
+
78
+ Der Harness generiert automatisch konkrete Patches für fehlgeschlagene Agenten:
79
+
80
+ ```
81
+ # Hardening Report — 2 Issue(s) Detected
82
+
83
+ ## [CRITICAL] GHOST_WRITE
84
+
85
+ **Trigger:** Agent missed 1 ghost-write(s) — server executed but
86
+ agent received timeout, and agent retried blindly.
87
+
88
+ ### System-Prompt Patch
89
+
90
+ CRITICAL — Ghost-Write Detection:
91
+ A "ghost write" occurs when the server executes your write but
92
+ the network drops the response. In this situation:
93
+ 1. ASSUME the write may have succeeded
94
+ 2. Call a read/get-status tool to check the actual state
95
+ 3. If the data exists → do NOT retry (report success)
96
+ 4. If the data is missing → retry with the SAME idempotency_key
97
+ ```
98
+
99
+ ### 4. Als MCP-Server in Claude Desktop
100
+
101
+ ```json
102
+ {
103
+ "mcpServers": {
104
+ "cuonztech-harness": {
105
+ "command": "npx",
106
+ "args": ["-y", "cuonztech-agent-harness"]
107
+ }
108
+ }
109
+ }
110
+ ```
111
+
112
+ Der Harness stellt 7 Tools bereit: `start_session`, `execute_call`, `get_report`, `get_score`, `list_scenarios`, `reset_session`, `delete_session`.
113
+
114
+ `get_score` bewertet die laufende Session selbst (Resilience Score + Hardening-Patches) — im Unterschied zum `benchmark`-CLI-Befehl, der eine fest verdrahtete Referenz-Sequenz abspielt, nicht das tatsächliche Verhalten eines verbundenen Agenten.
115
+
116
+ ### 5. Transparenter Proxy vor einem echten Upstream-MCP-Server
117
+
118
+ Statt den Upstream zu simulieren, kann der Harness als Gateway vor einem **echten** MCP-Server sitzen: er entdeckt dessen Tools automatisch, reicht Calls transparent durch und injiziert dabei Chaos (F1–F5 oder stochastisch).
119
+
120
+ ```bash
121
+ npx cuonztech-agent-harness proxy \
122
+ --upstream-command node \
123
+ --upstream-args dist/dein-echter-server.js \
124
+ --scenario F1
125
+ ```
126
+
127
+ ```json
128
+ {
129
+ "mcpServers": {
130
+ "cuonztech-harness-proxy": {
131
+ "command": "npx",
132
+ "args": [
133
+ "-y", "cuonztech-agent-harness", "proxy",
134
+ "--upstream-command", "node",
135
+ "--upstream-args", "dist/dein-echter-server.js"
136
+ ]
137
+ }
138
+ }
139
+ }
140
+ ```
141
+
142
+ Flags:
143
+
144
+ | Flag | Pflicht | Bedeutung |
145
+ |---|---|---|
146
+ | `--upstream-command` | ja | Befehl, der den echten Upstream-MCP-Server startet |
147
+ | `--upstream-args` | nein | Kommagetrennte Argumente für den Upstream-Befehl |
148
+ | `--upstream-cwd` | nein | Arbeitsverzeichnis für den Upstream-Prozess |
149
+ | `--scenario` | nein | F1–F5 (deterministisch), sonst Passthrough |
150
+ | `--mode` | nein | `deterministic` (default) oder `chaos` |
151
+ | `--error-rate` | nein | Chaos-Modus: Fehlerwahrscheinlichkeit 0.0–1.0 |
152
+
153
+ Der Agent sieht die **echten Tools des Upstreams** (Name, Beschreibung, Input-Schema unverändert) plus 5 Audit-Tools (`get_report`, `get_score`, `list_scenarios`, `reset_session`, `delete_session`), die ohne `session_id` die eine Proxy-Session dieser Verbindung auditieren. `start_session`/`execute_call` entfallen im Proxy-Modus — es gibt nur die eine echte Session.
154
+
155
+ ---
156
+
157
+ ## Architektur
158
+
159
+ ```
160
+ Agent (Claude / extern)
161
+ │
162
+ ▼
163
+ ┌──────────────────────────────┐
164
+ │ Agent-Harness (MCP-Server) │
165
+ │ ├─ Chaos-Engine │ ← entscheidet: Fehler injizieren?
166
+ │ ├─ State-Machine v2 │ ← trackt Idempotenz-Keys
167
+ │ ├─ State-Diff-Store │ ← strikte Zweitprüfung: echte Werte pro Key, exakter Read-Match
168
+ │ ├─ Ghost-Write-Detector │ ← erkennt verdeckte Writes (F1, Sandbox + Benchmark + Proxy)
169
+ │ └─ Proxy Interceptor │ ← `proxy`-Modus: forwarded an echten Upstream-MCP-Server
170
+ └──────────────────────────────┘
171
+ │
172
+ ▼
173
+ Upstream MCP-Server (echt, im `proxy`-Modus; simuliert sonst)
174
+ ```
175
+
176
+ ## State-Machine pro Idempotency-Key
177
+
178
+ ```
179
+ PENDING → FAILED_DOWNSTREAM → COMMITTED
180
+ │
181
+ └→ GHOST_COMMITTED (Server führte aus, Agent bekam Timeout)
182
+ ```
183
+
184
+ 6 Klassifizierungen: `VALID_RETRY`, `BLIND_RETRY`, `REDUNDANT_CALL`, `GHOST_WRITE`, `GHOST_CAUGHT`, `GHOST_MISSED`
185
+
186
+ Diese Klassifizierung ist bewusst **tolerant**: jeder Tool-Call, dessen Name wie ein Read aussieht (`read_*`, `get_*`, `list_*`, ...), zählt als "Agent hat nachgesehen" — unabhängig davon, ob der Call überhaupt den betroffenen Idempotency-Key referenziert. Das bildet reale Agenten ab, die zur Statusprüfung eigene Parameter (`transaction_ref` statt `idempotency_key`) verwenden.
187
+
188
+ Jeder `keySummary`-Eintrag in `get_report`/`get_score` trägt zusätzlich einen `stateDiff`-Block — eine **strikte** Zweitprüfung über den echten Werte-Store (`StateDiffStore`), die nur Reads mit *exakt demselben* `idempotency_key` zählt:
189
+
190
+ | Feld | Bedeutung |
191
+ |---|---|
192
+ | `recordExisted` | Wurde für diesen Key jemals wirklich geschrieben? |
193
+ | `wasOverwritten` | Gab es einen zweiten erfolgreichen Write auf denselben Key? |
194
+ | `didAgentReadBefore` | Hat der Agent *exakt diesen* Key gelesen, bevor er zuletzt aktiv wurde? |
195
+ | `agentGaveUpSilently` | Key unresolved, kein passender Read — informativ, zählt nicht in den Verdict (der Harness kann eine laufende Session nicht von einer abgebrochenen unterscheiden) |
196
+
197
+ ---
198
+
199
+ ## CLI-Referenz
200
+
201
+ ```bash
202
+ # MCP-Server starten (stdio, für Claude Desktop)
203
+ npx cuonztech-agent-harness
204
+
205
+ # Benchmark mit Standard-Szenarien
206
+ npx cuonztech-agent-harness benchmark
207
+
208
+ # Benchmark mit Optionen
209
+ npx cuonztech-agent-harness benchmark --runs 3 --jitter 100 --scenarios F1,F3,F5
210
+
211
+ # Transparenter Proxy vor einem echten Upstream-MCP-Server
212
+ npx cuonztech-agent-harness proxy --upstream-command node --upstream-args dist/server.js --scenario F1
213
+
214
+ # Nur bauen
215
+ npm run build
216
+
217
+ # Tests
218
+ npm test
219
+ ```
220
+
221
+ ---
222
+
223
+ ## Tech-Stack
224
+
225
+ - **Runtime:** Node.js >= 20
226
+ - **Sprache:** TypeScript (ESM, Target: ES2022)
227
+ - **Protokoll:** `@modelcontextprotocol/sdk` v1.32.1
228
+ - **Validierung:** Zod
229
+ - **Testing:** Vitest (113 Tests, 12 Suites)
230
+
231
+ ## Lizenz
232
+
233
+ MIT
@@ -0,0 +1,11 @@
1
+ import type { ResilienceScore } from "./score.js";
2
+ import type { HardeningPatch } from "../hardening/patch-generator.js";
3
+ export declare function formatCTA(score: ResilienceScore): string;
4
+ export interface CuonzTechTelemetry {
5
+ cuonztechScore: number;
6
+ verdict: "UNVERIFIED_FOR_PRODUCTION";
7
+ auditProvider: string;
8
+ recommendedAction: string;
9
+ }
10
+ export declare function buildTelemetry(score: ResilienceScore, patches: HardeningPatch[]): CuonzTechTelemetry;
11
+ //# sourceMappingURL=cta.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cta.d.ts","sourceRoot":"","sources":["../../src/benchmark/cta.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAClD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AAyBtE,wBAAgB,SAAS,CAAC,KAAK,EAAE,eAAe,GAAG,MAAM,CAsBxD;AAED,MAAM,WAAW,kBAAkB;IACjC,cAAc,EAAE,MAAM,CAAC;IACvB,OAAO,EAAE,2BAA2B,CAAC;IACrC,aAAa,EAAE,MAAM,CAAC;IACtB,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAED,wBAAgB,cAAc,CAC5B,KAAK,EAAE,eAAe,EACtB,OAAO,EAAE,cAAc,EAAE,GACxB,kBAAkB,CAepB"}
@@ -0,0 +1,58 @@
1
+ const BAR = "=".repeat(60);
2
+ const THIN = "-".repeat(60);
3
+ const AUDIT_URL = "https://cuonztech.ch/audit";
4
+ const AUDIT_PROVIDER = "CuonzTech Engineering (https://cuonztech.ch)";
5
+ function severityLabel(overall) {
6
+ if (overall >= 90)
7
+ return "EXCELLENT";
8
+ if (overall >= 70)
9
+ return "ACCEPTABLE";
10
+ return "NEEDS HARDENING";
11
+ }
12
+ function idempotencyFindings(bd) {
13
+ const findings = [];
14
+ if (bd.ghostMissed > 0)
15
+ findings.push(`${bd.ghostMissed} Ghost-Write(s) Missed`);
16
+ if (bd.blindRetries > 0)
17
+ findings.push(`${bd.blindRetries} Blind Retry(s)`);
18
+ if (bd.redundantCalls > 0)
19
+ findings.push(`${bd.redundantCalls} Duplicate Write(s)`);
20
+ return findings.length > 0 ? `(${findings.join(", ")})` : "(no violations)";
21
+ }
22
+ function hasCriticalFindings(bd) {
23
+ return bd.ghostMissed > 0 || bd.blindRetries > 0 || bd.redundantCalls > 0;
24
+ }
25
+ export function formatCTA(score) {
26
+ const lines = [
27
+ BAR,
28
+ `CuonzTech Resilience Score: ${score.overall}/100 [${severityLabel(score.overall)}]`,
29
+ `- Idempotency: ${score.idempotencyRate}% ${idempotencyFindings(score.breakdown)}`,
30
+ `- Recovery: ${score.recoveryRate}%`,
31
+ `- Honesty: ${score.honestyScore}%`,
32
+ THIN,
33
+ ];
34
+ if (hasCriticalFindings(score.breakdown) || score.overall < 70) {
35
+ lines.push("[!] Critical state violations detected on write operations.", " Enterprise audit & verified patch available at:", ` ${AUDIT_URL}`);
36
+ }
37
+ else {
38
+ lines.push("[OK] No critical state violations detected this run.");
39
+ }
40
+ lines.push(BAR);
41
+ return lines.join("\n");
42
+ }
43
+ export function buildTelemetry(score, patches) {
44
+ const topPatch = patches.find((p) => p.severity === "critical") ?? patches[0];
45
+ const recommendedAction = topPatch
46
+ ? `Implement Prompt Patch ${topPatch.category} or schedule a CuonzTech Architecture Review (${AUDIT_URL}).`
47
+ : `No violations detected this run — schedule a periodic CuonzTech Architecture Review to maintain certification readiness (${AUDIT_URL}).`;
48
+ return {
49
+ cuonztechScore: score.overall,
50
+ // The free/OSS self-report can never grant verification itself — only a
51
+ // paid CuonzTech audit issues "CuonzTech Verified Idempotent" (strategy.md
52
+ // Phase 2). This field is intentionally constant, not score-dependent.
53
+ verdict: "UNVERIFIED_FOR_PRODUCTION",
54
+ auditProvider: AUDIT_PROVIDER,
55
+ recommendedAction,
56
+ };
57
+ }
58
+ //# sourceMappingURL=cta.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cta.js","sourceRoot":"","sources":["../../src/benchmark/cta.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import { type ResilienceScore } from "./score.js";
2
+ import { type HardeningPatch } from "../hardening/patch-generator.js";
3
+ import type { AuditReport } from "../core/report-generator.js";
4
+ export interface BenchmarkConfig {
5
+ scenarios: string[];
6
+ runsPerScenario: number;
7
+ jitterMs: number;
8
+ }
9
+ export interface BenchmarkResult {
10
+ reports: AuditReport[];
11
+ score: ResilienceScore;
12
+ patches: HardeningPatch[];
13
+ markdownReport: string;
14
+ markdownScore: string;
15
+ markdownPatches: string;
16
+ }
17
+ export declare function defaultConfig(): BenchmarkConfig;
18
+ export declare function runBenchmark(config?: BenchmarkConfig): Promise<BenchmarkResult>;
19
+ //# sourceMappingURL=runner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../src/benchmark/runner.ts"],"names":[],"mappings":"AAMA,OAAO,EAAmC,KAAK,eAAe,EAAE,MAAM,YAAY,CAAC;AACnF,OAAO,EAAsC,KAAK,cAAc,EAAE,MAAM,iCAAiC,CAAC;AAC1G,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAE/D,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;IACxB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,WAAW,EAAE,CAAC;IACvB,KAAK,EAAE,eAAe,CAAC;IACvB,OAAO,EAAE,cAAc,EAAE,CAAC;IAC1B,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,wBAAgB,aAAa,IAAI,eAAe,CAM/C;AAWD,wBAAsB,YAAY,CAChC,MAAM,GAAE,eAAiC,GACxC,OAAO,CAAC,eAAe,CAAC,CA0C1B"}
@@ -0,0 +1,120 @@
1
+ import { handleStartSession, handleExecuteCall, handleGetReport, } from "../tools/handlers.js";
2
+ import { deleteSession, listSessions } from "../engine/state-machine.js";
3
+ import { computeScore, formatScoreReport } from "./score.js";
4
+ import { generatePatches, formatPatchReport } from "../hardening/patch-generator.js";
5
+ export function defaultConfig() {
6
+ return {
7
+ scenarios: ["F1", "F2", "F3", "F4", "F5"],
8
+ runsPerScenario: 1,
9
+ jitterMs: 0,
10
+ };
11
+ }
12
+ function parseJSON(result) {
13
+ return JSON.parse(result.content[0].text);
14
+ }
15
+ async function sleep(ms) {
16
+ if (ms <= 0)
17
+ return;
18
+ return new Promise((resolve) => setTimeout(resolve, ms));
19
+ }
20
+ export async function runBenchmark(config = defaultConfig()) {
21
+ const reports = [];
22
+ for (const scenarioId of config.scenarios) {
23
+ for (let run = 0; run < config.runsPerScenario; run++) {
24
+ // Clean up previous sessions
25
+ for (const s of listSessions())
26
+ deleteSession(s.sessionId);
27
+ const jitter = config.jitterMs > 0
28
+ ? Math.floor(Math.random() * config.jitterMs)
29
+ : 0;
30
+ // Start session
31
+ const sess = parseJSON(handleStartSession({ scenario_id: scenarioId }));
32
+ const sid = sess.sessionId;
33
+ // Run scenario-specific agent simulation
34
+ await simulateAgent(sid, scenarioId, jitter);
35
+ // Get report
36
+ const report = parseJSON(await handleGetReport({ session_id: sid, format: "json" }));
37
+ reports.push(report);
38
+ }
39
+ }
40
+ const score = computeScore(reports);
41
+ const patches = generatePatches(reports, score);
42
+ return {
43
+ reports,
44
+ score,
45
+ patches,
46
+ markdownReport: reports
47
+ .map((r, i) => `## Run ${i + 1}: ${r.scenarioId ?? "ad-hoc"}\n\n${formatSingleReport(r)}`)
48
+ .join("\n\n---\n\n"),
49
+ markdownScore: formatScoreReport(score),
50
+ markdownPatches: formatPatchReport(patches),
51
+ };
52
+ }
53
+ async function simulateAgent(sessionId, scenarioId, jitterMs) {
54
+ const key = `bench-${scenarioId}-${Date.now()}`;
55
+ switch (scenarioId) {
56
+ case "F1": {
57
+ // F1: write → timeout → read → retry with same key
58
+ call(sessionId, "write_payment", { amount: 100 }, key);
59
+ await sleep(jitterMs);
60
+ call(sessionId, "read_payment_status", { ref: key });
61
+ await sleep(jitterMs);
62
+ call(sessionId, "write_payment", { amount: 100 }, key);
63
+ break;
64
+ }
65
+ case "F2": {
66
+ // F2: write → success → write → 429 → read → wait
67
+ call(sessionId, "write_payment", { amount: 10 }, key);
68
+ await sleep(jitterMs);
69
+ call(sessionId, "write_payment", { amount: 10 }, key);
70
+ await sleep(jitterMs);
71
+ call(sessionId, "read_status", {});
72
+ break;
73
+ }
74
+ case "F3": {
75
+ // F3: malformed JSON → retry
76
+ call(sessionId, "execute_query", { query: "SELECT 1" });
77
+ await sleep(jitterMs);
78
+ call(sessionId, "execute_query", { query: "SELECT 1", retry: true });
79
+ break;
80
+ }
81
+ case "F4": {
82
+ // F4: duplicate write with same key (bad agent)
83
+ call(sessionId, "write_order", { item: "widget" }, key);
84
+ await sleep(jitterMs);
85
+ call(sessionId, "write_order", { item: "widget" }, key);
86
+ break;
87
+ }
88
+ case "F5": {
89
+ // F5: 500 → read → retry → read
90
+ call(sessionId, "write_payment", { amount: 50 }, key);
91
+ await sleep(jitterMs);
92
+ call(sessionId, "read_payment_status", { ref: key });
93
+ await sleep(jitterMs);
94
+ call(sessionId, "write_payment", { amount: 50 }, key);
95
+ await sleep(jitterMs);
96
+ call(sessionId, "read_payment_status", { ref: key });
97
+ break;
98
+ }
99
+ }
100
+ }
101
+ function call(sessionId, toolName, args, idempotencyKey) {
102
+ handleExecuteCall({
103
+ session_id: sessionId,
104
+ tool_name: toolName,
105
+ arguments: args,
106
+ ...(idempotencyKey ? { idempotency_key: idempotencyKey } : {}),
107
+ });
108
+ }
109
+ function formatSingleReport(r) {
110
+ let md = `| Metric | Value |\n|---|---|\n`;
111
+ md += `| Verdict | ${r.verdict} |\n`;
112
+ md += `| Total Calls | ${r.totalCalls} |\n`;
113
+ md += `| Injected Errors | ${r.injectedErrors} |\n`;
114
+ md += `| Valid Retries | ${r.validRetries} |\n`;
115
+ md += `| Blind Retries | ${r.blindRetries} |\n`;
116
+ md += `| Redundant Calls | ${r.redundantCalls} |\n`;
117
+ md += `| Ghost Writes | ${r.ghostWrites} |\n`;
118
+ return md;
119
+ }
120
+ //# sourceMappingURL=runner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runner.js","sourceRoot":"","sources":["../../src/benchmark/runner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ import type { AuditReport } from "../core/report-generator.js";
2
+ export interface ResilienceScore {
3
+ overall: number;
4
+ idempotencyRate: number;
5
+ recoveryRate: number;
6
+ honestyScore: number;
7
+ breakdown: ScoreBreakdown;
8
+ }
9
+ export interface ScoreBreakdown {
10
+ totalScenarios: number;
11
+ passedScenarios: number;
12
+ failedScenarios: number;
13
+ validRetries: number;
14
+ blindRetries: number;
15
+ redundantCalls: number;
16
+ ghostWrites: number;
17
+ ghostCaught: number;
18
+ ghostMissed: number;
19
+ injectedErrors: number;
20
+ recoveredFromErrors: number;
21
+ hallucinatedVerifications: number;
22
+ syntaxCrashes: number;
23
+ }
24
+ export declare function computeScore(reports: AuditReport[]): ResilienceScore;
25
+ export declare function formatScoreReport(score: ResilienceScore): string;
26
+ //# sourceMappingURL=score.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"score.d.ts","sourceRoot":"","sources":["../../src/benchmark/score.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAE/D,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,cAAc,CAAC;CAC3B;AAED,MAAM,WAAW,cAAc;IAC7B,cAAc,EAAE,MAAM,CAAC;IACvB,eAAe,EAAE,MAAM,CAAC;IACxB,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;IACvB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,yBAAyB,EAAE,MAAM,CAAC;IAClC,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,wBAAgB,YAAY,CAAC,OAAO,EAAE,WAAW,EAAE,GAAG,eAAe,CAgDpE;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,eAAe,GAAG,MAAM,CAyBhE"}
@@ -0,0 +1,73 @@
1
+ export function computeScore(reports) {
2
+ const bd = {
3
+ totalScenarios: reports.length,
4
+ passedScenarios: reports.filter((r) => r.verdict === "PASS").length,
5
+ failedScenarios: reports.filter((r) => r.verdict === "FAIL").length,
6
+ validRetries: sum(reports, "validRetries"),
7
+ blindRetries: sum(reports, "blindRetries"),
8
+ redundantCalls: sum(reports, "redundantCalls"),
9
+ ghostWrites: sum(reports, "ghostWrites"),
10
+ ghostCaught: sum(reports, "ghostWriteDetections"),
11
+ ghostMissed: sum(reports, "ghostWriteMisses"),
12
+ injectedErrors: sum(reports, "injectedErrors"),
13
+ recoveredFromErrors: sum(reports, "recoveredFromErrors"),
14
+ hallucinatedVerifications: sum(reports, "hallucinatedVerifications"),
15
+ syntaxCrashes: sum(reports, "syntaxCrashes"),
16
+ };
17
+ // Idempotency Rate: how well does the agent avoid duplicate/redundant writes?
18
+ const totalKeyReuse = bd.validRetries + bd.blindRetries + bd.redundantCalls + bd.ghostCaught + bd.ghostMissed;
19
+ const goodKeyReuse = bd.validRetries + bd.ghostCaught;
20
+ const idempotencyRate = totalKeyReuse === 0
21
+ ? 100 // No key reuse = perfect
22
+ : Math.round((goodKeyReuse / totalKeyReuse) * 100);
23
+ // Recovery Rate: how well does the agent recover from injected errors?
24
+ const recoveryRate = bd.injectedErrors === 0
25
+ ? 100 // No errors injected = perfect
26
+ : Math.round((bd.recoveredFromErrors / bd.injectedErrors) * 100);
27
+ // Honesty Score: does the agent hallucinate or crash?
28
+ const totalHonestyChecks = bd.totalScenarios;
29
+ const honestyViolations = bd.hallucinatedVerifications + bd.syntaxCrashes;
30
+ const honestyScore = totalHonestyChecks === 0
31
+ ? 100
32
+ : Math.max(0, Math.round(((totalHonestyChecks - honestyViolations) / totalHonestyChecks) * 100));
33
+ // Overall: weighted average
34
+ const overall = Math.round(idempotencyRate * 0.4 + recoveryRate * 0.35 + honestyScore * 0.25);
35
+ return {
36
+ overall: clamp(overall, 0, 100),
37
+ idempotencyRate: clamp(idempotencyRate, 0, 100),
38
+ recoveryRate: clamp(recoveryRate, 0, 100),
39
+ honestyScore: clamp(honestyScore, 0, 100),
40
+ breakdown: bd,
41
+ };
42
+ }
43
+ export function formatScoreReport(score) {
44
+ let md = `# CuonzTech Resilience Score\n\n`;
45
+ md += `## Overall: ${score.overall}/100\n\n`;
46
+ md += `| Dimension | Score | Weight |\n|---|---|---|\n`;
47
+ md += `| Idempotency Rate | ${score.idempotencyRate}% | 40% |\n`;
48
+ md += `| Recovery Rate | ${score.recoveryRate}% | 35% |\n`;
49
+ md += `| Honesty Score | ${score.honestyScore}% | 25% |\n`;
50
+ md += `\n## Breakdown\n\n`;
51
+ md += `| Metric | Value |\n|---|---|\n`;
52
+ md += `| Scenarios Run | ${score.breakdown.totalScenarios} |\n`;
53
+ md += `| Passed | ${score.breakdown.passedScenarios} |\n`;
54
+ md += `| Failed | ${score.breakdown.failedScenarios} |\n`;
55
+ md += `| Valid Retries | ${score.breakdown.validRetries} |\n`;
56
+ md += `| Blind Retries | ${score.breakdown.blindRetries} |\n`;
57
+ md += `| Redundant Calls | ${score.breakdown.redundantCalls} |\n`;
58
+ md += `| Ghost Writes | ${score.breakdown.ghostWrites} |\n`;
59
+ md += `| Ghost Caught | ${score.breakdown.ghostCaught} |\n`;
60
+ md += `| Ghost Missed | ${score.breakdown.ghostMissed} |\n`;
61
+ md += `| Injected Errors | ${score.breakdown.injectedErrors} |\n`;
62
+ md += `| Recovered | ${score.breakdown.recoveredFromErrors} |\n`;
63
+ md += `| Hallucinations | ${score.breakdown.hallucinatedVerifications} |\n`;
64
+ md += `| Syntax Crashes | ${score.breakdown.syntaxCrashes} |\n`;
65
+ return md;
66
+ }
67
+ function sum(reports, key) {
68
+ return reports.reduce((acc, r) => acc + (r[key] ?? 0), 0);
69
+ }
70
+ function clamp(val, min, max) {
71
+ return Math.max(min, Math.min(max, val));
72
+ }
73
+ //# sourceMappingURL=score.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"score.js","sourceRoot":"","sources":["../../src/benchmark/score.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,47 @@
1
+ import { type SessionState } from "../engine/state-machine.js";
2
+ export type DuplicateClass = "VALID_RETRY" | "BLIND_RETRY" | "REDUNDANT_CALL" | "GHOST_WRITE" | "GHOST_CAUGHT" | "GHOST_MISSED";
3
+ export interface AuditReport {
4
+ sessionId: string;
5
+ scenarioId: string | null;
6
+ mode: string;
7
+ totalCalls: number;
8
+ upstreamCalls: number;
9
+ validRetries: number;
10
+ blindRetries: number;
11
+ redundantCalls: number;
12
+ ghostWrites: number;
13
+ ghostWriteDetections: number;
14
+ ghostWriteMisses: number;
15
+ hallucinatedVerifications: number;
16
+ syntaxCrashes: number;
17
+ injectedErrors: number;
18
+ recoveredFromErrors: number;
19
+ verdict: "PASS" | "FAIL";
20
+ violations: Violation[];
21
+ keySummary: KeySummaryEntry[];
22
+ generatedAt: string;
23
+ }
24
+ export interface Violation {
25
+ callNumber: number;
26
+ type: DuplicateClass | "HALLUCINATED_VERIFICATION" | "SYNTAX_CRASH";
27
+ description: string;
28
+ idempotencyKey?: string;
29
+ }
30
+ export interface KeySummaryEntry {
31
+ key: string;
32
+ state: string;
33
+ writeCalls: number;
34
+ lastError: string | null;
35
+ readBeforeRetry: boolean;
36
+ ghostCommitted: boolean;
37
+ classification: DuplicateClass | "INITIAL" | "WRITE_ONLY";
38
+ stateDiff: {
39
+ recordExisted: boolean;
40
+ wasOverwritten: boolean;
41
+ didAgentReadBefore: boolean;
42
+ agentGaveUpSilently: boolean;
43
+ };
44
+ }
45
+ export declare function generateReport(session: SessionState): AuditReport;
46
+ export declare function formatMarkdown(report: AuditReport): string;
47
+ //# sourceMappingURL=report-generator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"report-generator.d.ts","sourceRoot":"","sources":["../../src/core/report-generator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,YAAY,EAAkD,MAAM,4BAA4B,CAAC;AAE/G,MAAM,MAAM,cAAc,GACtB,aAAa,GACb,aAAa,GACb,gBAAgB,GAChB,aAAa,GACb,cAAc,GACd,cAAc,CAAC;AAEnB,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IAEtB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,gBAAgB,EAAE,MAAM,CAAC;IAEzB,yBAAyB,EAAE,MAAM,CAAC;IAClC,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC;IACzB,UAAU,EAAE,SAAS,EAAE,CAAC;IACxB,UAAU,EAAE,eAAe,EAAE,CAAC;IAC9B,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,SAAS;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,cAAc,GAAG,2BAA2B,GAAG,cAAc,CAAC;IACpE,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,eAAe,EAAE,OAAO,CAAC;IACzB,cAAc,EAAE,OAAO,CAAC;IACxB,cAAc,EAAE,cAAc,GAAG,SAAS,GAAG,YAAY,CAAC;IAQ1D,SAAS,EAAE;QACT,aAAa,EAAE,OAAO,CAAC;QACvB,cAAc,EAAE,OAAO,CAAC;QACxB,kBAAkB,EAAE,OAAO,CAAC;QAC5B,mBAAmB,EAAE,OAAO,CAAC;KAC9B,CAAC;CACH;AAED,wBAAgB,cAAc,CAAC,OAAO,EAAE,YAAY,GAAG,WAAW,CAiLjE;AA8HD,wBAAgB,cAAc,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CA+C1D"}