agentcert 0.1.0
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/README.md +84 -0
- package/dist/badge.js +31 -0
- package/dist/bundle.js +80 -0
- package/dist/cli.js +553 -0
- package/dist/corpus-store.js +241 -0
- package/dist/corpus.js +435 -0
- package/dist/failure-review.js +188 -0
- package/dist/index.js +10 -0
- package/dist/lab.js +323 -0
- package/dist/local-server.js +491 -0
- package/dist/monitor.js +100 -0
- package/dist/normalizers.js +193 -0
- package/dist/report.js +148 -0
- package/dist/runner.js +341 -0
- package/dist/schema-validator.js +150 -0
- package/dist/types.js +1 -0
- package/package.json +31 -0
package/README.md
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# AgentCert CLI
|
|
2
|
+
|
|
3
|
+
Unified evidence, corpus, monitor, and lab CLI for AgentCert.
|
|
4
|
+
|
|
5
|
+
## 5-minute local path
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npx agentcert init --subject my-browser-agent
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Edit `tripwire.yml` so `startUrl` and `agent.command` point at your app and
|
|
12
|
+
browser agent. After Tripwire has produced `.tripwire/latest/tripwire-result.json`,
|
|
13
|
+
build the AgentCert outputs:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npx agentcert run --tripwire .tripwire/latest/tripwire-result.json --subject my-browser-agent --fail-on-verdict
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Default outputs:
|
|
20
|
+
|
|
21
|
+
- `.agentcert/latest/agentcert-evidence.json`
|
|
22
|
+
- `.agentcert/latest/agentcert-report.md`
|
|
23
|
+
- `.agentcert/latest/agentcert-report.html`
|
|
24
|
+
- `.agentcert/latest/agentcert-run-manifest.json`
|
|
25
|
+
- `.agentcert/latest/badge.svg`
|
|
26
|
+
- `.agentcert/corpus/corpus.jsonl`
|
|
27
|
+
- `.agentcert/latest/reviewed-failure-dataset.jsonl`
|
|
28
|
+
- `.agentcert/latest/monitor.json`
|
|
29
|
+
|
|
30
|
+
Review/export helpers:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
npx agentcert corpus metrics --corpus .agentcert/corpus/corpus.jsonl
|
|
34
|
+
npx agentcert corpus export-reviewed --corpus .agentcert/corpus/corpus.jsonl --out .agentcert/latest/reviewed-failure-dataset.jsonl
|
|
35
|
+
npx agentcert corpus classifier-eval --corpus .agentcert/corpus/corpus.jsonl --out .agentcert/latest/failure-classifier-evaluation.json
|
|
36
|
+
npx agentcert schema validate --schema evidence-bundle --file .agentcert/latest/agentcert-evidence.json
|
|
37
|
+
npx agentcert schema validate --schema classifier-eval --file examples/agentcert/classifier-eval.example.json
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
CI users can run Tripwire and AgentCert together with
|
|
41
|
+
`Kakarottoooo/agentcert/actions/tripwire@v0`.
|
|
42
|
+
|
|
43
|
+
Corpus storage:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
npx agentcert corpus ingest --tripwire .tripwire/latest/tripwire-result.json --out .agentcert/corpus/corpus.jsonl --subject my-browser-agent
|
|
47
|
+
npx agentcert corpus ingest --store sqlite --sqlite .agentcert/corpus/agentcert.sqlite --tripwire .tripwire/latest/tripwire-result.json --subject my-browser-agent
|
|
48
|
+
npx agentcert monitor build --store postgres --database-url "$AGENTCERT_DATABASE_URL" --out .agentcert/latest/monitor.json --subject my-browser-agent
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
The UI always reads `agentcert.monitor_snapshot`, so switching from JSONL to
|
|
52
|
+
SQLite or Postgres does not require a frontend rewrite.
|
|
53
|
+
|
|
54
|
+
Failure taxonomy reviews:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
node packages/agentcert-cli/dist/cli.js corpus review \
|
|
58
|
+
--corpus .agentcert/corpus/corpus.jsonl \
|
|
59
|
+
--reviews .agentcert/corpus/failure-reviews.jsonl \
|
|
60
|
+
--pattern-key "tripwire:network_failure:http-failure:no_console_error" \
|
|
61
|
+
--type console_error \
|
|
62
|
+
--status corrected \
|
|
63
|
+
--reviewer qa@example.com \
|
|
64
|
+
--confidence 0.85 \
|
|
65
|
+
--first-divergence "Console displayed a 503 failure before the task completed." \
|
|
66
|
+
--screenshot "runs/http-failure/step-2.png" \
|
|
67
|
+
--trace "runs/http-failure/trace.json" \
|
|
68
|
+
--why "The failed assertion is about a browser console error." \
|
|
69
|
+
--signal "assertion type no_console_error"
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
The review command appends an `agentcert.failure_review` JSONL record, reapplies
|
|
73
|
+
the review ledger, and writes the corrected taxonomy back to the corpus store.
|
|
74
|
+
Optional review metadata includes confidence, first-divergence snippets,
|
|
75
|
+
screenshot/trace pointers, supporting signals, classifier limitations, and a
|
|
76
|
+
structured taxonomy rationale for later classifier training and evaluation.
|
|
77
|
+
|
|
78
|
+
For local development inside this repository:
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
npm --prefix packages/agentcert-cli ci
|
|
82
|
+
npm --prefix packages/agentcert-cli run build
|
|
83
|
+
node packages/agentcert-cli/dist/cli.js run --profile public-demo
|
|
84
|
+
```
|
package/dist/badge.js
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export function renderAgentCertBadge(bundle) {
|
|
2
|
+
const status = bundle.verdict.passed ? "pass" : "fail";
|
|
3
|
+
const color = bundle.verdict.passed ? "#087f5b" : "#cc2431";
|
|
4
|
+
const value = `${status} ${bundle.verdict.score}`;
|
|
5
|
+
const valueWidth = Math.max(54, value.length * 7 + 18);
|
|
6
|
+
const labelWidth = 76;
|
|
7
|
+
const width = labelWidth + valueWidth;
|
|
8
|
+
return `<svg xmlns="http://www.w3.org/2000/svg" width="${width}" height="20" role="img" aria-label="agentcert: ${escapeXml(value)}">
|
|
9
|
+
<title>agentcert: ${escapeXml(value)}</title>
|
|
10
|
+
<linearGradient id="s" x2="0" y2="100%">
|
|
11
|
+
<stop offset="0" stop-color="#fff" stop-opacity=".12"/>
|
|
12
|
+
<stop offset="1" stop-color="#000" stop-opacity=".12"/>
|
|
13
|
+
</linearGradient>
|
|
14
|
+
<clipPath id="r"><rect width="${width}" height="20" rx="3" fill="#fff"/></clipPath>
|
|
15
|
+
<g clip-path="url(#r)">
|
|
16
|
+
<rect width="${labelWidth}" height="20" fill="#07172f"/>
|
|
17
|
+
<rect x="${labelWidth}" width="${valueWidth}" height="20" fill="${color}"/>
|
|
18
|
+
<rect width="${width}" height="20" fill="url(#s)"/>
|
|
19
|
+
</g>
|
|
20
|
+
<g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" font-size="11">
|
|
21
|
+
<text x="${labelWidth / 2}" y="15" fill="#010101" fill-opacity=".3">agentcert</text>
|
|
22
|
+
<text x="${labelWidth / 2}" y="14">agentcert</text>
|
|
23
|
+
<text x="${labelWidth + valueWidth / 2}" y="15" fill="#010101" fill-opacity=".3">${escapeXml(value)}</text>
|
|
24
|
+
<text x="${labelWidth + valueWidth / 2}" y="14">${escapeXml(value)}</text>
|
|
25
|
+
</g>
|
|
26
|
+
</svg>
|
|
27
|
+
`;
|
|
28
|
+
}
|
|
29
|
+
function escapeXml(value) {
|
|
30
|
+
return value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """);
|
|
31
|
+
}
|
package/dist/bundle.js
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
export function buildEvidenceBundle(results, subjectName, subjectType = "agent") {
|
|
2
|
+
const evidence = results.flatMap((result) => result.evidence);
|
|
3
|
+
const score = results.length === 0 ? 0 : Math.round(results.reduce((sum, result) => sum + result.score, 0) / results.length);
|
|
4
|
+
const passed = results.length > 0 && results.every((result) => result.passed);
|
|
5
|
+
const artifacts = {};
|
|
6
|
+
for (const result of results) {
|
|
7
|
+
for (const [name, path] of Object.entries(result.artifacts)) {
|
|
8
|
+
if (path) {
|
|
9
|
+
artifacts[`${result.product}.${name}`] = path;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
return {
|
|
14
|
+
schemaName: "agentcert.evidence_bundle",
|
|
15
|
+
schemaVersion: "1",
|
|
16
|
+
schemaSemver: "1.0.0",
|
|
17
|
+
kind: "agentcert.evidence_bundle",
|
|
18
|
+
runId: `agentcert_${Date.now()}`,
|
|
19
|
+
generatedAt: new Date().toISOString(),
|
|
20
|
+
subject: {
|
|
21
|
+
name: subjectName,
|
|
22
|
+
type: parseSubjectType(subjectType),
|
|
23
|
+
},
|
|
24
|
+
verdict: {
|
|
25
|
+
passed,
|
|
26
|
+
score,
|
|
27
|
+
level: levelForScore(score, passed),
|
|
28
|
+
},
|
|
29
|
+
summary: {
|
|
30
|
+
products: [...new Set(results.map((result) => result.product))],
|
|
31
|
+
criticalEvidence: evidence.filter((item) => item.severity === "critical").length,
|
|
32
|
+
highEvidence: evidence.filter((item) => item.severity === "high").length,
|
|
33
|
+
totalEvidence: evidence.length,
|
|
34
|
+
},
|
|
35
|
+
results,
|
|
36
|
+
evidence,
|
|
37
|
+
artifacts,
|
|
38
|
+
standards: [
|
|
39
|
+
{
|
|
40
|
+
id: "aiuc-1",
|
|
41
|
+
name: "AIUC-1 agent security, safety, and reliability",
|
|
42
|
+
status: "mapped",
|
|
43
|
+
note: "AgentCert evidence can support preparation for independent AIUC-1-style reviews; it is not an official certification.",
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
id: "nist-ai-agent-standards",
|
|
47
|
+
name: "NIST AI Agent Standards Initiative",
|
|
48
|
+
status: "mapped",
|
|
49
|
+
note: "AgentCert evidence aligns with secure, interoperable, auditable agent deployment goals.",
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
id: "owasp-agentic-ai",
|
|
53
|
+
name: "OWASP Agentic AI threats and mitigations",
|
|
54
|
+
status: "mapped",
|
|
55
|
+
note: "AgentCert scenarios cover prompt injection, tool misuse, excessive agency, and runtime action governance.",
|
|
56
|
+
},
|
|
57
|
+
],
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
function levelForScore(score, passed) {
|
|
61
|
+
if (!passed) {
|
|
62
|
+
return "Not certified";
|
|
63
|
+
}
|
|
64
|
+
if (score >= 95) {
|
|
65
|
+
return "Platinum";
|
|
66
|
+
}
|
|
67
|
+
if (score >= 85) {
|
|
68
|
+
return "Gold";
|
|
69
|
+
}
|
|
70
|
+
if (score >= 70) {
|
|
71
|
+
return "Silver";
|
|
72
|
+
}
|
|
73
|
+
return "Needs review";
|
|
74
|
+
}
|
|
75
|
+
function parseSubjectType(value) {
|
|
76
|
+
if (value === "agent" || value === "mcp-server" || value === "tool" || value === "application") {
|
|
77
|
+
return value;
|
|
78
|
+
}
|
|
79
|
+
return "unknown";
|
|
80
|
+
}
|