@aethrekh/pi-cs 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.
Files changed (42) hide show
  1. package/CHANGELOG.md +40 -0
  2. package/LICENSE +21 -0
  3. package/README.md +250 -0
  4. package/config/defaults.json +25 -0
  5. package/config/schema.json +134 -0
  6. package/extensions/folder-detector.d.ts +34 -0
  7. package/extensions/folder-detector.d.ts.map +1 -0
  8. package/extensions/folder-detector.js +197 -0
  9. package/extensions/folder-detector.js.map +1 -0
  10. package/extensions/index.d.ts +12 -0
  11. package/extensions/index.d.ts.map +1 -0
  12. package/extensions/index.js +227 -0
  13. package/extensions/index.js.map +1 -0
  14. package/extensions/integrity-guard.d.ts +25 -0
  15. package/extensions/integrity-guard.d.ts.map +1 -0
  16. package/extensions/integrity-guard.js +118 -0
  17. package/extensions/integrity-guard.js.map +1 -0
  18. package/extensions/progress-tracker.d.ts +33 -0
  19. package/extensions/progress-tracker.d.ts.map +1 -0
  20. package/extensions/progress-tracker.js +175 -0
  21. package/extensions/progress-tracker.js.map +1 -0
  22. package/extensions/semester-detector.d.ts +53 -0
  23. package/extensions/semester-detector.d.ts.map +1 -0
  24. package/extensions/semester-detector.js +197 -0
  25. package/extensions/semester-detector.js.map +1 -0
  26. package/index.d.ts +146 -0
  27. package/index.js +381 -0
  28. package/index.js.map +1 -0
  29. package/package.json +33 -0
  30. package/pi-cs.meta.json +7 -0
  31. package/pi-package.yaml +76 -0
  32. package/skills/exam/SKILL.md +186 -0
  33. package/skills/explain/SKILL.md +124 -0
  34. package/skills/homework/SKILL.md +89 -0
  35. package/skills/leetcode/SKILL.md +139 -0
  36. package/skills/project/SKILL.md +143 -0
  37. package/skills/research/SKILL.md +164 -0
  38. package/skills/review/SKILL.md +136 -0
  39. package/system.md +98 -0
  40. package/templates/project-init.md +141 -0
  41. package/templates/research-paper.md +134 -0
  42. package/templates/semester-init.md +49 -0
@@ -0,0 +1,197 @@
1
+ "use strict";
2
+ /**
3
+ * folder-detector.ts
4
+ *
5
+ * Extension: Folder Detector
6
+ * Triggers: on_startup, on_directory_change
7
+ *
8
+ * Detects standard CS university folder structures and injects
9
+ * project context into the Pi session accordingly.
10
+ */
11
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
12
+ if (k2 === undefined) k2 = k;
13
+ var desc = Object.getOwnPropertyDescriptor(m, k);
14
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
15
+ desc = { enumerable: true, get: function() { return m[k]; } };
16
+ }
17
+ Object.defineProperty(o, k2, desc);
18
+ }) : (function(o, m, k, k2) {
19
+ if (k2 === undefined) k2 = k;
20
+ o[k2] = m[k];
21
+ }));
22
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
23
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
24
+ }) : function(o, v) {
25
+ o["default"] = v;
26
+ });
27
+ var __importStar = (this && this.__importStar) || (function () {
28
+ var ownKeys = function(o) {
29
+ ownKeys = Object.getOwnPropertyNames || function (o) {
30
+ var ar = [];
31
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
32
+ return ar;
33
+ };
34
+ return ownKeys(o);
35
+ };
36
+ return function (mod) {
37
+ if (mod && mod.__esModule) return mod;
38
+ var result = {};
39
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
40
+ __setModuleDefault(result, mod);
41
+ return result;
42
+ };
43
+ })();
44
+ Object.defineProperty(exports, "__esModule", { value: true });
45
+ exports.detectFolderContext = detectFolderContext;
46
+ exports.summarizeFolderContext = summarizeFolderContext;
47
+ exports.run = run;
48
+ const fs = __importStar(require("fs"));
49
+ const path = __importStar(require("path"));
50
+ // ─── Marker Files ──────────────────────────────────────────────────────────
51
+ const PYTHON_MARKERS = ["requirements.txt", "pyproject.toml", "setup.py", "Pipfile"];
52
+ const TS_MARKERS = ["package.json", "tsconfig.json"];
53
+ const JAVA_MARKERS = ["pom.xml", "build.gradle", "*.java"];
54
+ const CPP_MARKERS = ["CMakeLists.txt", "Makefile", "*.cpp", "*.h"];
55
+ const RUST_MARKERS = ["Cargo.toml"];
56
+ const GO_MARKERS = ["go.mod"];
57
+ const WEB_MARKERS = ["index.html", "vite.config.*", "next.config.*", "webpack.config.*"];
58
+ // ─── University Structure Patterns ─────────────────────────────────────────
59
+ // Matches patterns like: FALL2025, SPRING24, SEM1, SEMESTER2, etc.
60
+ const SEMESTER_PATTERN = /^(fall|spring|summer|winter|sem|semester)\d{0,4}$/i;
61
+ // Matches patterns like: CS301, ECE202, COS226, etc.
62
+ const COURSE_PATTERN = /^[A-Z]{2,4}\d{2,4}$/;
63
+ // ─── Helpers ───────────────────────────────────────────────────────────────
64
+ function listDir(dir) {
65
+ try {
66
+ return fs.readdirSync(dir);
67
+ }
68
+ catch {
69
+ return [];
70
+ }
71
+ }
72
+ function detectProjectType(dir) {
73
+ const files = listDir(dir);
74
+ const fileSet = new Set(files);
75
+ if (RUST_MARKERS.some((m) => fileSet.has(m)))
76
+ return "rust";
77
+ if (GO_MARKERS.some((m) => fileSet.has(m)))
78
+ return "go";
79
+ if (PYTHON_MARKERS.some((m) => fileSet.has(m)))
80
+ return "python";
81
+ if (JAVA_MARKERS.some((m) => fileSet.has(m)))
82
+ return "java";
83
+ if (CPP_MARKERS.some((m) => fileSet.has(m)))
84
+ return "cpp";
85
+ if (WEB_MARKERS.some((m) => fileSet.has(m)))
86
+ return "web";
87
+ if (TS_MARKERS.some((m) => fileSet.has(m)))
88
+ return "typescript";
89
+ return "unknown";
90
+ }
91
+ function buildProjectContext(dir) {
92
+ const type = detectProjectType(dir);
93
+ const files = listDir(dir);
94
+ const fileSet = new Set(files);
95
+ const ctx = {
96
+ type,
97
+ root: dir,
98
+ name: path.basename(dir),
99
+ hasTests: fileSet.has("tests") || fileSet.has("test") || fileSet.has("__tests__"),
100
+ hasCi: fileSet.has(".github"),
101
+ hasDocker: fileSet.has("Dockerfile") || fileSet.has("docker-compose.yml"),
102
+ hasReadme: fileSet.has("README.md") || fileSet.has("readme.md"),
103
+ };
104
+ // Set type-specific commands
105
+ switch (type) {
106
+ case "python":
107
+ ctx.entrypoint = fileSet.has("main.py") ? "main.py" : "src/main.py";
108
+ ctx.testCommand = "pytest";
109
+ ctx.buildCommand = "pip install -r requirements.txt";
110
+ break;
111
+ case "typescript":
112
+ ctx.entrypoint = "src/index.ts";
113
+ ctx.testCommand = "npm test";
114
+ ctx.buildCommand = "npm run build";
115
+ break;
116
+ case "java":
117
+ ctx.testCommand = fileSet.has("pom.xml") ? "mvn test" : "gradle test";
118
+ ctx.buildCommand = fileSet.has("pom.xml") ? "mvn package" : "gradle build";
119
+ break;
120
+ case "cpp":
121
+ ctx.testCommand = "make test";
122
+ ctx.buildCommand = "make";
123
+ break;
124
+ case "rust":
125
+ ctx.testCommand = "cargo test";
126
+ ctx.buildCommand = "cargo build";
127
+ break;
128
+ case "go":
129
+ ctx.testCommand = "go test ./...";
130
+ ctx.buildCommand = "go build ./...";
131
+ break;
132
+ }
133
+ return ctx;
134
+ }
135
+ // ─── Main Detector ─────────────────────────────────────────────────────────
136
+ function detectFolderContext() {
137
+ const cwd = process.cwd();
138
+ const cwdParts = cwd.split(path.sep);
139
+ const result = {
140
+ isUniversityWorkspace: false,
141
+ };
142
+ // Check if we're inside a recognized university structure
143
+ for (let i = cwdParts.length - 1; i >= 0; i--) {
144
+ const part = cwdParts[i];
145
+ if (["university", "uni", "college", "school"].includes(part.toLowerCase())) {
146
+ result.isUniversityWorkspace = true;
147
+ // Try to find semester folder (one level below university root)
148
+ const semesterCandidate = cwdParts[i + 1];
149
+ if (semesterCandidate && SEMESTER_PATTERN.test(semesterCandidate)) {
150
+ result.semesterFolder = semesterCandidate;
151
+ }
152
+ // Try to find course folder
153
+ const courseCandidate = cwdParts[i + 2];
154
+ if (courseCandidate && COURSE_PATTERN.test(courseCandidate)) {
155
+ result.courseFolder = courseCandidate;
156
+ }
157
+ break;
158
+ }
159
+ }
160
+ // Detect the project type in cwd
161
+ result.project = buildProjectContext(cwd);
162
+ return result;
163
+ }
164
+ // ─── Context Summary ───────────────────────────────────────────────────────
165
+ function summarizeFolderContext(result) {
166
+ const lines = [];
167
+ if (result.isUniversityWorkspace) {
168
+ lines.push(`📂 University workspace detected`);
169
+ if (result.semesterFolder)
170
+ lines.push(` Semester: ${result.semesterFolder}`);
171
+ if (result.courseFolder)
172
+ lines.push(` Course: ${result.courseFolder}`);
173
+ }
174
+ if (result.project && result.project.type !== "unknown") {
175
+ const p = result.project;
176
+ lines.push(`🔧 Project: ${p.name} (${p.type})`);
177
+ if (!p.hasReadme)
178
+ lines.push(` ⚠️ No README.md found`);
179
+ if (!p.hasTests)
180
+ lines.push(` ⚠️ No test directory found`);
181
+ if (!p.hasCi)
182
+ lines.push(` 💡 Consider adding CI (.github/workflows)`);
183
+ if (p.testCommand)
184
+ lines.push(` Test: \`${p.testCommand}\``);
185
+ }
186
+ return lines.join("\n");
187
+ }
188
+ // ─── Pi Extension Entry Point ──────────────────────────────────────────────
189
+ function run() {
190
+ const result = detectFolderContext();
191
+ const summary = summarizeFolderContext(result);
192
+ const inject = summary
193
+ ? `<!-- FOLDER CONTEXT -->\n${summary.split("\n").map((l) => `<!-- ${l} -->`).join("\n")}`
194
+ : "";
195
+ return { inject };
196
+ }
197
+ //# sourceMappingURL=folder-detector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"folder-detector.js","sourceRoot":"","sources":["../../src/extensions/folder-detector.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * extensions/index.ts
3
+ *
4
+ * pi-cs (Pisces) — Pi Extension Entry Point
5
+ *
6
+ * Exports a default factory function that Pi loads via jiti.
7
+ * Wires up semester context detection, academic integrity guard,
8
+ * skill usage tracking, and burnout nudges.
9
+ */
10
+ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
11
+ export default function (pi: ExtensionAPI): void;
12
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/extensions/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAC;AAuHpE,MAAM,CAAC,OAAO,WAAW,EAAE,EAAE,YAAY,QA6FxC"}
@@ -0,0 +1,227 @@
1
+ "use strict";
2
+ /**
3
+ * extensions/index.ts
4
+ *
5
+ * pi-cs (Pisces) — Pi Extension Entry Point
6
+ *
7
+ * Exports a default factory function that Pi loads via jiti.
8
+ * Wires up semester context detection, academic integrity guard,
9
+ * skill usage tracking, and burnout nudges.
10
+ */
11
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
12
+ if (k2 === undefined) k2 = k;
13
+ var desc = Object.getOwnPropertyDescriptor(m, k);
14
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
15
+ desc = { enumerable: true, get: function() { return m[k]; } };
16
+ }
17
+ Object.defineProperty(o, k2, desc);
18
+ }) : (function(o, m, k, k2) {
19
+ if (k2 === undefined) k2 = k;
20
+ o[k2] = m[k];
21
+ }));
22
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
23
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
24
+ }) : function(o, v) {
25
+ o["default"] = v;
26
+ });
27
+ var __importStar = (this && this.__importStar) || (function () {
28
+ var ownKeys = function(o) {
29
+ ownKeys = Object.getOwnPropertyNames || function (o) {
30
+ var ar = [];
31
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
32
+ return ar;
33
+ };
34
+ return ownKeys(o);
35
+ };
36
+ return function (mod) {
37
+ if (mod && mod.__esModule) return mod;
38
+ var result = {};
39
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
40
+ __setModuleDefault(result, mod);
41
+ return result;
42
+ };
43
+ })();
44
+ Object.defineProperty(exports, "__esModule", { value: true });
45
+ exports.default = default_1;
46
+ const fs = __importStar(require("node:fs"));
47
+ const path = __importStar(require("node:path"));
48
+ const os = __importStar(require("node:os"));
49
+ function findSemesterMd() {
50
+ const searchPaths = [
51
+ process.cwd(),
52
+ path.join(os.homedir(), "university"),
53
+ path.join(os.homedir(), "uni"),
54
+ path.join(os.homedir(), "college"),
55
+ path.join(os.homedir(), "Documents", "university"),
56
+ ];
57
+ for (const dir of searchPaths) {
58
+ try {
59
+ const candidate = path.join(dir, "SEMESTER.md");
60
+ if (fs.existsSync(candidate))
61
+ return candidate;
62
+ }
63
+ catch {
64
+ continue;
65
+ }
66
+ }
67
+ return null;
68
+ }
69
+ function parseSemesterMd(content) {
70
+ const ctx = {
71
+ semester: "Unknown",
72
+ year: new Date().getFullYear(),
73
+ courses: [],
74
+ };
75
+ for (const line of content.split("\n")) {
76
+ const t = line.trim();
77
+ const sem = t.match(/^semester[:\s]+(.+)/i);
78
+ if (sem)
79
+ ctx.semester = sem[1].trim();
80
+ const yr = t.match(/^year[:\s]+(\d{4})/i);
81
+ if (yr)
82
+ ctx.year = parseInt(yr[1]);
83
+ const wk = t.match(/^week[:\s]+(\d+)/i);
84
+ if (wk)
85
+ ctx.week = parseInt(wk[1]);
86
+ const sy = t.match(/^year.of.study[:\s]+(\d)/i);
87
+ if (sy)
88
+ ctx.year_of_study = parseInt(sy[1]);
89
+ const course = t.match(/^[-*]\s+([A-Z]{2,4}\d{2,4})[:\s]+(.+)/);
90
+ if (course)
91
+ ctx.courses.push({ code: course[1], name: course[2].trim() });
92
+ const proj = t.match(/^active.project[:\s]+(.+)/i);
93
+ if (proj)
94
+ ctx.active_project = proj[1].trim();
95
+ }
96
+ return ctx;
97
+ }
98
+ function semesterContextBlock(ctx) {
99
+ return [
100
+ `[pi-cs] Semester: ${ctx.semester} ${ctx.year}`,
101
+ ctx.week != null ? `[pi-cs] Week: ${ctx.week}` : "",
102
+ ctx.year_of_study != null ? `[pi-cs] Year of study: ${ctx.year_of_study}` : "",
103
+ ctx.courses.length
104
+ ? `[pi-cs] Courses: ${ctx.courses.map((c) => `${c.code} (${c.name})`).join(", ")}`
105
+ : "",
106
+ ctx.active_project ? `[pi-cs] Active project: ${ctx.active_project}` : "",
107
+ ]
108
+ .filter(Boolean)
109
+ .join("\n");
110
+ }
111
+ // ─── Academic Integrity Guard ──────────────────────────────────────────────
112
+ const HIGH_RISK_PATTERNS = [
113
+ /write.*(my|the)\s+(entire|whole|complete|full)\s+(assignment|homework|lab|project)/i,
114
+ /do\s+my\s+(homework|assignment|lab|project)/i,
115
+ /complete\s+(my|the)\s+(assignment|homework|lab|task)/i,
116
+ /finish\s+my\s+(assignment|homework|lab)\s+for\s+me/i,
117
+ ];
118
+ const SAFE_OVERRIDE_PATTERNS = [
119
+ /\bpractic/i,
120
+ /\blearn\b/i,
121
+ /\bunderstand\b/i,
122
+ /\bjust\s+curious\b/i,
123
+ /\bnot\s+for\s+grade/i,
124
+ /\bpersonal\s+project\b/i,
125
+ /\bleetcode\b/i,
126
+ ];
127
+ function integrityWarning(text) {
128
+ if (SAFE_OVERRIDE_PATTERNS.some((p) => p.test(text)))
129
+ return null;
130
+ if (HIGH_RISK_PATTERNS.some((p) => p.test(text))) {
131
+ return [
132
+ "⚠️ **Academic Integrity Notice**",
133
+ "",
134
+ "It sounds like you want me to complete a graded assignment. I won't do that — it would hurt your learning and could get you in serious trouble.",
135
+ "",
136
+ "Here's what I *can* do:",
137
+ "- Break down the problem and explain the concepts",
138
+ "- Give hints and guided pseudocode",
139
+ "- Help you debug your own code",
140
+ "- Explain similar example problems",
141
+ "",
142
+ "Tell me where you're actually stuck and we'll work through it together. 🐠",
143
+ ].join("\n");
144
+ }
145
+ return null;
146
+ }
147
+ // ─── Pi Extension Factory ──────────────────────────────────────────────────
148
+ function default_1(pi) {
149
+ let semesterCtx = null;
150
+ const sessionStart = Date.now();
151
+ const skillsUsed = [];
152
+ // ── Load semester context at startup ─────────────────────────────────
153
+ pi.on("session_start", async (_event, ctx) => {
154
+ const semFile = findSemesterMd();
155
+ if (semFile) {
156
+ try {
157
+ const content = fs.readFileSync(semFile, "utf-8");
158
+ semesterCtx = parseSemesterMd(content);
159
+ ctx.ui.notify(`🐠 Pisces loaded — ${semesterCtx.semester} ${semesterCtx.year}${semesterCtx.week ? `, Week ${semesterCtx.week}` : ""}`, "info");
160
+ }
161
+ catch {
162
+ ctx.ui.notify("🐠 Pisces loaded", "info");
163
+ }
164
+ }
165
+ else {
166
+ ctx.ui.notify("🐠 Pisces loaded — no SEMESTER.md found. Create one to enable context awareness.", "info");
167
+ }
168
+ });
169
+ // ── Inject semester context into system prompt each turn ─────────────
170
+ pi.on("before_agent_start", async (event) => {
171
+ if (!semesterCtx)
172
+ return;
173
+ const contextBlock = semesterContextBlock(semesterCtx);
174
+ const appendedSystemPrompt = `${event.systemPrompt}\n\n${contextBlock}`;
175
+ return { systemPrompt: appendedSystemPrompt };
176
+ });
177
+ // ── Academic integrity guard on every input ───────────────────────────
178
+ pi.on("input", async (event) => {
179
+ const warning = integrityWarning(event.text);
180
+ if (warning) {
181
+ pi.sendUserMessage(warning);
182
+ return { action: "handled" };
183
+ }
184
+ return { action: "continue" };
185
+ });
186
+ // ── Track which skills are used this session ──────────────────────────
187
+ pi.on("input", async (event) => {
188
+ const match = event.text.match(/^\/skill:(\w+)/);
189
+ if (match && !skillsUsed.includes(match[1])) {
190
+ skillsUsed.push(match[1]);
191
+ }
192
+ return { action: "continue" };
193
+ });
194
+ // ── Burnout nudge at 3-hour mark ──────────────────────────────────────
195
+ pi.on("before_agent_start", async (_event, ctx) => {
196
+ const elapsed = Math.round((Date.now() - sessionStart) / 60000);
197
+ if (elapsed > 0 && elapsed % 180 === 0) {
198
+ ctx.ui.notify(`🐠 You've been at this for ${elapsed} minutes. Take a short break — your brain consolidates learning during rest, not during grinding.`, "info");
199
+ }
200
+ });
201
+ // ── /pisces command: show session status ──────────────────────────────
202
+ pi.registerCommand("pisces", {
203
+ description: "Show Pisces status — semester context, skills used, session duration",
204
+ handler: async (_args, ctx) => {
205
+ const elapsed = Math.round((Date.now() - sessionStart) / 60000);
206
+ const lines = [
207
+ "🐠 **Pisces Status**",
208
+ "",
209
+ semesterCtx
210
+ ? `📅 ${semesterCtx.semester} ${semesterCtx.year}${semesterCtx.week ? ` — Week ${semesterCtx.week}` : ""}`
211
+ : "📅 No SEMESTER.md loaded",
212
+ semesterCtx?.courses.length
213
+ ? `📚 Courses: ${semesterCtx.courses.map((c) => c.code).join(", ")}`
214
+ : "",
215
+ semesterCtx?.active_project ? `🔧 Project: ${semesterCtx.active_project}` : "",
216
+ `⏱ Session: ${elapsed} minute${elapsed !== 1 ? "s" : ""}`,
217
+ skillsUsed.length
218
+ ? `🛠 Skills used this session: ${skillsUsed.map((s) => `/skill:${s}`).join(", ")}`
219
+ : "🛠 No skills used yet — try /skill:explain, /skill:homework, or /skill:leetcode",
220
+ ]
221
+ .filter(Boolean)
222
+ .join("\n");
223
+ ctx.ui.notify(lines, "info");
224
+ },
225
+ });
226
+ }
227
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/extensions/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * integrity-guard.ts
3
+ *
4
+ * Extension: Academic Integrity Guard
5
+ * Triggers: on_skill_call
6
+ *
7
+ * Monitors skill calls for academic integrity risk patterns.
8
+ * Injects appropriate warnings and mode adjustments into the session.
9
+ */
10
+ export type IntegrityRisk = "none" | "low" | "medium" | "high";
11
+ export interface IntegrityCheckResult {
12
+ risk: IntegrityRisk;
13
+ reason?: string;
14
+ warning?: string;
15
+ shouldAskUser?: boolean;
16
+ }
17
+ export declare function checkIntegrityRisk(userInput: string, skillName: string): IntegrityCheckResult;
18
+ export declare function run(context: {
19
+ skillName: string;
20
+ userInput: string;
21
+ }): {
22
+ block: boolean;
23
+ inject: string;
24
+ };
25
+ //# sourceMappingURL=integrity-guard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"integrity-guard.d.ts","sourceRoot":"","sources":["../../src/extensions/integrity-guard.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;AAE/D,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,aAAa,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAwCD,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,GAChB,oBAAoB,CAmCtB;AA6BD,wBAAgB,GAAG,CAAC,OAAO,EAAE;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB,GAAG;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAkBrC"}
@@ -0,0 +1,118 @@
1
+ "use strict";
2
+ /**
3
+ * integrity-guard.ts
4
+ *
5
+ * Extension: Academic Integrity Guard
6
+ * Triggers: on_skill_call
7
+ *
8
+ * Monitors skill calls for academic integrity risk patterns.
9
+ * Injects appropriate warnings and mode adjustments into the session.
10
+ */
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.checkIntegrityRisk = checkIntegrityRisk;
13
+ exports.run = run;
14
+ // ─── Risk Signals ──────────────────────────────────────────────────────────
15
+ // High-risk: user is likely asking for submission-ready work
16
+ const HIGH_RISK_PATTERNS = [
17
+ /write.*(my|the)\s+(entire|whole|complete|full)\s+(assignment|homework|lab|project)/i,
18
+ /do\s+my\s+(homework|assignment|lab|project)/i,
19
+ /complete\s+(my|the)\s+(assignment|homework|lab|task)/i,
20
+ /submit.*(this|it)\s+as\s+my\s+own/i,
21
+ /just\s+give\s+me\s+the\s+(code|answer|solution)\s+(for|to)\s+my/i,
22
+ /finish\s+my\s+(assignment|homework|lab)\s+for\s+me/i,
23
+ ];
24
+ // Medium-risk: could be academic work, should clarify
25
+ const MEDIUM_RISK_PATTERNS = [
26
+ /\bassignment\b/i,
27
+ /\bhomework\b/i,
28
+ /\bdue\s+(tomorrow|tonight|today|friday|monday)\b/i,
29
+ /\blab\s+\d+\b/i,
30
+ /\bproject\s+\d+\b/i,
31
+ /\bgraded\b/i,
32
+ /\bsubmit\b/i,
33
+ /\bprofessor\s+(wants|requires|said)\b/i,
34
+ ];
35
+ // Safe patterns that override medium-risk (clearly practice/learning)
36
+ const SAFE_OVERRIDE_PATTERNS = [
37
+ /\bpractic/i,
38
+ /\blearn\b/i,
39
+ /\bunderstand\b/i,
40
+ /\bjust\s+curious\b/i,
41
+ /\bnot\s+for\s+grade/i,
42
+ /\bpersonal\s+project\b/i,
43
+ /\bside\s+project\b/i,
44
+ /\bleetcode\b/i,
45
+ ];
46
+ // ─── Checker ───────────────────────────────────────────────────────────────
47
+ function checkIntegrityRisk(userInput, skillName) {
48
+ // /leetcode and /project are always safe to produce complete code
49
+ if (["leetcode", "project"].includes(skillName)) {
50
+ return { risk: "none" };
51
+ }
52
+ // Check safe overrides first
53
+ const isSafe = SAFE_OVERRIDE_PATTERNS.some((p) => p.test(userInput));
54
+ if (isSafe) {
55
+ return { risk: "none" };
56
+ }
57
+ // Check high risk
58
+ const highRiskMatch = HIGH_RISK_PATTERNS.find((p) => p.test(userInput));
59
+ if (highRiskMatch) {
60
+ return {
61
+ risk: "high",
62
+ reason: "User appears to be asking for a complete, submittable solution",
63
+ warning: buildHighRiskWarning(),
64
+ shouldAskUser: false, // Don't ask — just redirect
65
+ };
66
+ }
67
+ // Check medium risk
68
+ const mediumRiskMatch = MEDIUM_RISK_PATTERNS.find((p) => p.test(userInput));
69
+ if (mediumRiskMatch) {
70
+ return {
71
+ risk: "medium",
72
+ reason: `Input mentions "${mediumRiskMatch.source}" — may be graded work`,
73
+ warning: buildMediumRiskWarning(),
74
+ shouldAskUser: true, // Ask before proceeding
75
+ };
76
+ }
77
+ return { risk: "none" };
78
+ }
79
+ // ─── Warning Messages ──────────────────────────────────────────────────────
80
+ function buildHighRiskWarning() {
81
+ return `⚠️ **Academic Integrity Notice**
82
+
83
+ It sounds like you're asking me to complete a graded assignment for you. I won't do that — not because I can't, but because it would genuinely hurt your learning and could get you in serious trouble.
84
+
85
+ Here's what I *can* do:
86
+ - Break down the problem and explain the concepts involved
87
+ - Give you hints and guided pseudocode
88
+ - Help you debug your own attempts
89
+ - Explain similar example problems
90
+
91
+ Tell me where you're actually stuck, and let's work through it together. 🐠`;
92
+ }
93
+ function buildMediumRiskWarning() {
94
+ return `Before I dive in — **is this for a graded assignment?**
95
+
96
+ - If **yes**: I'll use guided-mode (hints, pseudocode, concept explanations — no complete solutions)
97
+ - If **no**: I'll give you a full solution with explanation
98
+
99
+ Just let me know!`;
100
+ }
101
+ // ─── Pi Extension Entry Point ──────────────────────────────────────────────
102
+ function run(context) {
103
+ const result = checkIntegrityRisk(context.userInput, context.skillName);
104
+ if (result.risk === "high") {
105
+ return {
106
+ block: false, // Don't block — redirect gracefully
107
+ inject: result.warning ?? "",
108
+ };
109
+ }
110
+ if (result.risk === "medium" && result.shouldAskUser) {
111
+ return {
112
+ block: false,
113
+ inject: result.warning ?? "",
114
+ };
115
+ }
116
+ return { block: false, inject: "" };
117
+ }
118
+ //# sourceMappingURL=integrity-guard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"integrity-guard.js","sourceRoot":"","sources":["../../src/extensions/integrity-guard.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * progress-tracker.ts
3
+ *
4
+ * Extension: Progress Tracker
5
+ * Triggers: on_session_end
6
+ *
7
+ * Tracks weekly activity across skills and sessions.
8
+ * Surfaces burnout prevention nudges and weekly summaries.
9
+ */
10
+ export interface SessionRecord {
11
+ date: string;
12
+ durationMinutes: number;
13
+ skillsUsed: string[];
14
+ topicsWorked: string[];
15
+ }
16
+ export interface WeeklyStats {
17
+ totalMinutes: number;
18
+ sessionCount: number;
19
+ skillBreakdown: Record<string, number>;
20
+ longestSession: number;
21
+ streak: number;
22
+ }
23
+ export declare function getBurnoutNudge(sessionDurationMinutes: number, stats: WeeklyStats): string | null;
24
+ export declare function buildWeeklySummary(stats: WeeklyStats): string;
25
+ export declare function run(context: {
26
+ sessionDurationMinutes: number;
27
+ skillsUsed: string[];
28
+ topicsWorked?: string[];
29
+ }): {
30
+ nudge: string | null;
31
+ weeklySummary: string;
32
+ };
33
+ //# sourceMappingURL=progress-tracker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"progress-tracker.d.ts","sourceRoot":"","sources":["../../src/extensions/progress-tracker.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAQH,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,eAAe,EAAE,MAAM,CAAC;IACxB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB;AAED,MAAM,WAAW,WAAW;IAC1B,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACvC,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;CAChB;AAgFD,wBAAgB,eAAe,CAC7B,sBAAsB,EAAE,MAAM,EAC9B,KAAK,EAAE,WAAW,GACjB,MAAM,GAAG,IAAI,CAiBf;AAID,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,CA6B7D;AAID,wBAAgB,GAAG,CAAC,OAAO,EAAE;IAC3B,sBAAsB,EAAE,MAAM,CAAC;IAC/B,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;CACzB,GAAG;IAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,aAAa,EAAE,MAAM,CAAA;CAAE,CAmBlD"}