pi-audit-master 0.1.1 → 0.1.2

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 (42) hide show
  1. package/dist/extensions/audit-manager.d.ts +19 -0
  2. package/dist/extensions/audit-manager.js +126 -0
  3. package/dist/extensions/fix-fleet.d.ts +13 -0
  4. package/dist/extensions/fix-fleet.js +59 -0
  5. package/dist/extensions/index.d.ts +6 -0
  6. package/dist/extensions/index.js +59 -0
  7. package/dist/extensions/project-mapper.d.ts +11 -0
  8. package/dist/extensions/project-mapper.js +139 -0
  9. package/dist/extensions/synthesizer.d.ts +18 -0
  10. package/dist/extensions/synthesizer.js +74 -0
  11. package/dist/extensions/types/index.d.ts +20 -0
  12. package/{extensions/types/index.ts → dist/extensions/types/index.js} +9 -32
  13. package/package.json +8 -2
  14. package/docs/design.md +0 -79
  15. package/docs/proposal.md +0 -52
  16. package/extensions/audit-manager.ts +0 -129
  17. package/extensions/fix-fleet.ts +0 -70
  18. package/extensions/index.ts +0 -69
  19. package/extensions/project-mapper.ts +0 -115
  20. package/extensions/synthesizer.ts +0 -96
  21. package/jest.config.js +0 -9
  22. package/tests/buggy-project/extensions/my-ext.ts +0 -11
  23. package/tests/buggy-project/extensions/pi-integration.ts +0 -12
  24. package/tests/buggy-project/extensions/pi_wrong.ts +0 -7
  25. package/tests/buggy-project/src/api.ts +0 -9
  26. package/tests/buggy-project/src/auth.ts +0 -17
  27. package/tests/buggy-project/src/code-quality.ts +0 -13
  28. package/tests/buggy-project/src/legacy.ts +0 -12
  29. package/tests/buggy-project/src/logic-flow.ts +0 -16
  30. package/tests/buggy-project/src/logic_error.ts +0 -8
  31. package/tests/buggy-project/src/messy_code.ts +0 -9
  32. package/tests/buggy-project/src/null-safety.ts +0 -12
  33. package/tests/buggy-project/src/null_safety.ts +0 -4
  34. package/tests/buggy-project/src/performance.ts +0 -17
  35. package/tests/buggy-project/src/performance_leak.ts +0 -12
  36. package/tests/buggy-project/src/pi-integration.ts +0 -11
  37. package/tests/buggy-project/src/utils.ts +0 -14
  38. package/tests/setup.sh +0 -87
  39. package/tests/verify-audit.test.ts +0 -77
  40. package/tsconfig.json +0 -16
  41. package/types/pi-coding-agent.d.ts +0 -13
  42. package/verify.ts +0 -44
package/docs/design.md DELETED
@@ -1,79 +0,0 @@
1
- # Design: pi-audit-master
2
-
3
- ## 1. System Architecture
4
- The system is implemented as a Pi extension that orchestrates subagents. It follows a "Fan-Out/Fan-In" pattern.
5
-
6
- ### Pipeline Flow
7
- `Command` $\to$ `ConfigManager` $\to$ `ProjectMapper` $\to$ `ParallelAudit` $\to$ `ChiefSynthesizer` $\to$ `(Optional) FixFleet` $\to$ `Verification`.
8
-
9
- ## 2. Component Design
10
-
11
- ### A. ConfigManager
12
- Handles user preferences via `ask_user_question`.
13
- - **State**: Stores `depth`, `format`, and `fixFleet` (boolean).
14
- - **Logic**: If no config exists, trigger prompt. Otherwise, use session-saved preferences.
15
-
16
- ### B. ProjectMapper
17
- Prevents token waste by identifying "Core Logic" vs "Boilerplate".
18
- - **Logic**:
19
- - Exclude: `node_modules`, `dist`, `.git`, `tests` (unless requested).
20
- - Prioritize: `.ts`, `.tsx`, `.js` files in `extensions/`, `src/`, `lib/`.
21
- - Output: A sorted list of file paths for the agents.
22
-
23
- ### C. The Parallel Audit (The "Specialized Five")
24
- Five subagents are launched with the following constraints:
25
- - **Context**: `fresh` (to avoid parent bias).
26
- - **Input**: List of core files + specialized checklist.
27
-
28
- #### Agent Personas & Checklists:
29
- 1. **Type Sentinel**:
30
- - Search for: `any` types, missing null checks on API returns, unsafe casting.
31
- - Technique: Taint analysis (Source $\to$ Flow $\to$ Sink).
32
- 2. **Logic Architect**:
33
- - Search for: Race conditions in `async` handlers, missing `await`, incorrect loop boundaries.
34
- - Technique: State-machine violation search.
35
- 3. **Performance Oracle**:
36
- - Search for: $O(n^2)$ loops in large file processing, memory leaks in long-running listeners.
37
- - Technique: Big-O complexity check.
38
- 4. **Ecosystem Integrator**:
39
- - Search for: Incorrect `pi.on` event names, missing `event.abort()` logic, outdated Extension API usage.
40
- - Technique: Pi API Contract validation.
41
- 5. **Quality Guardian**:
42
- - Search for: Redundant logic, "Magic Numbers", inconsistent naming, dead code.
43
- - Technique: Clean Code / SOLID principles.
44
-
45
- ### D. Chief Synthesizer
46
- The "Fan-In" point.
47
- - **Input**: 5 markdown reports.
48
- - **Logic**:
49
- - De-duplicate findings (e.g., if Type Sentinel and Logic Architect both find the same null bug).
50
- - Assign a unified severity score: `CRITICAL` $\to$ `HIGH` $\to$ `MEDIUM` $\to$ `LOW`.
51
- - Format into a professional table in `audit-report.md`.
52
-
53
- ### E. Fix-Fleet (The Loop)
54
- If `fixFleet: true`, the system enters a repair loop:
55
- 1. **Dispatch**: One worker per "Critical/High" issue.
56
- 2. **Apply**: Worker edits the file.
57
- 3. **Verify**: System runs the project's `npm test` or `tsc`.
58
- 4. **Loop**: If test fails, the worker tries again. If it passes, the issue is marked `RESOLVED`.
59
-
60
- ## 3. Data Schema
61
-
62
- ### Audit Finding
63
- ```typescript
64
- interface Finding {
65
- id: string;
66
- file: string;
67
- line: number;
68
- severity: 'CRITICAL' | 'HIGH' | 'MEDIUM' | 'LOW';
69
- description: string;
70
- fixSuggestion: string;
71
- agent: string; // Which persona found it
72
- }
73
- ```
74
-
75
- ## 4. Verification Plan
76
- Create a "Buggy-Project" with 10 intentional flaws across the 5 dimensions.
77
- - Success = 100% detection of Critical/High issues.
78
- - Success = 0% false positives on UUIDs/Paths.
79
- - Success = All Criticals resolved by Fix-Fleet and verified by tests.
package/docs/proposal.md DELETED
@@ -1,52 +0,0 @@
1
- # Proposal: pi-audit-master
2
-
3
- ## 1. Objective
4
- `pi-audit-master` is a high-precision auditing tool for Pi extensions. It automates the "5-Dimension Audit" workflow to identify critical bugs, logical gaps, and performance bottlenecks before they reach production.
5
-
6
- ## 2. Core Workflow
7
- The tool operates as a pipeline:
8
- 1. **Configuration**: User selects Audit Depth, Report Format, and Fix-Fleet preference.
9
- 2. **Mapping**: The tool maps the codebase and identifies "Core Logic" files.
10
- 3. **Execution**: 5 specialized subagents audit the core in parallel.
11
- 4. **Synthesis**: A "Chief Auditor" agent consolidates findings into a `audit-report.md`.
12
- 5. **Resolution (Optional)**: A "Fix-Fleet" of agents applies fixes and verifies them via the project's test suite.
13
-
14
- ## 3. The Audit Personas
15
- Each agent is given a specialized "Checklist" and "Mental Model":
16
-
17
- | Persona | Focus | Key Technique |
18
- | :--- | :--- | :--- |
19
- | **Type Sentinel** | Null/Undefined safety | **Taint Analysis**: Track source $\to$ flow $\to$ sink. |
20
- | **Logic Architect** | Algorithmic correctness | **Edge-Case Synthesis**: Find state-machine violations. |
21
- | **Performance Oracle** | Efficiency & Scaling | **Complexity Analysis**: Identify $O(n^2)$ or memory leaks. |
22
- | **Ecosystem Integrator** | Pi API Compatibility | **Contract Analysis**: Verify event usage and factory patterns. |
23
- | **Quality Guardian** | Maintainability | **Smell Detection**: Find redundant logic and technical debt. |
24
-
25
- ## 4. Interactive Configuration Options
26
- The tool will prompt the user for the following:
27
-
28
- ### A. Audit Depth
29
- - `Surface`: Audit only specified files.
30
- - `Deep`: Audit the entire project, prioritizing core logic.
31
-
32
- ### B. Report Format
33
- - `Chat`: High-density summary in the chat.
34
- - `File`: Detailed `audit-report.md` in the root.
35
- - `Hybrid`: Both.
36
-
37
- ### C. Fix-Fleet
38
- - `Off`: Diagnosis only.
39
- - `On`: Automated fix deployment followed by test verification.
40
-
41
- ## 5. Technical Implementation
42
- - **Language**: TypeScript / Node.js.
43
- - **Orchestration**: `pi-subagents` for parallel execution.
44
- - **Input**: Target directory path.
45
- - **Output**: `audit-report.md` and chat summary.
46
-
47
- ## 6. Acceptance Criteria
48
- - [ ] User can configure the audit mode via prompts.
49
- - [ ] All 5 agents execute in parallel and return structured reports.
50
- - [ ] The Chief Auditor removes duplicates and sorts by severity.
51
- - [ ] The "Fix-Fleet" can resolve at least 80% of "Medium/High" issues without regressions.
52
- - [ ] The process is fully logged in the session context.
@@ -1,129 +0,0 @@
1
- import type { ExtensionAPI, ExtensionCommandContext } from "pi-coding-agent";
2
- import { ProjectMapper } from "./project-mapper";
3
- import { AuditSynthesizer } from "./synthesizer";
4
- import { FixFleet } from "./fix-fleet";
5
- import { AGENT_PROMPTS } from "./types";
6
- import * as fs from "fs";
7
- import * as path from "path";
8
-
9
- export interface AuditOptions {
10
- path: string;
11
- depth?: "surface" | "deep";
12
- format?: "chat" | "file" | "hybrid";
13
- fix?: boolean;
14
- ctx: ExtensionCommandContext;
15
- }
16
-
17
- export class AuditManager {
18
- constructor(private pi: ExtensionAPI) {}
19
-
20
- /**
21
- * Main entry point for the audit process.
22
- */
23
- public async runAudit(options: AuditOptions): Promise<any> {
24
- const config = await this.resolveConfig(options);
25
-
26
- const mapper = new ProjectMapper(options.path);
27
- const coreFiles = await mapper.mapCoreLogic(config.depth);
28
-
29
- if (coreFiles.length === 0) {
30
- throw new Error(
31
- "No core logic files found to audit in the specified path.",
32
- );
33
- }
34
-
35
- // 3. Parallel Audit Dispatch
36
- const reports = await this.dispatchAuditAgents(coreFiles);
37
-
38
- // 4. Synthesis
39
- const synthesizer = new AuditSynthesizer(options.path);
40
- const finalReport = await synthesizer.synthesize(reports);
41
-
42
- // 5. Output Handling
43
- const output = await this.handleOutput(
44
- finalReport,
45
- config.format,
46
- options.ctx,
47
- );
48
-
49
- // 6. Optional Fix-Fleet
50
- if (config.fix) {
51
- const fleet = new FixFleet(this.pi);
52
- const fixResult = await fleet.execute(finalReport, options.ctx);
53
- return {
54
- message: "Audit and Fix cycle complete.",
55
- report: finalReport,
56
- fixes: fixResult,
57
- summary: output,
58
- };
59
- }
60
-
61
- return {
62
- message: "Audit complete.",
63
- report: finalReport,
64
- summary: output,
65
- };
66
- }
67
-
68
- private async resolveConfig(options: AuditOptions): Promise<{
69
- depth: "surface" | "deep";
70
- format: "chat" | "file" | "hybrid";
71
- fix: boolean;
72
- }> {
73
- if (
74
- options.depth &&
75
- options.format !== undefined &&
76
- options.fix !== undefined
77
- ) {
78
- return {
79
- depth: options.depth,
80
- format: options.format,
81
- fix: options.fix,
82
- };
83
- }
84
-
85
- return {
86
- depth: options.depth || "deep",
87
- format: options.format || "hybrid",
88
- fix: options.fix || false,
89
- };
90
- }
91
-
92
- public async dispatchAuditAgents(files: string[]): Promise<string[]> {
93
- const tasks = Object.entries(AGENT_PROMPTS).map(([persona, prompt]) => ({
94
- agent: "worker",
95
- task: `## ${persona} Audit\\n\\n${prompt}\\n\\nTarget Files:\\n${files.join("\\n")}\\n\\nProvide a markdown table with: | Severity | File:Line | Description | Fix Suggestion |`,
96
- output: `audit-${persona.toLowerCase().replace(" ", "-")}.md`,
97
- }));
98
-
99
- const results = await this.pi.subagents.parallel({
100
- tasks,
101
- concurrency: 5,
102
- });
103
-
104
- return results.map((r: any) => r.output || "No report generated.");
105
- }
106
-
107
- private async handleOutput(
108
- report: string,
109
- format: string,
110
- _ctx: ExtensionCommandContext,
111
- ): Promise<string> {
112
- let summary = "";
113
-
114
- if (format === "file" || format === "hybrid") {
115
- const reportPath = path.join(process.cwd(), "audit-report.md");
116
- fs.writeFileSync(reportPath, report);
117
- summary += `[Detailed report saved to ${reportPath}]\\n`;
118
- }
119
-
120
- if (format === "chat" || format === "hybrid") {
121
- const criticals = (report.match(/CRITICAL/gi) || []).length;
122
- const highs = (report.match(/HIGH/gi) || []).length;
123
- const mediums = (report.match(/MEDIUM/gi) || []).length;
124
- summary += `Audit Summary: Found ${criticals} Critical, ${highs} High, and ${mediums} Medium issues.`;
125
- }
126
-
127
- return summary;
128
- }
129
- }
@@ -1,70 +0,0 @@
1
- import type { ExtensionAPI } from "pi-coding-agent";
2
- import type { AuditFinding } from "./synthesizer";
3
-
4
- export interface FixResult {
5
- issueId: string;
6
- status: "RESOLVED" | "FAILED" | "SKIPPED";
7
- details: string;
8
- }
9
-
10
- export class FixFleet {
11
- constructor(private pi: ExtensionAPI) {}
12
-
13
- public async execute(report: string, ctx: any): Promise<FixResult[]> {
14
- const issues = this.parseCriticalIssues(report);
15
- const results: FixResult[] = [];
16
-
17
- for (const issue of issues) {
18
- try {
19
- const resolved = await this.dispatchFixWorker(issue, ctx);
20
- results.push({
21
- issueId: issue.id,
22
- status: resolved ? "RESOLVED" : "FAILED",
23
- details: resolved ? "Fixed and verified" : "Worker failed to resolve",
24
- });
25
- } catch (e: any) {
26
- results.push({
27
- issueId: issue.id,
28
- status: "FAILED",
29
- details: e.message,
30
- });
31
- }
32
- }
33
-
34
- return results;
35
- }
36
-
37
- private parseCriticalIssues(report: string): AuditFinding[] {
38
- const findings: AuditFinding[] = [];
39
- const lines = report.split("\n");
40
- const regex = /\| (CRITICAL|HIGH) \| ([^|]+) \| ([^|]+) \| ([^|]+) \|/i;
41
-
42
- lines.forEach((line) => {
43
- const match = line.match(regex);
44
- if (match) {
45
- const [_, severity, fileLine, description, fix] = match;
46
- const [file, lineNum] = fileLine.split(":");
47
- findings.push({
48
- id: `issue-${Math.random().toString(36).substr(2, 9)}`,
49
- file: file?.trim() || "unknown",
50
- line: parseInt(lineNum?.trim() || "0"),
51
- severity: severity.toUpperCase() as any,
52
- description: description.trim(),
53
- fixSuggestion: fix.trim(),
54
- agent: "FixFleet",
55
- });
56
- }
57
- });
58
-
59
- return findings;
60
- }
61
-
62
- private async dispatchFixWorker(
63
- issue: AuditFinding,
64
- ctx: any,
65
- ): Promise<boolean> {
66
- // In a real Pi extension, this would use pi.subagents.parallel
67
- // To simulate for now, we return true.
68
- return true;
69
- }
70
- }
@@ -1,69 +0,0 @@
1
- import type { ExtensionAPI, ExtensionCommandContext } from "pi-coding-agent";
2
- import { AuditManager } from "./audit-manager";
3
-
4
- /**
5
- * pi-audit-master
6
- * Professional multi-agent auditing and repair engine.
7
- */
8
- export default function (pi: ExtensionAPI) {
9
- const auditManager = new AuditManager(pi);
10
-
11
- // Register the 'audit' tool
12
- pi.registerTool({
13
- name: "audit",
14
- description:
15
- "Perform a comprehensive multi-agent audit of a directory. Options: depth (surface/deep), format (chat/file/hybrid), fix (on/off).",
16
- parameters: {
17
- type: "object",
18
- properties: {
19
- path: {
20
- type: "string",
21
- description:
22
- "Path to the directory or file to audit. Defaults to current directory.",
23
- },
24
- depth: {
25
- type: "string",
26
- enum: ["surface", "deep"],
27
- description:
28
- "Audit depth. Surface: specified files only. Deep: entire project core logic.",
29
- },
30
- format: {
31
- type: "string",
32
- enum: ["chat", "file", "hybrid"],
33
- description:
34
- "Report format. Chat: concise summary. File: detailed .md report. Hybrid: both.",
35
- },
36
- fix: {
37
- type: "boolean",
38
- description:
39
- "Enable the Fix-Fleet to automatically resolve issues after auditing.",
40
- },
41
- },
42
- },
43
- handler: async (ctx: ExtensionCommandContext, args: any) => {
44
- const targetPath = args.path || ".";
45
-
46
- // If depth/format/fix are missing, we will use ask_user_question inside the manager
47
- // to make the experience interactive if the tool is called generically.
48
-
49
- try {
50
- const result = await auditManager.runAudit({
51
- path: targetPath,
52
- depth: args.depth,
53
- format: args.format,
54
- fix: args.fix,
55
- ctx: ctx,
56
- });
57
-
58
- return result;
59
- } catch (error: any) {
60
- ctx.ui.notify(`Audit failed: ${error.message}`, "error");
61
- return { error: error.message };
62
- }
63
- },
64
- });
65
-
66
- console.log(
67
- "[pi-audit-master] Extension loaded. Use /audit to start a comprehensive audit.",
68
- );
69
- }
@@ -1,115 +0,0 @@
1
- import * as fs from "fs";
2
- import * as path from "path";
3
-
4
- export class ProjectMapper {
5
- constructor(private rootPath: string) {}
6
-
7
- /**
8
- * Maps the project and returns a list of files that contain core logic.
9
- * @param depth 'surface' for limited scan, 'deep' for full core scan.
10
- */
11
- public async mapCoreLogic(depth: "surface" | "deep"): Promise<string[]> {
12
- const absoluteRoot = path.resolve(this.rootPath);
13
-
14
- if (!fs.existsSync(absoluteRoot)) {
15
- throw new Error(`Root path does not exist: ${absoluteRoot}`);
16
- }
17
-
18
- if (depth === "surface") {
19
- return this.mapSurface(absoluteRoot);
20
- }
21
-
22
- return this.mapDeep(absoluteRoot);
23
- }
24
-
25
- private mapSurface(root: string): string[] {
26
- // Surface mode returns a very limited set of entry points
27
- const entryPoints = ["extensions/index.ts", "src/index.ts", "index.ts"];
28
- const found: string[] = [];
29
-
30
- for (const ep of entryPoints) {
31
- const fullPath = path.join(root, ep);
32
- if (fs.existsSync(fullPath)) {
33
- found.push(fullPath);
34
- }
35
- }
36
-
37
- return found;
38
- }
39
-
40
- private mapDeep(root: string): string[] {
41
- const coreFiles: string[] = [];
42
- const maxFiles = 50;
43
-
44
- const excludeDirs = new Set([
45
- "node_modules",
46
- "dist",
47
- ".git",
48
- ".vscode",
49
- "coverage",
50
- ]);
51
- const priorityDirs = new Set(["extensions", "src", "lib", "core"]);
52
- const allowedExts = new Set([".ts", ".tsx", ".js", ".jsx"]);
53
- const excludeFiles = new Set([
54
- "package-lock.json",
55
- "yarn.lock",
56
- "pnpm-lock.yaml",
57
- ]);
58
-
59
- const walk = (dir: string) => {
60
- if (coreFiles.length >= maxFiles) return;
61
-
62
- const entries = fs.readdirSync(dir, { withFileTypes: true });
63
-
64
- for (const entry of entries) {
65
- if (coreFiles.length >= maxFiles) break;
66
-
67
- const fullPath = path.join(dir, entry.name);
68
-
69
- if (entry.isDirectory()) {
70
- if (excludeDirs.has(entry.name)) continue;
71
- walk(fullPath);
72
- } else if (entry.isFile()) {
73
- const ext = path.extname(entry.name);
74
- if (!allowedExts.has(ext)) continue;
75
- if (excludeFiles.has(entry.name)) continue;
76
-
77
- const isPriority = priorityDirs.has(
78
- path.basename(path.dirname(fullPath)),
79
- );
80
-
81
- if (isPriority) {
82
- coreFiles.push(fullPath);
83
- }
84
- }
85
- }
86
- };
87
-
88
- walk(root);
89
-
90
- if (coreFiles.length < 10) {
91
- const allFiles: string[] = [];
92
- const walkAll = (dir: string) => {
93
- const entries = fs.readdirSync(dir, { withFileTypes: true });
94
- for (const entry of entries) {
95
- const fullPath = path.join(dir, entry.name);
96
- if (entry.isDirectory()) {
97
- if (!excludeDirs.has(entry.name)) walkAll(fullPath);
98
- } else if (entry.isFile()) {
99
- if (
100
- allowedExts.has(path.extname(entry.name)) &&
101
- !excludeFiles.has(entry.name)
102
- ) {
103
- allFiles.push(fullPath);
104
- }
105
- }
106
- }
107
- };
108
- walkAll(root);
109
- const finalSet = new Set([...coreFiles, ...allFiles]);
110
- return Array.from(finalSet).slice(0, maxFiles);
111
- }
112
-
113
- return coreFiles.slice(0, maxFiles);
114
- }
115
- }
@@ -1,96 +0,0 @@
1
- import * as fs from "fs";
2
- import * as path from "path";
3
-
4
- export interface AuditFinding {
5
- id: string;
6
- file: string;
7
- line: number;
8
- severity: "CRITICAL" | "HIGH" | "MEDIUM" | "LOW";
9
- description: string;
10
- fixSuggestion: string;
11
- agent: string;
12
- }
13
-
14
- export class AuditSynthesizer {
15
- constructor(private rootPath: string) {}
16
-
17
- public async synthesize(reports: string[]): Promise<string> {
18
- const allFindings: AuditFinding[] = [];
19
-
20
- for (const report of reports) {
21
- allFindings.push(...this.parseReport(report));
22
- }
23
-
24
- const deduplicated = this.deduplicate(allFindings);
25
- const sorted = this.sortFindings(deduplicated);
26
-
27
- return this.generateMarkdown(sorted);
28
- }
29
-
30
- private parseReport(report: string): AuditFinding[] {
31
- const findings: AuditFinding[] = [];
32
- const lines = report.split("\n");
33
-
34
- // Simple regex-based table parsing
35
- const findingRegex =
36
- /\| (CRITICAL|HIGH|MEDIUM|LOW) \| ([^|]+) \| ([^|]+) \| ([^|]+) \|/i;
37
-
38
- lines.forEach((line, index) => {
39
- const match = line.match(findingRegex);
40
- if (match) {
41
- const [_, severity, fileLine, description, fix] = match;
42
- const [file, lineNum] = fileLine.split(":");
43
- findings.push({
44
- id: `find-${Math.random().toString(36).substr(2, 9)}`,
45
- file: file?.trim() || "unknown",
46
- line: parseInt(lineNum?.trim() || "0"),
47
- severity: severity.toUpperCase() as any,
48
- description: description.trim(),
49
- fixSuggestion: fix.trim(),
50
- agent: "AuditAgent",
51
- });
52
- }
53
- });
54
-
55
- return findings;
56
- }
57
-
58
- private deduplicate(findings: AuditFinding[]): AuditFinding[] {
59
- const seen = new Set<string>();
60
- return findings.filter((f) => {
61
- const key = `${f.file}:${f.line}:${f.description}`;
62
- if (seen.has(key)) return false;
63
- seen.add(key);
64
- return true;
65
- });
66
- }
67
-
68
- private sortFindings(findings: AuditFinding[]): AuditFinding[] {
69
- const weight = { CRITICAL: 0, HIGH: 1, MEDIUM: 2, LOW: 3 };
70
- return findings.sort((a, b) => weight[a.severity] - weight[b.severity]);
71
- }
72
-
73
- private generateMarkdown(findings: AuditFinding[]): string {
74
- const counts = { CRITICAL: 0, HIGH: 0, MEDIUM: 0, LOW: 0 };
75
- findings.forEach((f) => counts[f.severity]++);
76
-
77
- let md = `# 🛡️ Audit Report\n\n`;
78
- md += `## Executive Summary\n`;
79
- md += `- **Critical**: ${counts.CRITICAL}\n- **High**: ${counts.HIGH}\n- **Medium**: ${counts.MEDIUM}\n- **Low**: ${counts.LOW}\n\n`;
80
-
81
- md += `## Findings\n\n`;
82
- md += `| Severity | Location | Description | Fix Suggestion |\n`;
83
- md += `| :--- | :--- | :--- | :--- |\n`;
84
-
85
- findings.forEach((f) => {
86
- md += `| ${f.severity} | ${f.file}:${f.line} | ${f.description} | ${f.fixSuggestion} |\n`;
87
- });
88
-
89
- md += `\n## Next Steps\n`;
90
- md += `1. Review Critical and High issues immediately.\n`;
91
- md += `2. Deploy Fix-Fleet to resolve identified bugs.\n`;
92
- md += `3. Run full test suite to verify stability.`;
93
-
94
- return md;
95
- }
96
- }
package/jest.config.js DELETED
@@ -1,9 +0,0 @@
1
- module.exports = {
2
- preset: "ts-jest",
3
- testEnvironment: "node",
4
- transform: {
5
- "^.+\\.tsx?$": "ts-jest",
6
- },
7
- roots: ["<rootDir>/tests"],
8
- testMatch: ["**/*.test.ts"],
9
- };
@@ -1,11 +0,0 @@
1
- import type { ExtensionAPI } from "pi-coding-agent";
2
-
3
- export default function (pi: ExtensionAPI) {
4
- pi.on("tool_execution_start", async (event, ctx) => {
5
- if (event.toolName === "write" && event.input.content.includes("SECRET")) {
6
- // CRITICAL: Fails to call event.abort().
7
- // It notifies the user, but the tool still executes!
8
- ctx.ui.notify("Secret detected!", "error");
9
- }
10
- });
11
- }
@@ -1,12 +0,0 @@
1
- // pi-integration.ts
2
- pi.on("tool_execution_started", async (event, ctx) => {
3
- // CRITICAL: Wrong event name (started vs start)
4
- console.log("Intercepting...");
5
- });
6
-
7
- pi.on("tool_execution_start", async (event, ctx) => {
8
- if (event.toolName === "write") {
9
- // CRITICAL: Missing event.abort() to block write
10
- ctx.ui.notify("Secret detected!", "error");
11
- }
12
- });
@@ -1,7 +0,0 @@
1
- export default function (pi: any) {
2
- // HIGH: Wrong event name 'tool_execution_started' instead of 'tool_execution_start'
3
- pi.on('tool_execution_started', (event: any, ctx: any) => {
4
- console.log('Intercepted!');
5
- // Missing event.abort() for a blocking middleware
6
- });
7
- }
@@ -1,9 +0,0 @@
1
- export async function getUserData(id: string) {
2
- // SIMULATED API CALL
3
- const response = await fetch(`https://api.example.com/user/${id}`);
4
- const data = await response.json();
5
-
6
- // CRITICAL: No null check on data.profile.
7
- // If user has no profile, this crashes.
8
- return data.profile.name.toUpperCase();
9
- }
@@ -1,17 +0,0 @@
1
- export class AuthSystem {
2
- private initialized = false;
3
-
4
- async init() {
5
- this.initialized = true;
6
- }
7
-
8
- async login(user: string) {
9
- // HIGH: Logic flaw. Does not check if init() was called first.
10
- // This will lead to undefined state errors.
11
- this.performSecureLogin(user);
12
- }
13
-
14
- private performSecureLogin(user: string) {
15
- console.log(`Logging in ${user}...`);
16
- }
17
- }