trace-to-skill 0.1.26
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/LICENSE +190 -0
- package/README.md +456 -0
- package/dist/src/agentsLint.d.ts +15 -0
- package/dist/src/agentsLint.js +156 -0
- package/dist/src/agentsLint.js.map +1 -0
- package/dist/src/analyze.d.ts +3 -0
- package/dist/src/analyze.js +53 -0
- package/dist/src/analyze.js.map +1 -0
- package/dist/src/benchmark.d.ts +27 -0
- package/dist/src/benchmark.js +109 -0
- package/dist/src/benchmark.js.map +1 -0
- package/dist/src/cli.d.ts +2 -0
- package/dist/src/cli.js +281 -0
- package/dist/src/cli.js.map +1 -0
- package/dist/src/doctor.d.ts +18 -0
- package/dist/src/doctor.js +300 -0
- package/dist/src/doctor.js.map +1 -0
- package/dist/src/eval.d.ts +19 -0
- package/dist/src/eval.js +48 -0
- package/dist/src/eval.js.map +1 -0
- package/dist/src/github.d.ts +11 -0
- package/dist/src/github.js +66 -0
- package/dist/src/github.js.map +1 -0
- package/dist/src/githubContext.d.ts +6 -0
- package/dist/src/githubContext.js +60 -0
- package/dist/src/githubContext.js.map +1 -0
- package/dist/src/index.d.ts +11 -0
- package/dist/src/index.js +11 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/init.d.ts +16 -0
- package/dist/src/init.js +186 -0
- package/dist/src/init.js.map +1 -0
- package/dist/src/parsers.d.ts +2 -0
- package/dist/src/parsers.js +138 -0
- package/dist/src/parsers.js.map +1 -0
- package/dist/src/report.d.ts +11 -0
- package/dist/src/report.js +273 -0
- package/dist/src/report.js.map +1 -0
- package/dist/src/rules.d.ts +2 -0
- package/dist/src/rules.js +400 -0
- package/dist/src/rules.js.map +1 -0
- package/dist/src/scorecard.d.ts +25 -0
- package/dist/src/scorecard.js +75 -0
- package/dist/src/scorecard.js.map +1 -0
- package/dist/src/types.d.ts +31 -0
- package/dist/src/types.js +2 -0
- package/dist/src/types.js.map +1 -0
- package/docs/ADOPTION_GUIDE.md +97 -0
- package/docs/AGENTS_LINT.md +30 -0
- package/docs/BENCHMARK.md +21 -0
- package/docs/FAILURE_TAXONOMY.md +57 -0
- package/docs/SCORECARD.md +51 -0
- package/examples/codex-failed-run.md +17 -0
- package/fixtures/codex-session.jsonl +4 -0
- package/fixtures/failed-run.md +28 -0
- package/fixtures/github-pr-event.json +6 -0
- package/fixtures/github-prompt-injection-event.json +9 -0
- package/fixtures/instruction-drift/AGENTS.md +5 -0
- package/fixtures/instruction-drift/CLAUDE.md +6 -0
- package/fixtures/mcp-risk.json +22 -0
- package/fixtures/prompt-injection.md +7 -0
- package/fixtures/safe-run.md +12 -0
- package/package.json +55 -0
- package/schemas/agents-lint-result.schema.json +67 -0
- package/schemas/analysis-result.schema.json +134 -0
- package/schemas/doctor-result.schema.json +81 -0
- package/schemas/scorecard-result.schema.json +102 -0
- package/skills/codex-readiness-auditor/SKILL.md +61 -0
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export interface InitOptions {
|
|
2
|
+
cwd?: string;
|
|
3
|
+
traces?: string;
|
|
4
|
+
threshold?: string;
|
|
5
|
+
doctorThreshold?: string;
|
|
6
|
+
comment?: boolean;
|
|
7
|
+
sarif?: boolean;
|
|
8
|
+
force?: boolean;
|
|
9
|
+
dryRun?: boolean;
|
|
10
|
+
}
|
|
11
|
+
export interface InitResult {
|
|
12
|
+
written: string[];
|
|
13
|
+
skipped: string[];
|
|
14
|
+
message: string;
|
|
15
|
+
}
|
|
16
|
+
export declare function initProject(options?: InitOptions): Promise<InitResult>;
|
package/dist/src/init.js
ADDED
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
import { mkdir, writeFile } from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
export async function initProject(options = {}) {
|
|
4
|
+
const cwd = path.resolve(options.cwd ?? process.cwd());
|
|
5
|
+
const traces = normalizeTracePath(options.traces ?? "runs");
|
|
6
|
+
const threshold = normalizeThreshold(options.threshold ?? "80");
|
|
7
|
+
const doctorThreshold = normalizeThreshold(options.doctorThreshold ?? "85");
|
|
8
|
+
const files = buildInitFiles(traces, threshold, doctorThreshold, Boolean(options.comment), Boolean(options.sarif));
|
|
9
|
+
const written = [];
|
|
10
|
+
const skipped = [];
|
|
11
|
+
for (const file of files) {
|
|
12
|
+
const target = path.join(cwd, file.path);
|
|
13
|
+
const relative = path.relative(cwd, target);
|
|
14
|
+
if (options.dryRun) {
|
|
15
|
+
written.push(relative);
|
|
16
|
+
continue;
|
|
17
|
+
}
|
|
18
|
+
await mkdir(path.dirname(target), { recursive: true });
|
|
19
|
+
try {
|
|
20
|
+
await writeFile(target, file.content, {
|
|
21
|
+
encoding: "utf8",
|
|
22
|
+
flag: options.force ? "w" : "wx"
|
|
23
|
+
});
|
|
24
|
+
written.push(relative);
|
|
25
|
+
}
|
|
26
|
+
catch (error) {
|
|
27
|
+
if (isAlreadyExists(error)) {
|
|
28
|
+
skipped.push(relative);
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
throw error;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return {
|
|
35
|
+
written,
|
|
36
|
+
skipped,
|
|
37
|
+
message: buildInitMessage(written, skipped, options.dryRun)
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
function buildInitFiles(traces, threshold, doctorThreshold, comment, sarif) {
|
|
41
|
+
const files = [
|
|
42
|
+
{
|
|
43
|
+
path: ".github/workflows/codex-readiness.yml",
|
|
44
|
+
content: renderCodexReadinessWorkflow(doctorThreshold, comment)
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
path: ".github/workflows/agent-learning.yml",
|
|
48
|
+
content: renderAgentLearningWorkflow(traces, threshold, comment, sarif)
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
path: `${traces}/README.md`,
|
|
52
|
+
content: renderRunsReadme()
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
path: `${traces}/.gitkeep`,
|
|
56
|
+
content: ""
|
|
57
|
+
}
|
|
58
|
+
];
|
|
59
|
+
return files;
|
|
60
|
+
}
|
|
61
|
+
function renderCodexReadinessWorkflow(doctorThreshold, comment) {
|
|
62
|
+
const permissions = comment
|
|
63
|
+
? [
|
|
64
|
+
" permissions:",
|
|
65
|
+
" contents: read",
|
|
66
|
+
" pull-requests: write",
|
|
67
|
+
" issues: write"
|
|
68
|
+
].join("\n")
|
|
69
|
+
: " permissions:\n contents: read";
|
|
70
|
+
return `${[
|
|
71
|
+
"name: Codex Readiness",
|
|
72
|
+
"",
|
|
73
|
+
"on:",
|
|
74
|
+
" pull_request:",
|
|
75
|
+
" workflow_dispatch:",
|
|
76
|
+
"",
|
|
77
|
+
"jobs:",
|
|
78
|
+
" codex-readiness:",
|
|
79
|
+
" runs-on: ubuntu-latest",
|
|
80
|
+
permissions,
|
|
81
|
+
" steps:",
|
|
82
|
+
" - uses: actions/checkout@v5",
|
|
83
|
+
" - id: trace-to-skill",
|
|
84
|
+
" uses: grnbtqdbyx-create/trace-to-skill@v0.1.26",
|
|
85
|
+
" with:",
|
|
86
|
+
" mode: all",
|
|
87
|
+
` doctor-threshold: "${doctorThreshold}"`,
|
|
88
|
+
comment ? ' doctor-comment: "true"' : undefined,
|
|
89
|
+
comment ? ' scorecard-comment: "true"' : undefined,
|
|
90
|
+
' job-summary: "true"',
|
|
91
|
+
comment ? " github-token: ${{ github.token }}" : undefined,
|
|
92
|
+
" - run: |",
|
|
93
|
+
" echo \"Codex readiness score is ${{ steps.trace-to-skill.outputs.doctor-score }}\"",
|
|
94
|
+
" echo \"Benchmark status is ${{ steps.trace-to-skill.outputs.benchmark-status }}\"",
|
|
95
|
+
" echo \"Scorecard status is ${{ steps.trace-to-skill.outputs.scorecard-status }}\""
|
|
96
|
+
].filter((line) => Boolean(line)).join("\n")}\n`;
|
|
97
|
+
}
|
|
98
|
+
function renderAgentLearningWorkflow(traces, threshold, comment, sarif) {
|
|
99
|
+
const permissions = comment || sarif
|
|
100
|
+
? [
|
|
101
|
+
" permissions:",
|
|
102
|
+
" contents: read",
|
|
103
|
+
comment ? " pull-requests: write" : undefined,
|
|
104
|
+
comment ? " issues: write" : undefined,
|
|
105
|
+
sarif ? " security-events: write" : undefined
|
|
106
|
+
].filter((line) => Boolean(line)).join("\n")
|
|
107
|
+
: " permissions:\n contents: read";
|
|
108
|
+
const steps = [
|
|
109
|
+
" - uses: actions/checkout@v5",
|
|
110
|
+
" - id: trace-to-skill",
|
|
111
|
+
" uses: grnbtqdbyx-create/trace-to-skill@v0.1.26",
|
|
112
|
+
" with:",
|
|
113
|
+
" mode: traces",
|
|
114
|
+
` traces: ${traces}`,
|
|
115
|
+
` threshold: "${threshold}"`,
|
|
116
|
+
comment ? ' comment: "true"' : undefined,
|
|
117
|
+
' job-summary: "true"',
|
|
118
|
+
comment ? " github-token: ${{ github.token }}" : undefined,
|
|
119
|
+
sarif ? ` - run: npx github:grnbtqdbyx-create/trace-to-skill analyze ${traces} --format sarif --output trace-to-skill.sarif` : undefined,
|
|
120
|
+
sarif ? " - uses: github/codeql-action/upload-sarif@v4" : undefined,
|
|
121
|
+
sarif ? " with:" : undefined,
|
|
122
|
+
sarif ? " sarif_file: trace-to-skill.sarif" : undefined,
|
|
123
|
+
" - run: echo \"Agent report is ${{ steps.trace-to-skill.outputs.agent-report }}\""
|
|
124
|
+
].filter((line) => Boolean(line));
|
|
125
|
+
return `${[
|
|
126
|
+
"name: Agent Learning Report",
|
|
127
|
+
"",
|
|
128
|
+
"on:",
|
|
129
|
+
" pull_request:",
|
|
130
|
+
" workflow_dispatch:",
|
|
131
|
+
"",
|
|
132
|
+
"jobs:",
|
|
133
|
+
" trace-to-skill:",
|
|
134
|
+
" runs-on: ubuntu-latest",
|
|
135
|
+
permissions,
|
|
136
|
+
" steps:",
|
|
137
|
+
...steps
|
|
138
|
+
].join("\n")}\n`;
|
|
139
|
+
}
|
|
140
|
+
function renderRunsReadme() {
|
|
141
|
+
return `# Agent Run Traces
|
|
142
|
+
|
|
143
|
+
Store anonymized Codex, Claude Code, Cursor, Copilot, Gemini CLI, OpenCode, or MCP-enabled agent run traces here.
|
|
144
|
+
|
|
145
|
+
Recommended files:
|
|
146
|
+
|
|
147
|
+
- failed-run.md
|
|
148
|
+
- codex-session.jsonl
|
|
149
|
+
- mcp-risk.json
|
|
150
|
+
|
|
151
|
+
Do not commit secrets, customer data, private source code, or full proprietary transcripts.
|
|
152
|
+
`;
|
|
153
|
+
}
|
|
154
|
+
function buildInitMessage(written, skipped, dryRun) {
|
|
155
|
+
const prefix = dryRun ? "dry-run: " : "";
|
|
156
|
+
const parts = [`${prefix}prepared ${written.length} file(s)`];
|
|
157
|
+
if (skipped.length > 0) {
|
|
158
|
+
parts.push(`skipped ${skipped.length} existing file(s)`);
|
|
159
|
+
}
|
|
160
|
+
return parts.join(", ");
|
|
161
|
+
}
|
|
162
|
+
function isAlreadyExists(error) {
|
|
163
|
+
return error instanceof Error && "code" in error && error.code === "EEXIST";
|
|
164
|
+
}
|
|
165
|
+
function normalizeTracePath(value) {
|
|
166
|
+
const traces = value.replace(/^\.\/+/, "");
|
|
167
|
+
if (!traces || path.isAbsolute(traces) || traces.includes("\\") || !/^[A-Za-z0-9._/-]+$/.test(traces)) {
|
|
168
|
+
throw new Error("--traces must be a safe relative path such as runs or agent-runs");
|
|
169
|
+
}
|
|
170
|
+
const parts = traces.split("/");
|
|
171
|
+
if (parts.some((part) => !part || part === "." || part === "..")) {
|
|
172
|
+
throw new Error("--traces must not contain empty, current, or parent directory segments");
|
|
173
|
+
}
|
|
174
|
+
return traces;
|
|
175
|
+
}
|
|
176
|
+
function normalizeThreshold(value) {
|
|
177
|
+
if (!/^[0-9]{1,3}$/.test(value)) {
|
|
178
|
+
throw new Error("--threshold must be an integer between 1 and 100");
|
|
179
|
+
}
|
|
180
|
+
const threshold = Number(value);
|
|
181
|
+
if (!Number.isInteger(threshold) || threshold < 1 || threshold > 100) {
|
|
182
|
+
throw new Error("--threshold must be an integer between 1 and 100");
|
|
183
|
+
}
|
|
184
|
+
return String(threshold);
|
|
185
|
+
}
|
|
186
|
+
//# sourceMappingURL=init.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/init.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,IAAI,MAAM,WAAW,CAAC;AAmB7B,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,UAAuB,EAAE;IACzD,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IACvD,MAAM,MAAM,GAAG,kBAAkB,CAAC,OAAO,CAAC,MAAM,IAAI,MAAM,CAAC,CAAC;IAC5D,MAAM,SAAS,GAAG,kBAAkB,CAAC,OAAO,CAAC,SAAS,IAAI,IAAI,CAAC,CAAC;IAChE,MAAM,eAAe,GAAG,kBAAkB,CAAC,OAAO,CAAC,eAAe,IAAI,IAAI,CAAC,CAAC;IAC5E,MAAM,KAAK,GAAG,cAAc,CAAC,MAAM,EAAE,SAAS,EAAE,eAAe,EAAE,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;IACnH,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,MAAM,OAAO,GAAa,EAAE,CAAC;IAE7B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;QACzC,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;QAC5C,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;YACnB,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YACvB,SAAS;QACX,CAAC;QAED,MAAM,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACvD,IAAI,CAAC;YACH,MAAM,SAAS,CAAC,MAAM,EAAE,IAAI,CAAC,OAAO,EAAE;gBACpC,QAAQ,EAAE,MAAM;gBAChB,IAAI,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI;aACjC,CAAC,CAAC;YACH,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACzB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,eAAe,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC3B,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;gBACvB,SAAS;YACX,CAAC;YAED,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;IAED,OAAO;QACL,OAAO;QACP,OAAO;QACP,OAAO,EAAE,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,MAAM,CAAC;KAC5D,CAAC;AACJ,CAAC;AAOD,SAAS,cAAc,CAAC,MAAc,EAAE,SAAiB,EAAE,eAAuB,EAAE,OAAgB,EAAE,KAAc;IAClH,MAAM,KAAK,GAAe;QACxB;YACE,IAAI,EAAE,uCAAuC;YAC7C,OAAO,EAAE,4BAA4B,CAAC,eAAe,EAAE,OAAO,CAAC;SAChE;QACD;YACE,IAAI,EAAE,sCAAsC;YAC5C,OAAO,EAAE,2BAA2B,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,KAAK,CAAC;SACxE;QACD;YACE,IAAI,EAAE,GAAG,MAAM,YAAY;YAC3B,OAAO,EAAE,gBAAgB,EAAE;SAC5B;QACD;YACE,IAAI,EAAE,GAAG,MAAM,WAAW;YAC1B,OAAO,EAAE,EAAE;SACZ;KACF,CAAC;IAEF,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,4BAA4B,CAAC,eAAuB,EAAE,OAAgB;IAC7E,MAAM,WAAW,GAAG,OAAO;QACzB,CAAC,CAAC;YACA,kBAAkB;YAClB,sBAAsB;YACtB,4BAA4B;YAC5B,qBAAqB;SACtB,CAAC,IAAI,CAAC,IAAI,CAAC;QACZ,CAAC,CAAC,wCAAwC,CAAC;IAE7C,OAAO,GAAG;QACR,uBAAuB;QACvB,EAAE;QACF,KAAK;QACL,iBAAiB;QACjB,sBAAsB;QACtB,EAAE;QACF,OAAO;QACP,oBAAoB;QACpB,4BAA4B;QAC5B,WAAW;QACX,YAAY;QACZ,mCAAmC;QACnC,4BAA4B;QAC5B,wDAAwD;QACxD,eAAe;QACf,qBAAqB;QACrB,gCAAgC,eAAe,GAAG;QAClD,OAAO,CAAC,CAAC,CAAC,kCAAkC,CAAC,CAAC,CAAC,SAAS;QACxD,OAAO,CAAC,CAAC,CAAC,qCAAqC,CAAC,CAAC,CAAC,SAAS;QAC3D,+BAA+B;QAC/B,OAAO,CAAC,CAAC,CAAC,6CAA6C,CAAC,CAAC,CAAC,SAAS;QACnE,gBAAgB;QAChB,8FAA8F;QAC9F,6FAA6F;QAC7F,6FAA6F;KAC9F,CAAC,MAAM,CAAC,CAAC,IAAI,EAAkB,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;AACnE,CAAC;AAED,SAAS,2BAA2B,CAAC,MAAc,EAAE,SAAiB,EAAE,OAAgB,EAAE,KAAc;IACtG,MAAM,WAAW,GAAG,OAAO,IAAI,KAAK;QAClC,CAAC,CAAC;YACA,kBAAkB;YAClB,sBAAsB;YACtB,OAAO,CAAC,CAAC,CAAC,4BAA4B,CAAC,CAAC,CAAC,SAAS;YAClD,OAAO,CAAC,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,SAAS;YAC3C,KAAK,CAAC,CAAC,CAAC,8BAA8B,CAAC,CAAC,CAAC,SAAS;SACnD,CAAC,MAAM,CAAC,CAAC,IAAI,EAAkB,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;QAC5D,CAAC,CAAC,wCAAwC,CAAC;IAE7C,MAAM,KAAK,GAAG;QACZ,mCAAmC;QACnC,4BAA4B;QAC5B,wDAAwD;QACxD,eAAe;QACf,wBAAwB;QACxB,qBAAqB,MAAM,EAAE;QAC7B,yBAAyB,SAAS,GAAG;QACrC,OAAO,CAAC,CAAC,CAAC,2BAA2B,CAAC,CAAC,CAAC,SAAS;QACjD,+BAA+B;QAC/B,OAAO,CAAC,CAAC,CAAC,6CAA6C,CAAC,CAAC,CAAC,SAAS;QACnE,KAAK,CAAC,CAAC,CAAC,oEAAoE,MAAM,+CAA+C,CAAC,CAAC,CAAC,SAAS;QAC7I,KAAK,CAAC,CAAC,CAAC,oDAAoD,CAAC,CAAC,CAAC,SAAS;QACxE,KAAK,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,SAAS;QACnC,KAAK,CAAC,CAAC,CAAC,4CAA4C,CAAC,CAAC,CAAC,SAAS;QAChE,wFAAwF;KACzF,CAAC,MAAM,CAAC,CAAC,IAAI,EAAkB,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;IAElD,OAAO,GAAG;QACR,6BAA6B;QAC7B,EAAE;QACF,KAAK;QACL,iBAAiB;QACjB,sBAAsB;QACtB,EAAE;QACF,OAAO;QACP,mBAAmB;QACnB,4BAA4B;QAC5B,WAAW;QACX,YAAY;QACZ,GAAG,KAAK;KACT,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;AACnB,CAAC;AAED,SAAS,gBAAgB;IACvB,OAAO;;;;;;;;;;;CAWR,CAAC;AACF,CAAC;AAED,SAAS,gBAAgB,CAAC,OAAiB,EAAE,OAAiB,EAAE,MAA2B;IACzF,MAAM,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC;IACzC,MAAM,KAAK,GAAG,CAAC,GAAG,MAAM,YAAY,OAAO,CAAC,MAAM,UAAU,CAAC,CAAC;IAC9D,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvB,KAAK,CAAC,IAAI,CAAC,WAAW,OAAO,CAAC,MAAM,mBAAmB,CAAC,CAAC;IAC3D,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED,SAAS,eAAe,CAAC,KAAc;IACrC,OAAO,KAAK,YAAY,KAAK,IAAI,MAAM,IAAI,KAAK,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ,CAAC;AAC9E,CAAC;AAED,SAAS,kBAAkB,CAAC,KAAa;IACvC,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;IAC3C,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,oBAAoB,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;QACtG,MAAM,IAAI,KAAK,CAAC,kEAAkE,CAAC,CAAC;IACtF,CAAC;IAED,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAChC,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,IAAI,IAAI,KAAK,GAAG,IAAI,IAAI,KAAK,IAAI,CAAC,EAAE,CAAC;QACjE,MAAM,IAAI,KAAK,CAAC,wEAAwE,CAAC,CAAC;IAC5F,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,kBAAkB,CAAC,KAAa;IACvC,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QAChC,MAAM,IAAI,KAAK,CAAC,kDAAkD,CAAC,CAAC;IACtE,CAAC;IAED,MAAM,SAAS,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IAChC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,SAAS,CAAC,IAAI,SAAS,GAAG,CAAC,IAAI,SAAS,GAAG,GAAG,EAAE,CAAC;QACrE,MAAM,IAAI,KAAK,CAAC,kDAAkD,CAAC,CAAC;IACtE,CAAC;IAED,OAAO,MAAM,CAAC,SAAS,CAAC,CAAC;AAC3B,CAAC"}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { promises as fs } from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
const SUPPORTED_EXTENSIONS = new Set([".txt", ".log", ".md", ".json", ".jsonl"]);
|
|
4
|
+
export async function loadTraceInputs(targets) {
|
|
5
|
+
const expanded = [];
|
|
6
|
+
for (const target of targets.length > 0 ? targets : [process.cwd()]) {
|
|
7
|
+
const absolute = path.resolve(target);
|
|
8
|
+
const stats = await fs.stat(absolute);
|
|
9
|
+
if (stats.isDirectory()) {
|
|
10
|
+
expanded.push(...(await loadDirectory(absolute)));
|
|
11
|
+
}
|
|
12
|
+
else {
|
|
13
|
+
expanded.push(await loadFile(absolute));
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
return expanded.sort((a, b) => a.path.localeCompare(b.path));
|
|
17
|
+
}
|
|
18
|
+
async function loadDirectory(dir) {
|
|
19
|
+
const entries = await fs.readdir(dir, { withFileTypes: true });
|
|
20
|
+
const inputs = [];
|
|
21
|
+
for (const entry of entries) {
|
|
22
|
+
if (entry.name === "node_modules" || entry.name === ".git" || entry.name === "dist") {
|
|
23
|
+
continue;
|
|
24
|
+
}
|
|
25
|
+
const fullPath = path.join(dir, entry.name);
|
|
26
|
+
if (entry.isDirectory()) {
|
|
27
|
+
inputs.push(...(await loadDirectory(fullPath)));
|
|
28
|
+
continue;
|
|
29
|
+
}
|
|
30
|
+
if (entry.isFile() && SUPPORTED_EXTENSIONS.has(path.extname(entry.name).toLowerCase())) {
|
|
31
|
+
inputs.push(await loadFile(fullPath));
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return inputs;
|
|
35
|
+
}
|
|
36
|
+
async function loadFile(filePath) {
|
|
37
|
+
const raw = await fs.readFile(filePath, "utf8");
|
|
38
|
+
return {
|
|
39
|
+
path: path.relative(process.cwd(), filePath),
|
|
40
|
+
content: normalizeJsonl(raw)
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
function normalizeJsonl(raw) {
|
|
44
|
+
const lines = raw.split(/\r?\n/);
|
|
45
|
+
const normalized = lines.map((line) => {
|
|
46
|
+
const trimmed = line.trim();
|
|
47
|
+
if (!trimmed.startsWith("{")) {
|
|
48
|
+
return line;
|
|
49
|
+
}
|
|
50
|
+
try {
|
|
51
|
+
const parsed = JSON.parse(trimmed);
|
|
52
|
+
return extractTraceLine(parsed) ?? line;
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
return line;
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
return normalized.join("\n");
|
|
59
|
+
}
|
|
60
|
+
function extractTraceLine(value) {
|
|
61
|
+
const timestamp = typeof value.timestamp === "string" ? value.timestamp : undefined;
|
|
62
|
+
const type = typeof value.type === "string" ? value.type : undefined;
|
|
63
|
+
const payload = asObject(value.payload);
|
|
64
|
+
if (type === "response_item" && payload) {
|
|
65
|
+
const payloadType = typeof payload.type === "string" ? payload.type : "response_item";
|
|
66
|
+
const role = typeof payload.role === "string" ? payload.role : undefined;
|
|
67
|
+
if (payloadType === "function_call") {
|
|
68
|
+
const name = typeof payload.name === "string" ? payload.name : "function_call";
|
|
69
|
+
const args = stringifyUnknown(payload.arguments);
|
|
70
|
+
return joinParts(timestamp, "tool_call", name, args);
|
|
71
|
+
}
|
|
72
|
+
if (payloadType === "function_call_output") {
|
|
73
|
+
return joinParts(timestamp, "tool_output", extractText(payload.output) ?? stringifyUnknown(payload.output));
|
|
74
|
+
}
|
|
75
|
+
const text = extractText(payload.content) ?? extractText(payload.summary);
|
|
76
|
+
if (text) {
|
|
77
|
+
return joinParts(timestamp, payloadType, role, text);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
if (type === "event_msg" && payload) {
|
|
81
|
+
const payloadType = typeof payload.type === "string" ? payload.type : "event_msg";
|
|
82
|
+
const text = extractText(payload.message) ?? extractText(payload.content) ?? extractText(payload.text);
|
|
83
|
+
if (text) {
|
|
84
|
+
return joinParts(timestamp, payloadType, text);
|
|
85
|
+
}
|
|
86
|
+
if (payloadType === "token_count") {
|
|
87
|
+
return joinParts(timestamp, payloadType, stringifyUnknown(payload));
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return extractText(value);
|
|
91
|
+
}
|
|
92
|
+
function extractText(value) {
|
|
93
|
+
if (typeof value === "string") {
|
|
94
|
+
return value;
|
|
95
|
+
}
|
|
96
|
+
if (Array.isArray(value)) {
|
|
97
|
+
const parts = value.map((item) => extractText(item)).filter((item) => Boolean(item));
|
|
98
|
+
return parts.length > 0 ? parts.join("\n") : undefined;
|
|
99
|
+
}
|
|
100
|
+
const object = asObject(value);
|
|
101
|
+
if (!object) {
|
|
102
|
+
return undefined;
|
|
103
|
+
}
|
|
104
|
+
for (const key of ["message", "content", "text", "output", "error", "summary"]) {
|
|
105
|
+
const candidate = object[key];
|
|
106
|
+
const text = extractText(candidate);
|
|
107
|
+
if (text) {
|
|
108
|
+
return text;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
const nested = object.item ?? object.event ?? object.payload ?? object.delta;
|
|
112
|
+
const nestedObject = asObject(nested);
|
|
113
|
+
if (nestedObject) {
|
|
114
|
+
return extractText(nestedObject);
|
|
115
|
+
}
|
|
116
|
+
return undefined;
|
|
117
|
+
}
|
|
118
|
+
function joinParts(...parts) {
|
|
119
|
+
return parts.filter((part) => Boolean(part && part.trim().length > 0)).join(" ");
|
|
120
|
+
}
|
|
121
|
+
function stringifyUnknown(value) {
|
|
122
|
+
if (value === undefined || value === null) {
|
|
123
|
+
return undefined;
|
|
124
|
+
}
|
|
125
|
+
if (typeof value === "string") {
|
|
126
|
+
return value;
|
|
127
|
+
}
|
|
128
|
+
try {
|
|
129
|
+
return JSON.stringify(value);
|
|
130
|
+
}
|
|
131
|
+
catch {
|
|
132
|
+
return String(value);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
function asObject(value) {
|
|
136
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : undefined;
|
|
137
|
+
}
|
|
138
|
+
//# sourceMappingURL=parsers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parsers.js","sourceRoot":"","sources":["../../src/parsers.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ComparisonResult } from "./eval.js";
|
|
2
|
+
import type { DoctorResult } from "./doctor.js";
|
|
3
|
+
import type { AnalysisResult } from "./types.js";
|
|
4
|
+
export declare function renderMarkdown(result: AnalysisResult): string;
|
|
5
|
+
export declare function renderAgentsRules(result: AnalysisResult): string;
|
|
6
|
+
export declare function renderSkill(result: AnalysisResult): string;
|
|
7
|
+
export declare function renderPrComment(result: AnalysisResult): string;
|
|
8
|
+
export declare function renderComparison(result: ComparisonResult): string;
|
|
9
|
+
export declare function renderDoctorMarkdown(result: DoctorResult): string;
|
|
10
|
+
export declare function renderDoctorPrComment(result: DoctorResult, threshold?: number): string;
|
|
11
|
+
export declare function renderSarif(result: AnalysisResult): string;
|
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
export function renderMarkdown(result) {
|
|
2
|
+
const lines = [
|
|
3
|
+
"# Agent Learning Report",
|
|
4
|
+
"",
|
|
5
|
+
`Score: **${result.score}/100**`,
|
|
6
|
+
"",
|
|
7
|
+
result.summary,
|
|
8
|
+
"",
|
|
9
|
+
`Generated: ${result.generatedAt}`,
|
|
10
|
+
"",
|
|
11
|
+
"## Findings",
|
|
12
|
+
""
|
|
13
|
+
];
|
|
14
|
+
if (result.findings.length === 0) {
|
|
15
|
+
lines.push("No findings.");
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
result.findings.forEach((finding, index) => {
|
|
19
|
+
lines.push(renderFinding(finding, index + 1));
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
lines.push("", "## Suggested AGENTS.md Rules", "");
|
|
23
|
+
result.recommendations.forEach((recommendation) => {
|
|
24
|
+
lines.push(`- ${recommendation}`);
|
|
25
|
+
});
|
|
26
|
+
return `${lines.join("\n")}\n`;
|
|
27
|
+
}
|
|
28
|
+
export function renderAgentsRules(result) {
|
|
29
|
+
const lines = [
|
|
30
|
+
"# Agent Rules Generated From Failed Runs",
|
|
31
|
+
"",
|
|
32
|
+
"<!-- Generated by trace-to-skill. Review before committing. -->",
|
|
33
|
+
"",
|
|
34
|
+
"## Verification",
|
|
35
|
+
""
|
|
36
|
+
];
|
|
37
|
+
result.recommendations.forEach((recommendation) => {
|
|
38
|
+
lines.push(`- ${recommendation}`);
|
|
39
|
+
});
|
|
40
|
+
return `${lines.join("\n")}\n`;
|
|
41
|
+
}
|
|
42
|
+
export function renderSkill(result) {
|
|
43
|
+
const slugs = Array.from(new Set(result.findings.map((finding) => finding.suggestedSkill ?? finding.kind)));
|
|
44
|
+
const name = slugs[0] ?? "agent-verification";
|
|
45
|
+
const lines = [
|
|
46
|
+
"---",
|
|
47
|
+
`name: ${name}`,
|
|
48
|
+
"description: Use when an AI coding agent is about to finish a task or repeat a workflow that previously failed.",
|
|
49
|
+
"---",
|
|
50
|
+
"",
|
|
51
|
+
"# Skill Generated From Agent Traces",
|
|
52
|
+
"",
|
|
53
|
+
"Before completing the task, apply these rules:",
|
|
54
|
+
""
|
|
55
|
+
];
|
|
56
|
+
result.recommendations.forEach((recommendation) => {
|
|
57
|
+
lines.push(`- ${recommendation}`);
|
|
58
|
+
});
|
|
59
|
+
lines.push("", "## Evidence Required", "", "- List commands run, results, and any remaining blockers.");
|
|
60
|
+
return `${lines.join("\n")}\n`;
|
|
61
|
+
}
|
|
62
|
+
export function renderPrComment(result) {
|
|
63
|
+
const topFindings = result.findings.slice(0, 5);
|
|
64
|
+
const status = result.findings.some((finding) => finding.severity === "critical") ? "needs attention" : "reviewable";
|
|
65
|
+
const lines = [
|
|
66
|
+
"<!-- trace-to-skill-report -->",
|
|
67
|
+
"## trace-to-skill Agent Learning Report",
|
|
68
|
+
"",
|
|
69
|
+
`Score: **${result.score}/100** (${status})`,
|
|
70
|
+
"",
|
|
71
|
+
result.summary,
|
|
72
|
+
""
|
|
73
|
+
];
|
|
74
|
+
if (topFindings.length > 0) {
|
|
75
|
+
lines.push("### Top Findings", "");
|
|
76
|
+
topFindings.forEach((finding) => {
|
|
77
|
+
const firstEvidence = finding.evidence[0];
|
|
78
|
+
const evidence = firstEvidence ? ` Evidence: \`${firstEvidence.file}:${firstEvidence.line}\`.` : "";
|
|
79
|
+
lines.push(`- **${finding.severity}**: ${finding.title}.${evidence}`);
|
|
80
|
+
});
|
|
81
|
+
lines.push("");
|
|
82
|
+
}
|
|
83
|
+
if (result.recommendations.length > 0) {
|
|
84
|
+
lines.push("### Suggested Rules", "");
|
|
85
|
+
result.recommendations.slice(0, 5).forEach((recommendation) => {
|
|
86
|
+
lines.push(`- ${recommendation}`);
|
|
87
|
+
});
|
|
88
|
+
lines.push("");
|
|
89
|
+
}
|
|
90
|
+
lines.push("_Generated by trace-to-skill. Review generated rules before committing them._");
|
|
91
|
+
return `${lines.join("\n")}\n`;
|
|
92
|
+
}
|
|
93
|
+
export function renderComparison(result) {
|
|
94
|
+
return `${[
|
|
95
|
+
"# Agent Improvement Comparison",
|
|
96
|
+
"",
|
|
97
|
+
`Decision: **${result.decision}**`,
|
|
98
|
+
"",
|
|
99
|
+
`Before score: **${result.beforeScore}/100**`,
|
|
100
|
+
`After score: **${result.afterScore}/100**`,
|
|
101
|
+
`Delta: **${result.delta >= 0 ? "+" : ""}${result.delta}**`,
|
|
102
|
+
`Critical findings: **${result.beforeCriticalFindings} -> ${result.afterCriticalFindings}**`,
|
|
103
|
+
"",
|
|
104
|
+
result.message
|
|
105
|
+
].join("\n")}\n`;
|
|
106
|
+
}
|
|
107
|
+
export function renderDoctorMarkdown(result) {
|
|
108
|
+
const lines = [
|
|
109
|
+
"# Codex Readiness Doctor",
|
|
110
|
+
"",
|
|
111
|
+
`Score: **${result.score}/100**`,
|
|
112
|
+
"",
|
|
113
|
+
result.summary,
|
|
114
|
+
"",
|
|
115
|
+
`Repository: \`${result.root}\``,
|
|
116
|
+
`Generated: ${result.generatedAt}`,
|
|
117
|
+
"",
|
|
118
|
+
"## Checks",
|
|
119
|
+
""
|
|
120
|
+
];
|
|
121
|
+
result.checks.forEach((check) => {
|
|
122
|
+
const marker = check.status === "pass" ? "PASS" : check.status === "warn" ? "WARN" : "FAIL";
|
|
123
|
+
lines.push(`- **${marker}** ${check.title}: ${check.detail}`);
|
|
124
|
+
if (check.recommendation) {
|
|
125
|
+
lines.push(` Recommendation: ${check.recommendation}`);
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
lines.push("", "## Agent Risk Findings", "");
|
|
129
|
+
if (result.findings.length === 0) {
|
|
130
|
+
lines.push("No instruction or MCP risk findings detected.");
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
133
|
+
result.findings.forEach((finding) => {
|
|
134
|
+
const firstEvidence = finding.evidence[0];
|
|
135
|
+
const evidence = firstEvidence ? ` Evidence: \`${firstEvidence.file}:${firstEvidence.line}\`.` : "";
|
|
136
|
+
lines.push(`- **${finding.severity}** ${finding.title}.${evidence}`);
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
return `${lines.join("\n")}\n`;
|
|
140
|
+
}
|
|
141
|
+
export function renderDoctorPrComment(result, threshold) {
|
|
142
|
+
const failedChecks = result.checks.filter((check) => check.status === "fail");
|
|
143
|
+
const warningChecks = result.checks.filter((check) => check.status === "warn");
|
|
144
|
+
const criticalFindings = result.findings.filter((finding) => finding.severity === "critical");
|
|
145
|
+
const passesThreshold = threshold === undefined || result.score >= threshold;
|
|
146
|
+
const status = failedChecks.length > 0 || criticalFindings.length > 0 || !passesThreshold ? "needs attention" : "ready";
|
|
147
|
+
const lines = [
|
|
148
|
+
"<!-- trace-to-skill-doctor-report -->",
|
|
149
|
+
"## trace-to-skill Codex Readiness Doctor",
|
|
150
|
+
"",
|
|
151
|
+
`Score: **${result.score}/100**${threshold === undefined ? "" : ` (threshold ${threshold})`} - **${status}**`,
|
|
152
|
+
"",
|
|
153
|
+
result.summary,
|
|
154
|
+
""
|
|
155
|
+
];
|
|
156
|
+
const notableChecks = [...failedChecks, ...warningChecks].slice(0, 6);
|
|
157
|
+
if (notableChecks.length > 0) {
|
|
158
|
+
lines.push("### Checks To Review", "");
|
|
159
|
+
notableChecks.forEach((check) => {
|
|
160
|
+
const marker = check.status.toUpperCase();
|
|
161
|
+
lines.push(`- **${marker}** ${check.title}: ${check.detail}`);
|
|
162
|
+
if (check.recommendation) {
|
|
163
|
+
lines.push(` Recommendation: ${check.recommendation}`);
|
|
164
|
+
}
|
|
165
|
+
});
|
|
166
|
+
lines.push("");
|
|
167
|
+
}
|
|
168
|
+
else {
|
|
169
|
+
lines.push("### Checks", "", "All readiness checks passed.", "");
|
|
170
|
+
}
|
|
171
|
+
if (result.findings.length > 0) {
|
|
172
|
+
lines.push("### Agent Risk Findings", "");
|
|
173
|
+
result.findings.slice(0, 5).forEach((finding) => {
|
|
174
|
+
const firstEvidence = finding.evidence[0];
|
|
175
|
+
const evidence = firstEvidence ? ` Evidence: \`${firstEvidence.file}:${firstEvidence.line}\`.` : "";
|
|
176
|
+
lines.push(`- **${finding.severity}** ${finding.title}.${evidence}`);
|
|
177
|
+
});
|
|
178
|
+
lines.push("");
|
|
179
|
+
}
|
|
180
|
+
lines.push("_Generated by trace-to-skill. Keep this deterministic report separate from any LLM-written summary._");
|
|
181
|
+
return `${lines.join("\n")}\n`;
|
|
182
|
+
}
|
|
183
|
+
export function renderSarif(result) {
|
|
184
|
+
const sarif = {
|
|
185
|
+
version: "2.1.0",
|
|
186
|
+
$schema: "https://json.schemastore.org/sarif-2.1.0.json",
|
|
187
|
+
runs: [
|
|
188
|
+
{
|
|
189
|
+
tool: {
|
|
190
|
+
driver: {
|
|
191
|
+
name: "trace-to-skill",
|
|
192
|
+
informationUri: "https://github.com/grnbtqdbyx-create/trace-to-skill",
|
|
193
|
+
rules: buildSarifRules(result.findings)
|
|
194
|
+
}
|
|
195
|
+
},
|
|
196
|
+
results: result.findings.flatMap((finding) => finding.evidence.map((evidence) => ({
|
|
197
|
+
ruleId: finding.kind,
|
|
198
|
+
level: severityToSarifLevel(finding.severity),
|
|
199
|
+
message: {
|
|
200
|
+
text: `${finding.title}: ${evidence.excerpt}`
|
|
201
|
+
},
|
|
202
|
+
locations: [
|
|
203
|
+
{
|
|
204
|
+
physicalLocation: {
|
|
205
|
+
artifactLocation: {
|
|
206
|
+
uri: evidence.file
|
|
207
|
+
},
|
|
208
|
+
region: {
|
|
209
|
+
startLine: Math.max(1, evidence.line)
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
],
|
|
214
|
+
properties: {
|
|
215
|
+
severity: finding.severity,
|
|
216
|
+
suggestedRule: finding.suggestedRule
|
|
217
|
+
}
|
|
218
|
+
})))
|
|
219
|
+
}
|
|
220
|
+
]
|
|
221
|
+
};
|
|
222
|
+
return `${JSON.stringify(sarif, null, 2)}\n`;
|
|
223
|
+
}
|
|
224
|
+
function renderFinding(finding, index) {
|
|
225
|
+
const lines = [
|
|
226
|
+
`### ${index}. ${finding.title}`,
|
|
227
|
+
"",
|
|
228
|
+
`Severity: **${finding.severity}**`,
|
|
229
|
+
"",
|
|
230
|
+
finding.why,
|
|
231
|
+
"",
|
|
232
|
+
"Evidence:"
|
|
233
|
+
];
|
|
234
|
+
finding.evidence.forEach((evidence) => {
|
|
235
|
+
lines.push(`- \`${evidence.file}:${evidence.line}\` ${evidence.excerpt}`);
|
|
236
|
+
});
|
|
237
|
+
lines.push("", "Suggested rule:", "", `> ${finding.suggestedRule}`, "");
|
|
238
|
+
return lines.join("\n");
|
|
239
|
+
}
|
|
240
|
+
function buildSarifRules(findings) {
|
|
241
|
+
const byKind = new Map();
|
|
242
|
+
findings.forEach((finding) => {
|
|
243
|
+
if (!byKind.has(finding.kind)) {
|
|
244
|
+
byKind.set(finding.kind, finding);
|
|
245
|
+
}
|
|
246
|
+
});
|
|
247
|
+
return Array.from(byKind.values()).map((finding) => ({
|
|
248
|
+
id: finding.kind,
|
|
249
|
+
name: finding.title,
|
|
250
|
+
shortDescription: {
|
|
251
|
+
text: finding.title
|
|
252
|
+
},
|
|
253
|
+
fullDescription: {
|
|
254
|
+
text: finding.why
|
|
255
|
+
},
|
|
256
|
+
help: {
|
|
257
|
+
text: finding.suggestedRule
|
|
258
|
+
},
|
|
259
|
+
properties: {
|
|
260
|
+
severity: finding.severity
|
|
261
|
+
}
|
|
262
|
+
}));
|
|
263
|
+
}
|
|
264
|
+
function severityToSarifLevel(severity) {
|
|
265
|
+
if (severity === "critical" || severity === "high") {
|
|
266
|
+
return "error";
|
|
267
|
+
}
|
|
268
|
+
if (severity === "medium") {
|
|
269
|
+
return "warning";
|
|
270
|
+
}
|
|
271
|
+
return "note";
|
|
272
|
+
}
|
|
273
|
+
//# sourceMappingURL=report.js.map
|