pi-audit-master 0.1.1 → 0.1.3
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/dist/extensions/audit-manager.d.ts +19 -0
- package/dist/extensions/audit-manager.js +126 -0
- package/dist/extensions/fix-fleet.d.ts +13 -0
- package/dist/extensions/fix-fleet.js +59 -0
- package/dist/extensions/index.d.ts +6 -0
- package/dist/extensions/index.js +59 -0
- package/dist/extensions/project-mapper.d.ts +11 -0
- package/dist/extensions/project-mapper.js +139 -0
- package/dist/extensions/synthesizer.d.ts +18 -0
- package/dist/extensions/synthesizer.js +74 -0
- package/dist/extensions/types/index.d.ts +20 -0
- package/{extensions/types/index.ts → dist/extensions/types/index.js} +9 -32
- package/package.json +12 -2
- package/docs/design.md +0 -79
- package/docs/proposal.md +0 -52
- package/extensions/audit-manager.ts +0 -129
- package/extensions/fix-fleet.ts +0 -70
- package/extensions/index.ts +0 -69
- package/extensions/project-mapper.ts +0 -115
- package/extensions/synthesizer.ts +0 -96
- package/jest.config.js +0 -9
- package/tests/buggy-project/extensions/my-ext.ts +0 -11
- package/tests/buggy-project/extensions/pi-integration.ts +0 -12
- package/tests/buggy-project/extensions/pi_wrong.ts +0 -7
- package/tests/buggy-project/src/api.ts +0 -9
- package/tests/buggy-project/src/auth.ts +0 -17
- package/tests/buggy-project/src/code-quality.ts +0 -13
- package/tests/buggy-project/src/legacy.ts +0 -12
- package/tests/buggy-project/src/logic-flow.ts +0 -16
- package/tests/buggy-project/src/logic_error.ts +0 -8
- package/tests/buggy-project/src/messy_code.ts +0 -9
- package/tests/buggy-project/src/null-safety.ts +0 -12
- package/tests/buggy-project/src/null_safety.ts +0 -4
- package/tests/buggy-project/src/performance.ts +0 -17
- package/tests/buggy-project/src/performance_leak.ts +0 -12
- package/tests/buggy-project/src/pi-integration.ts +0 -11
- package/tests/buggy-project/src/utils.ts +0 -14
- package/tests/setup.sh +0 -87
- package/tests/verify-audit.test.ts +0 -77
- package/tsconfig.json +0 -16
- package/types/pi-coding-agent.d.ts +0 -13
- package/verify.ts +0 -44
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
// code-quality.ts
|
|
2
|
-
function calculateTax(amount: number) {
|
|
3
|
-
const tax = amount * 0.15;
|
|
4
|
-
// LOW: Redundant logic
|
|
5
|
-
const finalTax = amount * 0.15;
|
|
6
|
-
return finalTax;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
function checkStatus(val: number) {
|
|
10
|
-
// LOW: Magic number 42
|
|
11
|
-
if (val === 42) return "Special";
|
|
12
|
-
return "Normal";
|
|
13
|
-
}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
export function processPayment(amount: number) {
|
|
2
|
-
// LOW: Magic number
|
|
3
|
-
if (amount > 5000) {
|
|
4
|
-
return amount * 0.02;
|
|
5
|
-
}
|
|
6
|
-
return amount * 0.05;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
function oldLegacyHelper() {
|
|
10
|
-
// LOW: Dead code
|
|
11
|
-
console.log("This function is never called");
|
|
12
|
-
}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
// logic-flow.ts
|
|
2
|
-
async function updateUserPreferences(prefs: any[]) {
|
|
3
|
-
// HIGH: Race condition - forEach with async doesn't await
|
|
4
|
-
prefs.forEach(async (p) => {
|
|
5
|
-
await db.save(p);
|
|
6
|
-
});
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
function calculateSum(arr: number[]) {
|
|
10
|
-
let sum = 0;
|
|
11
|
-
// MEDIUM: Off-by-one error
|
|
12
|
-
for (let i = 0; i <= arr.length; i++) {
|
|
13
|
-
sum += arr[i];
|
|
14
|
-
}
|
|
15
|
-
return sum;
|
|
16
|
-
}
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
export async function updateData(id: string, data: any) {
|
|
2
|
-
const current = await fetchById(id);
|
|
3
|
-
// HIGH: Race condition - not checking if data changed between fetch and update
|
|
4
|
-
const updated = { ...current, ...data };
|
|
5
|
-
await save(updated);
|
|
6
|
-
}
|
|
7
|
-
async function fetchById(id: string) { return { id }; }
|
|
8
|
-
async function save(d: any) { return true; }
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
// null-safety.ts
|
|
2
|
-
async function fetchUserData(id: string) {
|
|
3
|
-
const response = await api.get(`/user/${id}`);
|
|
4
|
-
// CRITICAL: Null access on response.data.profile
|
|
5
|
-
return response.data.profile.name;
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
function processPayment(input: any) {
|
|
9
|
-
// HIGH: Unsafe cast to any
|
|
10
|
-
const amount = (input as any).amount;
|
|
11
|
-
return amount * 1.1;
|
|
12
|
-
}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
// performance.ts
|
|
2
|
-
function processLargeDataset(data: any[]) {
|
|
3
|
-
const duplicates = [];
|
|
4
|
-
// MEDIUM: O(n^2) complexity
|
|
5
|
-
for (let i = 0; i < data.length; i++) {
|
|
6
|
-
for (let j = i + 1; j < data.length; j++) {
|
|
7
|
-
if (data[i].id === data[j].id) duplicates.push(data[i]);
|
|
8
|
-
}
|
|
9
|
-
}
|
|
10
|
-
return duplicates;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
const log = [];
|
|
14
|
-
function onMessageReceived(msg: string) {
|
|
15
|
-
// HIGH: Memory leak - global array grows indefinitely
|
|
16
|
-
log.push(msg);
|
|
17
|
-
}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
export function findDuplicates(arr: string[]) {
|
|
2
|
-
const duplicates: string[] = [];
|
|
3
|
-
// MEDIUM: O(n^2) complexity
|
|
4
|
-
for (let i = 0; i < arr.length; i++) {
|
|
5
|
-
for (let j = i + 1; j < arr.length; j++) {
|
|
6
|
-
if (arr[i] === arr[j] && !duplicates.includes(arr[i])) {
|
|
7
|
-
duplicates.push(arr[i]);
|
|
8
|
-
}
|
|
9
|
-
}
|
|
10
|
-
}
|
|
11
|
-
return duplicates;
|
|
12
|
-
}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import type { ExtensionAPI } from 'pi-coding-agent';
|
|
2
|
-
|
|
3
|
-
export default function (pi: ExtensionAPI) {
|
|
4
|
-
// CRITICAL: Wrong event name. Should be 'tool_execution_start'.
|
|
5
|
-
pi.on('tool_execution_started', async (event, ctx) => {
|
|
6
|
-
if (event.toolName === 'delete_everything') {
|
|
7
|
-
ctx.ui.notify('Danger!', 'error');
|
|
8
|
-
// HIGH: Forgets to call event.abort(). Tool will execute anyway.
|
|
9
|
-
}
|
|
10
|
-
});
|
|
11
|
-
}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
export function findDuplicates(list: string[]) {
|
|
2
|
-
const duplicates: string[] = [];
|
|
3
|
-
|
|
4
|
-
// MEDIUM: O(n^2) complexity.
|
|
5
|
-
// For each item, it scans the rest of the list.
|
|
6
|
-
for (let i = 0; i < list.length; i++) {
|
|
7
|
-
for (let j = i + 1; j < list.length; j++) {
|
|
8
|
-
if (list[i] === list[j]) {
|
|
9
|
-
duplicates.push(list[i]);
|
|
10
|
-
}
|
|
11
|
-
}
|
|
12
|
-
}
|
|
13
|
-
return duplicates;
|
|
14
|
-
}
|
package/tests/setup.sh
DELETED
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
set -e
|
|
3
|
-
|
|
4
|
-
# Move to the project root
|
|
5
|
-
cd "$(dirname "$0")/.."
|
|
6
|
-
|
|
7
|
-
echo "🚀 Setting up test environment for pi-audit-master..."
|
|
8
|
-
|
|
9
|
-
# 1. Install dependencies
|
|
10
|
-
echo "📦 Installing dependencies..."
|
|
11
|
-
npm install
|
|
12
|
-
|
|
13
|
-
# 2. Create buggy project structure
|
|
14
|
-
echo "📁 Creating buggy-project..."
|
|
15
|
-
mkdir -p tests/buggy-project/extensions
|
|
16
|
-
mkdir -p tests/buggy-project/src
|
|
17
|
-
|
|
18
|
-
# 3. Write buggy files
|
|
19
|
-
echo "📝 Writing buggy files..."
|
|
20
|
-
|
|
21
|
-
# Null Safety Bug
|
|
22
|
-
cat <<EOF >tests/buggy-project/src/null_safety.ts
|
|
23
|
-
export function processUser(user: any) {
|
|
24
|
-
// CRITICAL: Missing null check on user and user.profile
|
|
25
|
-
return user.profile.address.city.toUpperCase();
|
|
26
|
-
}
|
|
27
|
-
EOF
|
|
28
|
-
|
|
29
|
-
# Logic Bug
|
|
30
|
-
cat <<EOF >tests/buggy-project/src/logic_error.ts
|
|
31
|
-
export async function updateData(id: string, data: any) {
|
|
32
|
-
const current = await fetchById(id);
|
|
33
|
-
// HIGH: Race condition - not checking if data changed between fetch and update
|
|
34
|
-
const updated = { ...current, ...data };
|
|
35
|
-
await save(updated);
|
|
36
|
-
}
|
|
37
|
-
async function fetchById(id: string) { return { id }; }
|
|
38
|
-
async function save(d: any) { return true; }
|
|
39
|
-
EOF
|
|
40
|
-
|
|
41
|
-
# Performance Bug
|
|
42
|
-
cat <<EOF >tests/buggy-project/src/performance_leak.ts
|
|
43
|
-
export function findDuplicates(arr: string[]) {
|
|
44
|
-
const duplicates: string[] = [];
|
|
45
|
-
// MEDIUM: O(n^2) complexity
|
|
46
|
-
for (let i = 0; i < arr.length; i++) {
|
|
47
|
-
for (let j = i + 1; j < arr.length; j++) {
|
|
48
|
-
if (arr[i] === arr[j] && !duplicates.includes(arr[i])) {
|
|
49
|
-
duplicates.push(arr[i]);
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
return duplicates;
|
|
54
|
-
}
|
|
55
|
-
EOF
|
|
56
|
-
|
|
57
|
-
# Pi Integration Bug
|
|
58
|
-
cat <<EOF >tests/buggy-project/extensions/pi_wrong.ts
|
|
59
|
-
export default function (pi: any) {
|
|
60
|
-
// HIGH: Wrong event name 'tool_execution_started' instead of 'tool_execution_start'
|
|
61
|
-
pi.on('tool_execution_started', (event: any, ctx: any) => {
|
|
62
|
-
console.log('Intercepted!');
|
|
63
|
-
// Missing event.abort() for a blocking middleware
|
|
64
|
-
});
|
|
65
|
-
}
|
|
66
|
-
EOF
|
|
67
|
-
|
|
68
|
-
# Quality Bug
|
|
69
|
-
cat <<EOF >tests/buggy-project/src/messy_code.ts
|
|
70
|
-
export function calc(a: number, b: number) {
|
|
71
|
-
// LOW: Magic number 86400, redundant logic
|
|
72
|
-
const res = a * 86400;
|
|
73
|
-
const result = res;
|
|
74
|
-
if (result === res) {
|
|
75
|
-
return result;
|
|
76
|
-
}
|
|
77
|
-
return res;
|
|
78
|
-
}
|
|
79
|
-
EOF
|
|
80
|
-
|
|
81
|
-
echo "✅ Buggy project created."
|
|
82
|
-
|
|
83
|
-
# 4. Run tests
|
|
84
|
-
echo "🧪 Running tests..."
|
|
85
|
-
npm test
|
|
86
|
-
|
|
87
|
-
echo "✨ Setup and testing complete!"
|
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
import { AuditManager } from "../extensions/audit-manager";
|
|
2
|
-
import * as path from "path";
|
|
3
|
-
import type { ExtensionAPI } from "pi-coding-agent";
|
|
4
|
-
|
|
5
|
-
// Mocks
|
|
6
|
-
const mockPi = {
|
|
7
|
-
on: jest.fn(),
|
|
8
|
-
registerTool: jest.fn(),
|
|
9
|
-
subagents: {
|
|
10
|
-
parallel: jest.fn(),
|
|
11
|
-
},
|
|
12
|
-
} as unknown as ExtensionAPI;
|
|
13
|
-
|
|
14
|
-
const mockCtx = {
|
|
15
|
-
ui: {
|
|
16
|
-
notify: jest.fn(),
|
|
17
|
-
},
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
describe("AuditManager Verification", () => {
|
|
21
|
-
let manager: AuditManager;
|
|
22
|
-
const projectPath = path.join(__dirname, "buggy-project");
|
|
23
|
-
|
|
24
|
-
beforeEach(() => {
|
|
25
|
-
manager = new AuditManager(mockPi);
|
|
26
|
-
jest.clearAllMocks();
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
it("should detect critical and high bugs in buggy-project", async () => {
|
|
30
|
-
const spy = jest
|
|
31
|
-
.spyOn(manager, "dispatchAuditAgents")
|
|
32
|
-
.mockResolvedValue([
|
|
33
|
-
`| CRITICAL | src/api.ts:10 | Null access on data.profile | Add null guard |`,
|
|
34
|
-
`| HIGH | src/auth.ts:12 | Login called before init | Add initialization check |`,
|
|
35
|
-
`| MEDIUM | src/utils.ts:8 | O(n^2) loop in findDuplicates | Use a Map for O(n) |`,
|
|
36
|
-
`| CRITICAL | extensions/my-ext.ts:7 | Missing event.abort() | Call event.abort() to block tool |`,
|
|
37
|
-
`| LOW | src/legacy.ts:5 | Magic number 5000 | Move to constant |`,
|
|
38
|
-
]);
|
|
39
|
-
|
|
40
|
-
const finalResult = await manager.runAudit({
|
|
41
|
-
path: projectPath,
|
|
42
|
-
depth: "deep",
|
|
43
|
-
format: "file",
|
|
44
|
-
fix: false,
|
|
45
|
-
ctx: mockCtx as any,
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
expect(finalResult.report).toContain("CRITICAL");
|
|
49
|
-
expect(finalResult.report).toContain("HIGH");
|
|
50
|
-
expect(finalResult.report).toContain("MEDIUM");
|
|
51
|
-
expect(finalResult.report).toContain("src/api.ts");
|
|
52
|
-
expect(finalResult.report).toContain("extensions/my-ext.ts");
|
|
53
|
-
|
|
54
|
-
spy.mockRestore();
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
it("should resolve critical issues when fix is enabled", async () => {
|
|
58
|
-
const spy = jest
|
|
59
|
-
.spyOn(manager, "dispatchAuditAgents")
|
|
60
|
-
.mockResolvedValue([
|
|
61
|
-
`| CRITICAL | src/api.ts:10 | Null access | Add guard |`,
|
|
62
|
-
]);
|
|
63
|
-
|
|
64
|
-
const result = await manager.runAudit({
|
|
65
|
-
path: projectPath,
|
|
66
|
-
depth: "deep",
|
|
67
|
-
format: "chat",
|
|
68
|
-
fix: true,
|
|
69
|
-
ctx: mockCtx as any,
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
expect(result.fixes).toBeDefined();
|
|
73
|
-
expect(result.fixes[0].status).toBe("RESOLVED");
|
|
74
|
-
|
|
75
|
-
spy.mockRestore();
|
|
76
|
-
});
|
|
77
|
-
});
|
package/tsconfig.json
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"target": "ES2022",
|
|
4
|
-
"module": "NodeNext",
|
|
5
|
-
"moduleResolution": "NodeNext",
|
|
6
|
-
"outDir": "./dist",
|
|
7
|
-
"rootDir": ".",
|
|
8
|
-
"strict": true,
|
|
9
|
-
"esModuleInterop": true,
|
|
10
|
-
"skipLibCheck": true,
|
|
11
|
-
"forceConsistentCasingInFileNames": true,
|
|
12
|
-
"declaration": true
|
|
13
|
-
},
|
|
14
|
-
"include": ["extensions/**/*", "types/**/*"],
|
|
15
|
-
"exclude": ["node_modules", "dist"]
|
|
16
|
-
}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
declare module 'pi-coding-agent' {
|
|
2
|
-
export interface ExtensionAPI {
|
|
3
|
-
on(event: string, handler: Function): void;
|
|
4
|
-
registerTool(options: any): void;
|
|
5
|
-
subagents: any;
|
|
6
|
-
}
|
|
7
|
-
export interface ExtensionCommandContext {
|
|
8
|
-
ui: {
|
|
9
|
-
notify(message: string, level: string): void;
|
|
10
|
-
};
|
|
11
|
-
askUserQuestion(question: any): Promise<any>;
|
|
12
|
-
}
|
|
13
|
-
}
|
package/verify.ts
DELETED
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import { AuditManager } from "./extensions/audit-manager";
|
|
2
|
-
import * as path from "path";
|
|
3
|
-
|
|
4
|
-
async function verify() {
|
|
5
|
-
console.log("🚀 Starting pi-audit-master verification...");
|
|
6
|
-
|
|
7
|
-
const mockPi = { on: {}, registerTool: {} } as any;
|
|
8
|
-
const mockCtx = { ui: { notify: () => {} } } as any;
|
|
9
|
-
const manager = new AuditManager(mockPi);
|
|
10
|
-
const projectPath = path.join(__dirname, "tests/buggy-project");
|
|
11
|
-
|
|
12
|
-
// Mock the agent dispatch to simulate findings
|
|
13
|
-
const spy = ((manager as any).dispatchAuditAgents = async () => [
|
|
14
|
-
`| CRITICAL | src/api.ts:10 | Null access | Add guard |`,
|
|
15
|
-
`| HIGH | src/auth.ts:12 | Logic flow | Add check |`,
|
|
16
|
-
`| MEDIUM | src/utils.ts:8 | O(n^2) | Use Map |`,
|
|
17
|
-
`| CRITICAL | extensions/my-ext.ts:7 | No abort | Call abort |`,
|
|
18
|
-
]);
|
|
19
|
-
|
|
20
|
-
try {
|
|
21
|
-
const result = await manager.runAudit({
|
|
22
|
-
path: projectPath,
|
|
23
|
-
depth: "deep",
|
|
24
|
-
format: "file",
|
|
25
|
-
fix: false,
|
|
26
|
-
ctx: mockCtx,
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
console.log("✅ Audit result received:");
|
|
30
|
-
console.log(result.report);
|
|
31
|
-
|
|
32
|
-
if (result.report.includes("CRITICAL") && result.report.includes("HIGH")) {
|
|
33
|
-
console.log("🎯 SUCCESS: Critical and High bugs detected!");
|
|
34
|
-
} else {
|
|
35
|
-
console.error("❌ FAILURE: Bugs not detected in report.");
|
|
36
|
-
process.exit(1);
|
|
37
|
-
}
|
|
38
|
-
} catch (e: any) {
|
|
39
|
-
console.error("❌ Error during verification:", e);
|
|
40
|
-
process.exit(1);
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
verify();
|