@aethrekh/pi-cs 0.1.10 → 0.2.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -7,6 +7,24 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ---
9
9
 
10
+ ## [0.2.0-alpha.0](https://github.com/AshishBagdane/pi-cs/compare/v0.1.10...v0.2.0-alpha.0) (2026-06-05)
11
+
12
+ ### ### Added
13
+
14
+ * implement workspace scoping via .pisces marker walk-up ([51444c1](https://github.com/AshishBagdane/pi-cs/commit/51444c19034047fbcd00111ce3ca2c30f7fb37c7))
15
+
16
+ ### ### Fixed
17
+
18
+ * clean up ~/.pi-cs/sessions.json on uninstall ([56d020a](https://github.com/AshishBagdane/pi-cs/commit/56d020aa319006b72299912ef43324c7747e0d4d))
19
+ * register workspace.ts as a Pi extension so workspace.js is included in pack ([7f2546c](https://github.com/AshishBagdane/pi-cs/commit/7f2546ce50debcd5bda4a6da6ece9c482a13d861))
20
+
21
+ ### ### Changed
22
+
23
+ * add workspace-scoping design document ([098504a](https://github.com/AshishBagdane/pi-cs/commit/098504a8262986def084c34a89d585a08e40531b))
24
+ * align README and STUDENT_GUIDE with v0.1.10 install behaviour ([e8f6ae5](https://github.com/AshishBagdane/pi-cs/commit/e8f6ae5a9ed4ebd54409985e00d18b3356438255))
25
+ * fix false local install scope claims and expand troubleshooting ([0e000f7](https://github.com/AshishBagdane/pi-cs/commit/0e000f7ac947fc641785ab46818649710d857265))
26
+ * update README and STUDENT_GUIDE for workspace-scoped activation ([81e8872](https://github.com/AshishBagdane/pi-cs/commit/81e8872c024edb8c41cbc0d7b1fa85b10ddb16c9))
27
+
10
28
  ## [0.1.10](https://github.com/AshishBagdane/pi-cs/compare/v0.1.10-alpha.1...v0.1.10) (2026-06-05)
11
29
 
12
30
  ## [0.1.10-alpha.1](https://github.com/AshishBagdane/pi-cs/compare/v0.1.10-alpha.0...v0.1.10-alpha.1) (2026-06-05)
package/README.md CHANGED
@@ -29,20 +29,23 @@ It covers every dimension of a CS degree:
29
29
  ## Quick Start
30
30
 
31
31
  ```bash
32
- # Install Pisces in your university workspace (recommended)
32
+ # Install Pisces globally (one-time setup)
33
+ pi install npm:@aethrekh/pi-cs
34
+
35
+ # Mark your university folder as a Pisces workspace
33
36
  cd ~/university
34
- pi install npm:@aethrekh/pi-cs -l
37
+ /pisces --activate
35
38
 
36
39
  # Initialize your semester context
37
40
  /semester --init
38
41
 
39
- # Start working
42
+ # Start working — from any subdirectory
40
43
  /homework
41
44
  /explain binary search trees
42
45
  /leetcode 42
43
46
  ```
44
47
 
45
- > **Global install:** `pi install npm:@aethrekh/pi-cs` (without `-l`) activates Pisces in every Pi session, including non-university projects. Use this only if you want Pisces everywhere.
48
+ > **Workspace-scoped by default:** Pisces is silent in non-academic sessions. Once you run `/pisces --activate` in a directory, Pisces activates in every Pi session started inside that directory tree — no reinstalling, no per-folder setup. See the [Installation](#installation) section for details.
46
49
 
47
50
  ---
48
51
 
@@ -196,10 +199,31 @@ See [`config/schema.json`](config/schema.json) for the full configuration refere
196
199
  **Requirements:** Pi >= 0.78.0, Node.js >= 18
197
200
 
198
201
  ```bash
202
+ # Step 1 — Install globally (one command, once per machine)
199
203
  pi install npm:@aethrekh/pi-cs
204
+
205
+ # Step 2 — Activate in your university folder
206
+ cd ~/university
207
+ /pisces --activate
208
+
209
+ # Step 3 — Set up semester context
210
+ /semester --init
211
+ ```
212
+
213
+ **How scoping works:** Pisces is completely silent outside workspace trees. Once you run `/pisces --activate` in a directory, it creates a `.pisces` marker file there. On every Pi session, Pisces walks up from `process.cwd()` looking for `.pisces` — if found, it activates; if not, it is a silent no-op. This means:
214
+
215
+ - One global install covers every workspace you mark
216
+ - Work and personal sessions are unaffected until you mark them
217
+ - Multiple independent workspaces are supported (just run `/pisces --activate` in each root)
218
+ - Deactivate with `/pisces --deactivate` or `rm .pisces`
219
+
220
+ ```bash
221
+ # Local install — activates Pisces only in the exact install directory
222
+ cd ~/university
223
+ pi install npm:@aethrekh/pi-cs -l
200
224
  ```
201
225
 
202
- That's it. Pisces activates automatically in every Pi session.
226
+ Pi does not walk up parent directories to find locally installed packages. If you use `-l`, Pisces only loads when Pi is started from `~/university` itself — not from any subdirectory like `~/university/fall2025/CS301/`. Use the global install for most setups.
203
227
 
204
228
  ---
205
229
 
@@ -220,6 +244,7 @@ pi-cs/
220
244
  │ │ ├── exam/SKILL.md # /exam skill
221
245
  │ │ └── research/SKILL.md # /research skill
222
246
  │ ├── extensions/
247
+ │ │ ├── workspace.ts # .pisces walk-up detection (shared)
223
248
  │ │ ├── semester-detector.ts # Auto-loads SEMESTER.md
224
249
  │ │ ├── folder-detector.ts # Detects CS folder structures
225
250
  │ │ ├── integrity-guard.ts # Academic integrity monitoring
@@ -242,6 +267,7 @@ pi-cs/
242
267
  - [x] 4 background extensions
243
268
  - [x] Semester context system
244
269
  - [x] Academic integrity guard
270
+ - [x] Workspace-scoped activation (`.pisces` marker)
245
271
  - [ ] arXiv live search integration
246
272
  - [ ] Model routing presets
247
273
  - [ ] Obsidian vault sync
@@ -48,6 +48,7 @@ exports.default = default_1;
48
48
  exports.run = run;
49
49
  const fs = __importStar(require("fs"));
50
50
  const path = __importStar(require("path"));
51
+ const workspace_1 = require("./workspace");
51
52
  // ─── Marker Files ──────────────────────────────────────────────────────────
52
53
  const PYTHON_MARKERS = ["requirements.txt", "pyproject.toml", "setup.py", "Pipfile"];
53
54
  const TS_MARKERS = ["package.json", "tsconfig.json"];
@@ -188,15 +189,14 @@ function summarizeFolderContext(result) {
188
189
  }
189
190
  // ─── Pi Extension Factory ──────────────────────────────────────────────────
190
191
  function default_1(pi) {
191
- let contextSummary = "";
192
- pi.on("session_start", async () => {
193
- const result = detectFolderContext();
194
- contextSummary = summarizeFolderContext(result);
195
- });
196
192
  pi.on("before_agent_start", async (event) => {
197
- if (!contextSummary)
193
+ // Re-check workspace on every agent turn — no closure state needed.
194
+ if (!(0, workspace_1.findPiscesMarker)())
195
+ return;
196
+ const summary = summarizeFolderContext(detectFolderContext());
197
+ if (!summary)
198
198
  return;
199
- return { systemPrompt: `${event.systemPrompt}\n\n${contextSummary}` };
199
+ return { systemPrompt: `${event.systemPrompt}\n\n${summary}` };
200
200
  });
201
201
  }
202
202
  // ─── Pi Extension Entry Point ──────────────────────────────────────────────
@@ -12,6 +12,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.checkIntegrityRisk = checkIntegrityRisk;
13
13
  exports.default = default_1;
14
14
  exports.run = run;
15
+ const workspace_1 = require("./workspace");
15
16
  // ─── Risk Signals ──────────────────────────────────────────────────────────
16
17
  // High-risk: user is likely asking for submission-ready work
17
18
  const HIGH_RISK_PATTERNS = [
@@ -101,10 +102,22 @@ Just let me know!`;
101
102
  }
102
103
  // ─── Pi Extension Factory ──────────────────────────────────────────────────
103
104
  function default_1(pi) {
105
+ let isActive = false;
104
106
  // Guard against sendUserMessage re-triggering this handler — warning text
105
107
  // contains words like "graded" that would otherwise match medium-risk patterns.
106
108
  let handlingWarning = false;
109
+ pi.on("session_start", async () => {
110
+ isActive = (0, workspace_1.findPiscesMarker)() !== null;
111
+ });
112
+ // Refresh isActive before each agent turn so mid-session workspace changes
113
+ // are picked up. The input handler may still use a one-turn-stale value for
114
+ // messages that arrive before the first before_agent_start of a new turn.
115
+ pi.on("before_agent_start", async () => {
116
+ isActive = (0, workspace_1.findPiscesMarker)() !== null;
117
+ });
107
118
  pi.on("input", async (event) => {
119
+ if (!isActive)
120
+ return { action: "continue" };
108
121
  if (handlingWarning)
109
122
  return { action: "continue" };
110
123
  const skillMatch = event.text.match(/^\/skill:(\w+)\s*/);
@@ -50,6 +50,7 @@ const fs = __importStar(require("fs"));
50
50
  const path = __importStar(require("path"));
51
51
  const os = __importStar(require("os"));
52
52
  const semester_detector_1 = require("./semester-detector");
53
+ const workspace_1 = require("./workspace");
53
54
  // ─── Storage ───────────────────────────────────────────────────────────────
54
55
  const TRACKER_DIR = path.join(os.homedir(), ".pi-cs");
55
56
  const SESSIONS_FILE = path.join(TRACKER_DIR, "sessions.json");
@@ -161,7 +162,15 @@ function buildWeeklySummary(stats) {
161
162
  function default_1(pi) {
162
163
  const sessionStart = Date.now();
163
164
  const skillsUsed = [];
165
+ let isActive = false;
166
+ let workspaceRoot = null;
167
+ pi.on("session_start", async () => {
168
+ workspaceRoot = (0, workspace_1.findPiscesMarker)();
169
+ isActive = workspaceRoot !== null;
170
+ });
164
171
  pi.on("input", async (event) => {
172
+ if (!isActive)
173
+ return { action: "continue" };
165
174
  const match = event.text.match(/^\/skill:(\w+)/);
166
175
  if (match && !skillsUsed.includes(match[1])) {
167
176
  skillsUsed.push(match[1]);
@@ -169,12 +178,19 @@ function default_1(pi) {
169
178
  return { action: "continue" };
170
179
  });
171
180
  pi.on("before_agent_start", async (_event, ctx) => {
181
+ // Refresh workspace state on every agent turn so mid-session changes are reflected.
182
+ workspaceRoot = (0, workspace_1.findPiscesMarker)();
183
+ isActive = workspaceRoot !== null;
184
+ if (!isActive)
185
+ return;
172
186
  const elapsed = Math.round((Date.now() - sessionStart) / 60000);
173
187
  if (elapsed > 0 && elapsed % 180 === 0) {
174
188
  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");
175
189
  }
176
190
  });
177
191
  pi.on("session_shutdown", async (_event, ctx) => {
192
+ if (!isActive)
193
+ return;
178
194
  const durationMinutes = Math.round((Date.now() - sessionStart) / 60000);
179
195
  const { nudge, weeklySummary } = run({ sessionDurationMinutes: durationMinutes, skillsUsed });
180
196
  if (nudge)
@@ -183,27 +199,101 @@ function default_1(pi) {
183
199
  ctx.ui.notify(weeklySummary, "info");
184
200
  });
185
201
  pi.registerCommand("pisces", {
186
- description: "Show Pisces status — semester context, skills used, session duration",
187
- handler: async (_args, ctx) => {
202
+ description: "Workspace lifecycle and status for Pisces use --activate, --deactivate, --status, --version",
203
+ handler: async (args, ctx) => {
204
+ const flag = (typeof args === "string" ? args : args[0] ?? "").trim();
205
+ // ── /pisces --activate ───────────────────────────────────────────────
206
+ if (flag === "--activate") {
207
+ const cwd = process.cwd();
208
+ const existing = (0, workspace_1.findPiscesMarker)(cwd);
209
+ if (existing) {
210
+ ctx.ui.notify(`🐠 Workspace already active at: ${existing}\n\nRun /pisces --status for details.`, "info");
211
+ return;
212
+ }
213
+ try {
214
+ (0, workspace_1.createPiscesMarker)(cwd);
215
+ workspaceRoot = cwd;
216
+ isActive = true;
217
+ ctx.ui.notify([
218
+ `✅ Workspace activated at: ${cwd}`,
219
+ ` ${workspace_1.PISCES_MARKER} created.`,
220
+ ``,
221
+ `All Pi sessions in this directory tree will now activate Pisces.`,
222
+ ``,
223
+ `Run /semester --init to set up semester context, or start working right away.`,
224
+ ].join("\n"), "info");
225
+ }
226
+ catch (err) {
227
+ ctx.ui.notify(`❌ Failed to create ${workspace_1.PISCES_MARKER}: ${String(err)}`, "error");
228
+ }
229
+ return;
230
+ }
231
+ // ── /pisces --deactivate ─────────────────────────────────────────────
232
+ if (flag === "--deactivate") {
233
+ if (!workspaceRoot) {
234
+ ctx.ui.notify("🐠 No active Pisces workspace in this session — nothing to deactivate.", "info");
235
+ return;
236
+ }
237
+ try {
238
+ (0, workspace_1.removePiscesMarker)(workspaceRoot);
239
+ const removed = workspaceRoot;
240
+ workspaceRoot = null;
241
+ isActive = false;
242
+ ctx.ui.notify(`✅ Workspace deactivated.\n Removed ${workspace_1.PISCES_MARKER} from: ${removed}\n\nTakes full effect on next session start.`, "info");
243
+ }
244
+ catch (err) {
245
+ ctx.ui.notify(`❌ Failed to remove ${workspace_1.PISCES_MARKER}: ${String(err)}`, "error");
246
+ }
247
+ return;
248
+ }
249
+ // ── /pisces --version ────────────────────────────────────────────────
250
+ if (flag === "--version") {
251
+ // Read version from package.json at runtime to stay in sync with releases
252
+ let version = "unknown";
253
+ try {
254
+ const pkgPath = path.resolve(__dirname, "../../package.json");
255
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
256
+ version = pkg.version;
257
+ }
258
+ catch { /* fall through */ }
259
+ ctx.ui.notify(`🐠 pi-cs (Pisces) v${version}`, "info");
260
+ return;
261
+ }
262
+ // ── /pisces --status (default) ───────────────────────────────────────
188
263
  const elapsed = Math.round((Date.now() - sessionStart) / 60000);
264
+ if (!isActive) {
265
+ ctx.ui.notify([
266
+ "Pisces Status",
267
+ "─────────────────────────────────────",
268
+ "Active: ❌ No",
269
+ `Reason: No ${workspace_1.PISCES_MARKER} found within search bounds (15 levels, ~)`,
270
+ "",
271
+ "Run /pisces --activate to mark this directory as a workspace root.",
272
+ ].join("\n"), "info");
273
+ return;
274
+ }
189
275
  const detection = (0, semester_detector_1.detectSemesterContext)();
190
276
  const semCtx = detection.context;
191
277
  const lines = [
192
- "🐠 **Pisces Status**",
278
+ "Pisces Status",
279
+ "─────────────────────────────────────",
280
+ "Active: ✅ Yes",
281
+ `Workspace root: ${workspaceRoot}`,
282
+ `Session: ${elapsed} minute${elapsed !== 1 ? "s" : ""}`,
193
283
  "",
194
284
  semCtx
195
- ? `📅 ${semCtx.semester} ${semCtx.year}${semCtx.week ? ` — Week ${semCtx.week}` : ""}`
196
- : "📅 No SEMESTER.md loaded",
285
+ ? `Semester: ${semCtx.semester} ${semCtx.year}${semCtx.week ? ` — Week ${semCtx.week}` : ""}`
286
+ : "Semester: ❌ No SEMESTER.md loaded — run /semester --init",
197
287
  semCtx?.courses?.length
198
- ? `📚 Courses: ${semCtx.courses.map((c) => c.code).join(", ")}`
288
+ ? `Courses: ${semCtx.courses.map((c) => c.code).join(", ")}`
199
289
  : "",
200
- semCtx?.active_project ? `🔧 Project: ${semCtx.active_project}` : "",
201
- `⏱ Session: ${elapsed} minute${elapsed !== 1 ? "s" : ""}`,
290
+ semCtx?.active_project ? `Project: ${semCtx.active_project}` : "",
291
+ "",
202
292
  skillsUsed.length
203
- ? `🛠 Skills used this session: ${skillsUsed.map((s) => `/skill:${s}`).join(", ")}`
204
- : "🛠 No skills used yet — try /skill:explain, /skill:homework, or /skill:leetcode",
293
+ ? `Skills used: ${skillsUsed.map((s) => `/skill:${s}`).join(", ")}`
294
+ : "No skills used yet — try /skill:explain, /skill:homework, or /skill:leetcode",
205
295
  ]
206
- .filter(Boolean)
296
+ .filter((l) => l !== undefined)
207
297
  .join("\n");
208
298
  ctx.ui.notify(lines, "info");
209
299
  },
@@ -49,6 +49,7 @@ exports.run = run;
49
49
  const fs = __importStar(require("fs"));
50
50
  const path = __importStar(require("path"));
51
51
  const os = __importStar(require("os"));
52
+ const workspace_1 = require("./workspace");
52
53
  // ─── Search Paths ──────────────────────────────────────────────────────────
53
54
  function getSearchPaths() {
54
55
  return [
@@ -224,6 +225,8 @@ function default_1(pi) {
224
225
  const persona = loadPersona();
225
226
  let semesterCtx = null;
226
227
  pi.on("session_start", async (_event, ctx) => {
228
+ if (!(0, workspace_1.findPiscesMarker)())
229
+ return;
227
230
  if (removeLegacyGlobalPersona(persona)) {
228
231
  ctx.ui.notify("🐠 Pisces: cleaned up a stale ~/.pi/agent/APPEND_SYSTEM.md from an older install. Persona is now session-scoped.", "info");
229
232
  }
@@ -238,6 +241,17 @@ function default_1(pi) {
238
241
  }
239
242
  });
240
243
  pi.on("before_agent_start", async (event) => {
244
+ // Re-check workspace on every agent turn so mid-session activation/deactivation
245
+ // is reflected without needing a session restart.
246
+ if (!(0, workspace_1.findPiscesMarker)())
247
+ return;
248
+ // Lazy-load semester context if it was not available at session_start
249
+ // (e.g. workspace was activated mid-session via /pisces --activate).
250
+ if (!semesterCtx) {
251
+ const result = detectSemesterContext();
252
+ if (result.found && result.context)
253
+ semesterCtx = result.context;
254
+ }
241
255
  const parts = [];
242
256
  if (persona)
243
257
  parts.push(persona);
@@ -0,0 +1,108 @@
1
+ "use strict";
2
+ /**
3
+ * workspace.ts
4
+ *
5
+ * Walk-up logic for .pisces workspace marker detection.
6
+ * Shared by all four extensions — each calls findPiscesMarker()
7
+ * independently at session_start and before_agent_start.
8
+ *
9
+ * Registered as a Pi extension so that the pack includes workspace.js
10
+ * alongside the other extension files. The default export is a no-op;
11
+ * the module's value is its named exports (findPiscesMarker et al.).
12
+ */
13
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
14
+ if (k2 === undefined) k2 = k;
15
+ var desc = Object.getOwnPropertyDescriptor(m, k);
16
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
17
+ desc = { enumerable: true, get: function() { return m[k]; } };
18
+ }
19
+ Object.defineProperty(o, k2, desc);
20
+ }) : (function(o, m, k, k2) {
21
+ if (k2 === undefined) k2 = k;
22
+ o[k2] = m[k];
23
+ }));
24
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
25
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
26
+ }) : function(o, v) {
27
+ o["default"] = v;
28
+ });
29
+ var __importStar = (this && this.__importStar) || (function () {
30
+ var ownKeys = function(o) {
31
+ ownKeys = Object.getOwnPropertyNames || function (o) {
32
+ var ar = [];
33
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
34
+ return ar;
35
+ };
36
+ return ownKeys(o);
37
+ };
38
+ return function (mod) {
39
+ if (mod && mod.__esModule) return mod;
40
+ var result = {};
41
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
42
+ __setModuleDefault(result, mod);
43
+ return result;
44
+ };
45
+ })();
46
+ Object.defineProperty(exports, "__esModule", { value: true });
47
+ exports.PISCES_MARKER = void 0;
48
+ exports.default = default_1;
49
+ exports.findPiscesMarker = findPiscesMarker;
50
+ exports.createPiscesMarker = createPiscesMarker;
51
+ exports.removePiscesMarker = removePiscesMarker;
52
+ const fs = __importStar(require("fs"));
53
+ const path = __importStar(require("path"));
54
+ const os = __importStar(require("os"));
55
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
56
+ function default_1(_pi) {
57
+ // Shared utility module — not a standalone extension.
58
+ // Pi loads this file; the named exports are imported by the other extensions.
59
+ }
60
+ exports.PISCES_MARKER = ".pisces";
61
+ const MAX_WALK_LEVELS = 15;
62
+ /**
63
+ * Walks up from cwd looking for a .pisces file. Returns the absolute
64
+ * path of the directory containing .pisces (the workspace root), or null
65
+ * if not found within the search bounds.
66
+ *
67
+ * Bounds (whichever is reached first):
68
+ * - 15 directory levels above cwd
69
+ * - Home directory (~) — .pisces at ~ or above is not a valid workspace root
70
+ * - Filesystem root (/)
71
+ */
72
+ function findPiscesMarker(cwd = process.cwd()) {
73
+ const home = path.resolve(os.homedir());
74
+ let current = path.resolve(cwd);
75
+ for (let level = 0; level < MAX_WALK_LEVELS; level++) {
76
+ // Stop at home or above — not a valid workspace root
77
+ if (current === home || !current.startsWith(home + path.sep))
78
+ break;
79
+ try {
80
+ if (fs.existsSync(path.join(current, exports.PISCES_MARKER))) {
81
+ return current;
82
+ }
83
+ }
84
+ catch {
85
+ // skip unreadable directories
86
+ }
87
+ const parent = path.dirname(current);
88
+ if (parent === current)
89
+ break; // reached filesystem root
90
+ current = parent;
91
+ }
92
+ return null;
93
+ }
94
+ /**
95
+ * Creates a .pisces marker in the given directory (default: cwd),
96
+ * marking it as a Pisces workspace root.
97
+ */
98
+ function createPiscesMarker(dir = process.cwd()) {
99
+ fs.writeFileSync(path.join(path.resolve(dir), exports.PISCES_MARKER), "");
100
+ }
101
+ /**
102
+ * Removes the .pisces marker from the given workspace root.
103
+ * Throws if the file does not exist.
104
+ */
105
+ function removePiscesMarker(workspaceRoot) {
106
+ fs.unlinkSync(path.join(path.resolve(workspaceRoot), exports.PISCES_MARKER));
107
+ }
108
+ //# sourceMappingURL=workspace.js.map
package/index.d.ts CHANGED
@@ -98,11 +98,13 @@ export declare function onLoad(): {
98
98
  /**
99
99
  * onStartup — called at the start of every Pi session.
100
100
  * Runs semester + folder detectors, builds greeting and context injection.
101
+ * Returns empty result silently when no .pisces workspace marker is found.
101
102
  */
102
103
  export declare function onStartup(state: SessionState): StartupResult;
103
104
  /**
104
105
  * onDirectoryChange — called when the user `cd`s to a new directory.
105
106
  * Re-runs context detectors so Pi stays accurate.
107
+ * Returns empty result silently when outside a .pisces workspace.
106
108
  */
107
109
  export declare function onDirectoryChange(state: SessionState): {
108
110
  contextInjection: string;
package/index.js CHANGED
@@ -70,6 +70,7 @@ const semester_detector_1 = require("./extensions/semester-detector");
70
70
  const folder_detector_1 = require("./extensions/folder-detector");
71
71
  const integrity_guard_1 = require("./extensions/integrity-guard");
72
72
  const progress_tracker_1 = require("./extensions/progress-tracker");
73
+ const workspace_1 = require("./extensions/workspace");
73
74
  // ─── Package Metadata ──────────────────────────────────────────────────────
74
75
  exports.PACKAGE_NAME = "pi-cs";
75
76
  exports.PACKAGE_VERSION = "0.1.0";
@@ -191,28 +192,27 @@ function onLoad() {
191
192
  /**
192
193
  * onStartup — called at the start of every Pi session.
193
194
  * Runs semester + folder detectors, builds greeting and context injection.
195
+ * Returns empty result silently when no .pisces workspace marker is found.
194
196
  */
195
197
  function onStartup(state) {
196
198
  const config = loadConfig();
199
+ if (!(0, workspace_1.findPiscesMarker)()) {
200
+ return { contextInjection: "", greeting: "", config };
201
+ }
197
202
  // Run semester detector
198
203
  const semesterResult = (0, semester_detector_1.run)();
199
204
  if (semesterResult) {
200
- // Extract context if found (greeting contains it serialised in comment blocks)
201
205
  const detection = (0, semester_detector_1.detectSemesterContext)();
202
206
  state.semesterContext = detection.context ?? null;
203
207
  }
204
208
  // Run folder detector
205
209
  const folderResult = (0, folder_detector_1.run)();
206
210
  state.folderContext = (0, folder_detector_1.detectFolderContext)();
207
- // Build the combined context injection block
208
211
  const contextParts = [];
209
- if (semesterResult.inject) {
212
+ if (semesterResult.inject)
210
213
  contextParts.push(semesterResult.inject);
211
- }
212
- if (folderResult.inject) {
214
+ if (folderResult.inject)
213
215
  contextParts.push(folderResult.inject);
214
- }
215
- // Inject config-derived hints
216
216
  contextParts.push(buildConfigInjection(config));
217
217
  return {
218
218
  contextInjection: contextParts.filter(Boolean).join("\n\n"),
@@ -223,20 +223,22 @@ function onStartup(state) {
223
223
  /**
224
224
  * onDirectoryChange — called when the user `cd`s to a new directory.
225
225
  * Re-runs context detectors so Pi stays accurate.
226
+ * Returns empty result silently when outside a .pisces workspace.
226
227
  */
227
228
  function onDirectoryChange(state) {
229
+ if (!(0, workspace_1.findPiscesMarker)()) {
230
+ return { contextInjection: "", message: null };
231
+ }
228
232
  const semesterResult = (0, semester_detector_1.run)();
229
233
  const folderResult = (0, folder_detector_1.run)();
230
234
  const newFolderContext = (0, folder_detector_1.detectFolderContext)();
231
235
  const previousProject = state.folderContext?.project?.name;
232
236
  const newProject = newFolderContext?.project?.name;
233
- // Update session state
234
237
  state.folderContext = newFolderContext;
235
238
  if ((0, semester_detector_1.detectSemesterContext)().context) {
236
239
  state.semesterContext = (0, semester_detector_1.detectSemesterContext)().context ?? null;
237
240
  }
238
241
  const contextParts = [semesterResult.inject, folderResult.inject].filter(Boolean);
239
- // Notify if we've moved into a different project
240
242
  const message = newProject && newProject !== previousProject
241
243
  ? `📂 Switched to project: **${newProject}** (${newFolderContext.project?.type ?? "unknown"})`
242
244
  : null;
package/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aethrekh/pi-cs",
3
- "version": "0.1.10",
3
+ "version": "0.2.0-alpha.0",
4
4
  "description": "Pisces — The CS Student Edition for Pi Coding Agent. Your personal AI teaching assistant from homework to thesis.",
5
5
  "keywords": [
6
6
  "academic",
@@ -32,6 +32,7 @@
32
32
  },
33
33
  "pi": {
34
34
  "extensions": [
35
+ "./extensions/workspace.js",
35
36
  "./extensions/semester-detector.js",
36
37
  "./extensions/folder-detector.js",
37
38
  "./extensions/integrity-guard.js",
package/pi-cs.meta.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "pi-cs",
3
- "version": "0.1.10",
4
- "built_at": "2026-06-05T11:13:41.394Z",
3
+ "version": "0.2.0-alpha.0",
4
+ "built_at": "2026-06-05T15:48:00.508Z",
5
5
  "entry": "index.js",
6
6
  "node_minimum": "18.0.0"
7
7
  }
package/pi-package.yaml CHANGED
@@ -1,5 +1,5 @@
1
1
  name: pi-cs
2
- version: 0.1.10
2
+ version: 0.2.0-alpha.0
3
3
  display_name: "pi-cs (Pisces)"
4
4
  description: "The CS Student Edition for Pi — Your personal AI teaching assistant for Computer Science, from homework to thesis."
5
5
  icon: public/pisces-logo-512.png
@@ -39,6 +39,11 @@ skills:
39
39
 
40
40
  # Extensions that run automatically in the background
41
41
  extensions:
42
+ - name: workspace
43
+ path: extensions/workspace.js
44
+ description: "Shared .pisces walk-up utility — required by all other extensions at runtime"
45
+ triggers:
46
+ - on_startup
42
47
  - name: semester-detector
43
48
  path: extensions/semester-detector.js
44
49
  description: "Auto-detects semester context from SEMESTER.md and folder structures"