@aethrekh/pi-cs 0.2.0-alpha.3 → 0.2.0-beta.1

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,42 +7,27 @@ 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.3](https://github.com/AshishBagdane/pi-cs/compare/v0.2.0-alpha.2...v0.2.0-alpha.3) (2026-06-05)
10
+ ## [0.2.0-beta.1](https://github.com/AshishBagdane/pi-cs/compare/v0.2.0-beta.0...v0.2.0-beta.1) (2026-06-06)
11
11
 
12
12
  ### ### Fixed
13
13
 
14
- * remove pi.skills from package.json so Pi doesn't load skills globally ([ada95e5](https://github.com/AshishBagdane/pi-cs/commit/ada95e5a5088fe38ad439f408092663e4cdf8090))
15
- * use ctx.cwd/event.cwd instead of process.cwd() in all extension handlers ([10f6d85](https://github.com/AshishBagdane/pi-cs/commit/10f6d853d58181a69efa5efc1d4b9de02b532c33))
14
+ * **pack:** include gatekeeper in published extensions and remove skills key ([dbae7be](https://github.com/AshishBagdane/pi-cs/commit/dbae7be7ac28293dfc09c87d0a257e4b88207909))
16
15
 
17
- ## [0.2.0-alpha.2](https://github.com/AshishBagdane/pi-cs/compare/v0.2.0-alpha.1...v0.2.0-alpha.2) (2026-06-05)
18
-
19
- ### ### Fixed
20
-
21
- * gate persona and skills to active Pisces workspaces ([3949f96](https://github.com/AshishBagdane/pi-cs/commit/3949f96f391306811c71e3290cb36eae3af14f42))
22
-
23
- ## [0.2.0-alpha.1](https://github.com/AshishBagdane/pi-cs/compare/v0.2.0-alpha.0...v0.2.0-alpha.1) (2026-06-05)
24
-
25
- ### ### Fixed
26
-
27
- * resolve package.json path for both pack and dev layouts in /pisces --version ([4cb59b5](https://github.com/AshishBagdane/pi-cs/commit/4cb59b5c80f80434c9931beddb6845c7b34d033e))
28
-
29
- ## [0.2.0-alpha.0](https://github.com/AshishBagdane/pi-cs/compare/v0.1.10...v0.2.0-alpha.0) (2026-06-05)
16
+ ## [0.2.0-beta.0](https://github.com/AshishBagdane/pi-cs/compare/v0.1.10...v0.2.0-beta.0) (2026-06-06)
30
17
 
31
18
  ### ### Added
32
19
 
33
- * implement workspace scoping via .pisces marker walk-up ([51444c1](https://github.com/AshishBagdane/pi-cs/commit/51444c19034047fbcd00111ce3ca2c30f7fb37c7))
20
+ * add workspace discovery and shared state modules ([4882f69](https://github.com/AshishBagdane/pi-cs/commit/4882f69f1d22ffe41d4861121b2a6a4c0fe5381e))
21
+ * workspace-scoped activation via .pisces marker file ([9deec2c](https://github.com/AshishBagdane/pi-cs/commit/9deec2c7ae9f03f9548c98934fe7c092af69d036))
34
22
 
35
23
  ### ### Fixed
36
24
 
37
- * clean up ~/.pi-cs/sessions.json on uninstall ([56d020a](https://github.com/AshishBagdane/pi-cs/commit/56d020aa319006b72299912ef43324c7747e0d4d))
38
- * register workspace.ts as a Pi extension so workspace.js is included in pack ([7f2546c](https://github.com/AshishBagdane/pi-cs/commit/7f2546ce50debcd5bda4a6da6ece9c482a13d861))
25
+ * **validate:** derive skill dirs from pi-package.yaml when pi.skills absent ([c3ebfa8](https://github.com/AshishBagdane/pi-cs/commit/c3ebfa8ca578f7dd3ca9f7ee54675a216ea31d2b))
39
26
 
40
27
  ### ### Changed
41
28
 
42
- * add workspace-scoping design document ([098504a](https://github.com/AshishBagdane/pi-cs/commit/098504a8262986def084c34a89d585a08e40531b))
43
29
  * align README and STUDENT_GUIDE with v0.1.10 install behaviour ([e8f6ae5](https://github.com/AshishBagdane/pi-cs/commit/e8f6ae5a9ed4ebd54409985e00d18b3356438255))
44
30
  * fix false local install scope claims and expand troubleshooting ([0e000f7](https://github.com/AshishBagdane/pi-cs/commit/0e000f7ac947fc641785ab46818649710d857265))
45
- * update README and STUDENT_GUIDE for workspace-scoped activation ([81e8872](https://github.com/AshishBagdane/pi-cs/commit/81e8872c024edb8c41cbc0d7b1fa85b10ddb16c9))
46
31
 
47
32
  ## [0.1.10](https://github.com/AshishBagdane/pi-cs/compare/v0.1.10-alpha.1...v0.1.10) (2026-06-05)
48
33
 
package/README.md CHANGED
@@ -15,6 +15,7 @@ It covers every dimension of a CS degree:
15
15
 
16
16
  | Need | Command | What it does |
17
17
  |---|---|---|
18
+ | Manage workspace activation | `/pisces` | Activate, deactivate, or check workspace status |
18
19
  | Set up semester context | `/semester` | Init, update, or inspect your `SEMESTER.md` context |
19
20
  | Stuck on an assignment | `/homework` | Hints, pseudocode, guided walkthrough — no cheating |
20
21
  | Starting a new project | `/project` | Requirements → architecture → scaffolded codebase |
@@ -29,23 +30,60 @@ It covers every dimension of a CS degree:
29
30
  ## Quick Start
30
31
 
31
32
  ```bash
32
- # Install Pisces globally (one-time setup)
33
+ # 1. Install Pisces globally (recommended for most students)
33
34
  pi install npm:@aethrekh/pi-cs
34
35
 
35
- # Mark your university folder as a Pisces workspace
36
+ # 2. Mark your university workspace (one-time setup)
36
37
  cd ~/university
38
+ pi
37
39
  /pisces --activate
38
40
 
39
- # Initialize your semester context
41
+ # 3. Initialize your semester context
40
42
  /semester --init
41
43
 
42
- # Start working — from any subdirectory
44
+ # 4. Start working
43
45
  /homework
44
46
  /explain binary search trees
45
47
  /leetcode 42
46
48
  ```
47
49
 
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.
50
+ After step 2, Pisces activates in `~/university` and all its subdirectories. Outside that workspace, Pi runs as stock — no skills, no persona.
51
+
52
+ ---
53
+
54
+ ## Workspace Activation
55
+
56
+ Pisces uses a `.pisces` marker file to decide where it is active. Outside a marked workspace Pi is completely silent — no skills load, no persona injects, no extensions run. Inside a workspace the full Pisces experience turns on.
57
+
58
+ ### Marking a workspace
59
+
60
+ ```bash
61
+ cd ~/university # navigate to your workspace root
62
+ /pisces --activate # creates .pisces here and reloads Pi
63
+ ```
64
+
65
+ ### How workspace discovery works
66
+
67
+ Pisces walks up the directory tree from where Pi was started, up to 15 levels, stopping at your home directory. This means you can start Pi from any subdirectory and Pisces will still find the marker:
68
+
69
+ ```
70
+ ~/university/ ← .pisces lives here
71
+ ├── fall2025/
72
+ │ └── CS301/
73
+ │ └── lab1/ ← start Pi here; Pisces walks up and activates
74
+ ```
75
+
76
+ ### Workspace commands
77
+
78
+ ```
79
+ /pisces --status # show whether the workspace is active and where .pisces was found
80
+ /pisces --activate # mark the current directory as a Pisces workspace
81
+ /pisces --deactivate # remove .pisces from the nearest workspace above cwd
82
+ ```
83
+
84
+ ### Switching workspace context
85
+
86
+ Pi's working directory is fixed at session start — there is no mid-session directory change mechanism in the Pi extension API. To switch workspace context, start a new Pi session (`/new` or restart Pi) from the target directory. `/pisces --status` always reflects the startup directory, not wherever you have `cd`'d during the session.
49
87
 
50
88
  ---
51
89
 
@@ -199,31 +237,26 @@ See [`config/schema.json`](config/schema.json) for the full configuration refere
199
237
  **Requirements:** Pi >= 0.78.0, Node.js >= 18
200
238
 
201
239
  ```bash
202
- # Step 1 Install globally (one command, once per machine)
240
+ # Recommendedinstalls Pisces globally
203
241
  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
242
  ```
212
243
 
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`
244
+ After a global install the gatekeeper extension loads in every Pi session, but **Pisces is silent by default** no skills, no persona, no extensions run until you activate a workspace with `/pisces --activate`. This means Pisces is available everywhere you want it without affecting non-university Pi sessions.
219
245
 
220
246
  ```bash
221
- # Local install — activates Pisces only in the exact install directory
247
+ # Local install — loads the extension only in the exact install directory
222
248
  cd ~/university
223
249
  pi install npm:@aethrekh/pi-cs -l
224
250
  ```
225
251
 
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.
252
+ With a local install, the extension itself only loads when Pi is started from `~/university` exactly — not from any subdirectory. Combined with workspace scoping, this offers the tightest possible containment, but requires you to always start Pi from that one root. Most students should use the global install.
253
+
254
+ | | Global | Local (`-l`) |
255
+ |---|---|---|
256
+ | Extension loads | In every Pi session | Only from exact install directory |
257
+ | Skills / persona active | Only inside a `.pisces` workspace | Only inside a `.pisces` workspace |
258
+ | Works from course subdirectories | Yes | No — exact directory only |
259
+ | Recommended | **Yes** | Edge case only |
227
260
 
228
261
  ---
229
262
 
@@ -244,11 +277,14 @@ pi-cs/
244
277
  │ │ ├── exam/SKILL.md # /exam skill
245
278
  │ │ └── research/SKILL.md # /research skill
246
279
  │ ├── extensions/
247
- │ │ ├── workspace.ts # .pisces walk-up detection (shared)
248
- │ │ ├── semester-detector.ts # Auto-loads SEMESTER.md
249
- │ │ ├── folder-detector.ts # Detects CS folder structures
250
- │ │ ├── integrity-guard.ts # Academic integrity monitoring
251
- │ │ └── progress-tracker.ts # Weekly stats & burnout nudges
280
+ │ │ ├── gatekeeper.ts # Workspace gating; /pisces command
281
+ │ │ ├── lib/
282
+ │ │ ├── workspace.ts # .pisces discovery (walks up 15 levels)
283
+ │ │ │ └── workspace-state.ts # Shared activation state across extensions
284
+ │ │ ├── semester-detector.ts # Auto-loads SEMESTER.md (workspace-gated)
285
+ │ │ ├── folder-detector.ts # Detects CS folder structures (workspace-gated)
286
+ │ │ ├── integrity-guard.ts # Academic integrity monitoring (workspace-gated)
287
+ │ │ └── progress-tracker.ts # Weekly stats & burnout nudges (workspace-gated)
252
288
  │ └── templates/
253
289
  │ └── semester-init.md # SEMESTER.md raw template
254
290
  ├── config/
@@ -267,7 +303,6 @@ pi-cs/
267
303
  - [x] 4 background extensions
268
304
  - [x] Semester context system
269
305
  - [x] Academic integrity guard
270
- - [x] Workspace-scoped activation (`.pisces` marker)
271
306
  - [ ] arXiv live search integration
272
307
  - [ ] Model routing presets
273
308
  - [ ] Obsidian vault sync
@@ -48,7 +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
+ const workspace_state_1 = require("./lib/workspace-state");
52
52
  // ─── Marker Files ──────────────────────────────────────────────────────────
53
53
  const PYTHON_MARKERS = ["requirements.txt", "pyproject.toml", "setup.py", "Pipfile"];
54
54
  const TS_MARKERS = ["package.json", "tsconfig.json"];
@@ -189,14 +189,17 @@ function summarizeFolderContext(result) {
189
189
  }
190
190
  // ─── Pi Extension Factory ──────────────────────────────────────────────────
191
191
  function default_1(pi) {
192
- pi.on("before_agent_start", async (event, ctx) => {
193
- // Re-check workspace on every agent turn — no closure state needed.
194
- if (!(0, workspace_1.findPiscesMarker)(ctx.cwd))
192
+ let contextSummary = "";
193
+ pi.on("session_start", async () => {
194
+ if (!(0, workspace_state_1.getWorkspaceState)().isActive)
195
195
  return;
196
- const summary = summarizeFolderContext(detectFolderContext());
197
- if (!summary)
196
+ const result = detectFolderContext();
197
+ contextSummary = summarizeFolderContext(result);
198
+ });
199
+ pi.on("before_agent_start", async (event) => {
200
+ if (!(0, workspace_state_1.getWorkspaceState)().isActive || !contextSummary)
198
201
  return;
199
- return { systemPrompt: `${event.systemPrompt}\n\n${summary}` };
202
+ return { systemPrompt: `${event.systemPrompt}\n\n${contextSummary}` };
200
203
  });
201
204
  }
202
205
  // ─── Pi Extension Entry Point ──────────────────────────────────────────────
@@ -0,0 +1,106 @@
1
+ "use strict";
2
+ /**
3
+ * gatekeeper.ts
4
+ *
5
+ * Extension: Workspace Gatekeeper
6
+ * Triggers: resources_discover
7
+ *
8
+ * Always loads. Has no academic content.
9
+ * Sole job: detect workspace state and gate all Pisces resources.
10
+ *
11
+ * Registers /pisces --activate | --deactivate | --status.
12
+ *
13
+ * Note: Pi's cwd is fixed at session startup — the extension context does not
14
+ * reflect mid-session directory changes. To switch workspace context, start Pi
15
+ * in the target directory or run /pisces --activate from within a new session.
16
+ */
17
+ Object.defineProperty(exports, "__esModule", { value: true });
18
+ exports.default = default_1;
19
+ const fs_1 = require("fs");
20
+ const path_1 = require("path");
21
+ const workspace_1 = require("./lib/workspace");
22
+ const workspace_state_1 = require("./lib/workspace-state");
23
+ function default_1(pi) {
24
+ // ─── Resource Gating ─────────────────────────────────────────────────────
25
+ // resources_discover fires before session_start and before skills are
26
+ // injected into the system prompt. Returning skillPaths: [] here is the
27
+ // only reliable way to suppress skills outside a workspace.
28
+ // Doubles as the authoritative initial sync of shared workspace state.
29
+ pi.on("resources_discover", async (event) => {
30
+ const { isActive } = (0, workspace_state_1.syncWorkspaceState)(event.cwd);
31
+ if (isActive) {
32
+ return {
33
+ skillPaths: [(0, path_1.resolve)(__dirname, "../skills")],
34
+ };
35
+ }
36
+ return { skillPaths: [] };
37
+ });
38
+ // ─── /pisces Command ─────────────────────────────────────────────────────
39
+ pi.registerCommand("pisces", {
40
+ description: "Manage Pisces workspace activation",
41
+ handler: async (args, ctx) => {
42
+ const flag = args?.trim();
43
+ // ── --activate ──────────────────────────────────────────────────────
44
+ if (flag === "--activate") {
45
+ const cwd = process.cwd();
46
+ (0, fs_1.writeFileSync)((0, path_1.join)(cwd, ".pisces"), "");
47
+ ctx.ui.notify(`Pisces workspace activated at ${cwd}`, "info");
48
+ await ctx.reload();
49
+ return;
50
+ }
51
+ // ── --deactivate ─────────────────────────────────────────────────────
52
+ if (flag === "--deactivate") {
53
+ const { isActive, root } = (0, workspace_1.findWorkspace)(process.cwd());
54
+ if (!isActive || !root) {
55
+ ctx.ui.notify("No active workspace found above this directory.", "warning");
56
+ return;
57
+ }
58
+ const confirmed = await ctx.ui.confirm("Deactivate workspace?", `Remove .pisces from ${root}?`);
59
+ if (!confirmed)
60
+ return;
61
+ (0, fs_1.unlinkSync)((0, path_1.join)(root, ".pisces"));
62
+ ctx.ui.notify([
63
+ `Workspace deactivated: ${root}`,
64
+ "",
65
+ "Skills are removed. The AI may still respond as Pisces for",
66
+ "the rest of this session due to conversation history.",
67
+ "Start a new session (/new) for a clean reset.",
68
+ ].join("\n"), "info");
69
+ await ctx.reload();
70
+ return;
71
+ }
72
+ // ── --status (default) ───────────────────────────────────────────────
73
+ if (flag === "--status" || !flag) {
74
+ const { isActive, root } = (0, workspace_1.findWorkspace)(process.cwd());
75
+ if (isActive && root) {
76
+ const cwd = process.cwd();
77
+ const depth = cwd
78
+ .replace(root, "")
79
+ .split("/")
80
+ .filter(Boolean).length;
81
+ ctx.ui.notify([
82
+ "Pisces Status",
83
+ "─────────────────────────────",
84
+ `Active: Yes`,
85
+ `Workspace root: ${root}`,
86
+ `.pisces found: ${depth} level${depth !== 1 ? "s" : ""} above cwd`,
87
+ ].join("\n"), "info");
88
+ }
89
+ else {
90
+ ctx.ui.notify([
91
+ "Pisces Status",
92
+ "─────────────────────────────",
93
+ `Active: No`,
94
+ `Reason: No .pisces found within 15 levels or above home directory`,
95
+ "",
96
+ `Run /pisces --activate to mark this directory as a workspace.`,
97
+ ].join("\n"), "info");
98
+ }
99
+ return;
100
+ }
101
+ // ── unknown flag ─────────────────────────────────────────────────────
102
+ ctx.ui.notify("Usage: /pisces --activate | --deactivate | --status", "warning");
103
+ },
104
+ });
105
+ }
106
+ //# sourceMappingURL=gatekeeper.js.map
@@ -12,7 +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
+ const workspace_state_1 = require("./lib/workspace-state");
16
16
  // ─── Risk Signals ──────────────────────────────────────────────────────────
17
17
  // High-risk: user is likely asking for submission-ready work
18
18
  const HIGH_RISK_PATTERNS = [
@@ -102,21 +102,11 @@ Just let me know!`;
102
102
  }
103
103
  // ─── Pi Extension Factory ──────────────────────────────────────────────────
104
104
  function default_1(pi) {
105
- let isActive = false;
106
105
  // Guard against sendUserMessage re-triggering this handler — warning text
107
106
  // contains words like "graded" that would otherwise match medium-risk patterns.
108
107
  let handlingWarning = false;
109
- pi.on("session_start", async (_event, ctx) => {
110
- isActive = (0, workspace_1.findPiscesMarker)(ctx.cwd) !== 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 (_event, ctx) => {
116
- isActive = (0, workspace_1.findPiscesMarker)(ctx.cwd) !== null;
117
- });
118
108
  pi.on("input", async (event) => {
119
- if (!isActive)
109
+ if (!(0, workspace_state_1.getWorkspaceState)().isActive)
120
110
  return { action: "continue" };
121
111
  if (handlingWarning)
122
112
  return { action: "continue" };
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getWorkspaceState = getWorkspaceState;
4
+ exports.syncWorkspaceState = syncWorkspaceState;
5
+ const workspace_1 = require("./workspace");
6
+ // Shared state owned by the gatekeeper, read by all extensions.
7
+ // Lazy-initialises on first read so tests that mock findWorkspace work
8
+ // without needing an explicit setup call.
9
+ let _state = null;
10
+ function getWorkspaceState() {
11
+ if (_state === null) {
12
+ _state = (0, workspace_1.findWorkspace)(process.cwd());
13
+ }
14
+ return _state;
15
+ }
16
+ function syncWorkspaceState(cwd) {
17
+ _state = (0, workspace_1.findWorkspace)(cwd);
18
+ return _state;
19
+ }
20
+ //# sourceMappingURL=workspace-state.js.map
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.findWorkspace = findWorkspace;
4
+ const fs_1 = require("fs");
5
+ const path_1 = require("path");
6
+ const os_1 = require("os");
7
+ /**
8
+ * Walks up from startCwd looking for a .pisces marker file.
9
+ * Stops at the home directory or filesystem root (whichever comes first).
10
+ * Caps at 15 levels to bound the cost — each check is a single synchronous stat.
11
+ */
12
+ function findWorkspace(startCwd) {
13
+ const home = (0, path_1.resolve)((0, os_1.homedir)());
14
+ let current = (0, path_1.resolve)(startCwd);
15
+ let depth = 0;
16
+ while (depth < 15) {
17
+ if (current === home || current.length < home.length)
18
+ break;
19
+ if (current === "/")
20
+ break;
21
+ if ((0, fs_1.existsSync)((0, path_1.join)(current, ".pisces"))) {
22
+ return { isActive: true, root: current };
23
+ }
24
+ const parent = (0, path_1.dirname)(current);
25
+ if (parent === current)
26
+ break;
27
+ current = parent;
28
+ depth++;
29
+ }
30
+ return { isActive: false, root: null };
31
+ }
32
+ //# sourceMappingURL=workspace.js.map
@@ -49,8 +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 semester_detector_1 = require("./semester-detector");
53
- const workspace_1 = require("./workspace");
52
+ const workspace_state_1 = require("./lib/workspace-state");
54
53
  // ─── Storage ───────────────────────────────────────────────────────────────
55
54
  const TRACKER_DIR = path.join(os.homedir(), ".pi-cs");
56
55
  const SESSIONS_FILE = path.join(TRACKER_DIR, "sessions.json");
@@ -162,14 +161,8 @@ function buildWeeklySummary(stats) {
162
161
  function default_1(pi) {
163
162
  const sessionStart = Date.now();
164
163
  const skillsUsed = [];
165
- let isActive = false;
166
- let workspaceRoot = null;
167
- pi.on("session_start", async (_event, ctx) => {
168
- workspaceRoot = (0, workspace_1.findPiscesMarker)(ctx.cwd);
169
- isActive = workspaceRoot !== null;
170
- });
171
164
  pi.on("input", async (event) => {
172
- if (!isActive)
165
+ if (!(0, workspace_state_1.getWorkspaceState)().isActive)
173
166
  return { action: "continue" };
174
167
  const match = event.text.match(/^\/skill:(\w+)/);
175
168
  if (match && !skillsUsed.includes(match[1])) {
@@ -178,10 +171,7 @@ function default_1(pi) {
178
171
  return { action: "continue" };
179
172
  });
180
173
  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)(ctx.cwd);
183
- isActive = workspaceRoot !== null;
184
- if (!isActive)
174
+ if (!(0, workspace_state_1.getWorkspaceState)().isActive)
185
175
  return;
186
176
  const elapsed = Math.round((Date.now() - sessionStart) / 60000);
187
177
  if (elapsed > 0 && elapsed % 180 === 0) {
@@ -189,7 +179,7 @@ function default_1(pi) {
189
179
  }
190
180
  });
191
181
  pi.on("session_shutdown", async (_event, ctx) => {
192
- if (!isActive)
182
+ if (!(0, workspace_state_1.getWorkspaceState)().isActive)
193
183
  return;
194
184
  const durationMinutes = Math.round((Date.now() - sessionStart) / 60000);
195
185
  const { nudge, weeklySummary } = run({ sessionDurationMinutes: durationMinutes, skillsUsed });
@@ -198,117 +188,6 @@ function default_1(pi) {
198
188
  if (weeklySummary)
199
189
  ctx.ui.notify(weeklySummary, "info");
200
190
  });
201
- pi.registerCommand("pisces", {
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
- `Reloading to register Pisces skills (/homework, /explain, etc.)...`,
223
- ].join("\n"), "info");
224
- await ctx.reload();
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\nReloading to unregister Pisces skills...`, "info");
243
- await ctx.reload();
244
- }
245
- catch (err) {
246
- ctx.ui.notify(`❌ Failed to remove ${workspace_1.PISCES_MARKER}: ${String(err)}`, "error");
247
- }
248
- return;
249
- }
250
- // ── /pisces --version ────────────────────────────────────────────────
251
- if (flag === "--version") {
252
- // Read version from package.json at runtime to stay in sync with releases
253
- let version = "unknown";
254
- // Pack layout: <install>/extensions/progress-tracker.js → ../package.json
255
- // Dev layout: src/extensions/progress-tracker.ts → ../../package.json
256
- const pkgCandidates = [
257
- path.resolve(__dirname, "../package.json"),
258
- path.resolve(__dirname, "../../package.json"),
259
- ];
260
- for (const p of pkgCandidates) {
261
- try {
262
- const pkg = JSON.parse(fs.readFileSync(p, "utf-8"));
263
- if (pkg.version) {
264
- version = pkg.version;
265
- break;
266
- }
267
- }
268
- catch { /* try next */ }
269
- }
270
- ctx.ui.notify(`🐠 pi-cs (Pisces) v${version}`, "info");
271
- return;
272
- }
273
- // ── /pisces --status (default) ───────────────────────────────────────
274
- const elapsed = Math.round((Date.now() - sessionStart) / 60000);
275
- if (!isActive) {
276
- ctx.ui.notify([
277
- "Pisces Status",
278
- "─────────────────────────────────────",
279
- "Active: ❌ No",
280
- `Reason: No ${workspace_1.PISCES_MARKER} found within search bounds (15 levels, ~)`,
281
- "",
282
- "Run /pisces --activate to mark this directory as a workspace root.",
283
- ].join("\n"), "info");
284
- return;
285
- }
286
- const detection = (0, semester_detector_1.detectSemesterContext)();
287
- const semCtx = detection.context;
288
- const lines = [
289
- "Pisces Status",
290
- "─────────────────────────────────────",
291
- "Active: ✅ Yes",
292
- `Workspace root: ${workspaceRoot}`,
293
- `Session: ${elapsed} minute${elapsed !== 1 ? "s" : ""}`,
294
- "",
295
- semCtx
296
- ? `Semester: ${semCtx.semester} ${semCtx.year}${semCtx.week ? ` — Week ${semCtx.week}` : ""}`
297
- : "Semester: ❌ No SEMESTER.md loaded — run /semester --init",
298
- semCtx?.courses?.length
299
- ? `Courses: ${semCtx.courses.map((c) => c.code).join(", ")}`
300
- : "",
301
- semCtx?.active_project ? `Project: ${semCtx.active_project}` : "",
302
- "",
303
- skillsUsed.length
304
- ? `Skills used: ${skillsUsed.map((s) => `/skill:${s}`).join(", ")}`
305
- : "No skills used yet — try /skill:explain, /skill:homework, or /skill:leetcode",
306
- ]
307
- .filter((l) => l !== undefined)
308
- .join("\n");
309
- ctx.ui.notify(lines, "info");
310
- },
311
- });
312
191
  }
313
192
  // ─── Pi Extension Entry Point ──────────────────────────────────────────────
314
193
  function run(context) {
@@ -49,7 +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
+ const workspace_state_1 = require("./lib/workspace-state");
53
53
  // ─── Search Paths ──────────────────────────────────────────────────────────
54
54
  function getSearchPaths() {
55
55
  return [
@@ -224,21 +224,12 @@ function removeLegacyGlobalPersona(persona) {
224
224
  function default_1(pi) {
225
225
  const persona = loadPersona();
226
226
  let semesterCtx = null;
227
- // Dynamically register skills only when a Pisces workspace is active.
228
- // Skills are absent outside a workspace — they never appear in the global command list.
229
- pi.on("resources_discover", async (event) => {
230
- if (!(0, workspace_1.findPiscesMarker)(event.cwd))
231
- return;
232
- // Relative path works for both pack (extensions/ → skills/) and dev (src/extensions/ → src/skills/) layouts
233
- const skillsDir = path.resolve(__dirname, "../skills");
234
- return fs.existsSync(skillsDir) ? { skillPaths: [skillsDir] } : undefined;
235
- });
236
227
  pi.on("session_start", async (_event, ctx) => {
237
- if (!(0, workspace_1.findPiscesMarker)(ctx.cwd))
238
- return;
239
228
  if (removeLegacyGlobalPersona(persona)) {
240
229
  ctx.ui.notify("🐠 Pisces: cleaned up a stale ~/.pi/agent/APPEND_SYSTEM.md from an older install. Persona is now session-scoped.", "info");
241
230
  }
231
+ if (!(0, workspace_state_1.getWorkspaceState)().isActive)
232
+ return;
242
233
  const result = detectSemesterContext();
243
234
  if (result.found && result.context) {
244
235
  semesterCtx = result.context;
@@ -249,18 +240,9 @@ function default_1(pi) {
249
240
  ctx.ui.notify("🐠 Pisces loaded — no SEMESTER.md found. Create one to enable context awareness.", "info");
250
241
  }
251
242
  });
252
- pi.on("before_agent_start", async (event, ctx) => {
253
- // Re-check workspace on every agent turn so mid-session activation/deactivation
254
- // is reflected without needing a session restart.
255
- if (!(0, workspace_1.findPiscesMarker)(ctx.cwd))
243
+ pi.on("before_agent_start", async (event) => {
244
+ if (!(0, workspace_state_1.getWorkspaceState)().isActive)
256
245
  return;
257
- // Lazy-load semester context if it was not available at session_start
258
- // (e.g. workspace was activated mid-session via /pisces --activate).
259
- if (!semesterCtx) {
260
- const result = detectSemesterContext();
261
- if (result.found && result.context)
262
- semesterCtx = result.context;
263
- }
264
246
  const parts = [];
265
247
  if (persona)
266
248
  parts.push(persona);
package/index.d.ts CHANGED
@@ -98,13 +98,11 @@ 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.
102
101
  */
103
102
  export declare function onStartup(state: SessionState): StartupResult;
104
103
  /**
105
104
  * onDirectoryChange — called when the user `cd`s to a new directory.
106
105
  * Re-runs context detectors so Pi stays accurate.
107
- * Returns empty result silently when outside a .pisces workspace.
108
106
  */
109
107
  export declare function onDirectoryChange(state: SessionState): {
110
108
  contextInjection: string;
package/index.js CHANGED
@@ -70,7 +70,6 @@ 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");
74
73
  // ─── Package Metadata ──────────────────────────────────────────────────────
75
74
  exports.PACKAGE_NAME = "pi-cs";
76
75
  exports.PACKAGE_VERSION = "0.1.0";
@@ -192,27 +191,28 @@ function onLoad() {
192
191
  /**
193
192
  * onStartup — called at the start of every Pi session.
194
193
  * Runs semester + folder detectors, builds greeting and context injection.
195
- * Returns empty result silently when no .pisces workspace marker is found.
196
194
  */
197
195
  function onStartup(state) {
198
196
  const config = loadConfig();
199
- if (!(0, workspace_1.findPiscesMarker)()) {
200
- return { contextInjection: "", greeting: "", config };
201
- }
202
197
  // Run semester detector
203
198
  const semesterResult = (0, semester_detector_1.run)();
204
199
  if (semesterResult) {
200
+ // Extract context if found (greeting contains it serialised in comment blocks)
205
201
  const detection = (0, semester_detector_1.detectSemesterContext)();
206
202
  state.semesterContext = detection.context ?? null;
207
203
  }
208
204
  // Run folder detector
209
205
  const folderResult = (0, folder_detector_1.run)();
210
206
  state.folderContext = (0, folder_detector_1.detectFolderContext)();
207
+ // Build the combined context injection block
211
208
  const contextParts = [];
212
- if (semesterResult.inject)
209
+ if (semesterResult.inject) {
213
210
  contextParts.push(semesterResult.inject);
214
- if (folderResult.inject)
211
+ }
212
+ if (folderResult.inject) {
215
213
  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,22 +223,20 @@ 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.
227
226
  */
228
227
  function onDirectoryChange(state) {
229
- if (!(0, workspace_1.findPiscesMarker)()) {
230
- return { contextInjection: "", message: null };
231
- }
232
228
  const semesterResult = (0, semester_detector_1.run)();
233
229
  const folderResult = (0, folder_detector_1.run)();
234
230
  const newFolderContext = (0, folder_detector_1.detectFolderContext)();
235
231
  const previousProject = state.folderContext?.project?.name;
236
232
  const newProject = newFolderContext?.project?.name;
233
+ // Update session state
237
234
  state.folderContext = newFolderContext;
238
235
  if ((0, semester_detector_1.detectSemesterContext)().context) {
239
236
  state.semesterContext = (0, semester_detector_1.detectSemesterContext)().context ?? null;
240
237
  }
241
238
  const contextParts = [semesterResult.inject, folderResult.inject].filter(Boolean);
239
+ // Notify if we've moved into a different project
242
240
  const message = newProject && newProject !== previousProject
243
241
  ? `📂 Switched to project: **${newProject}** (${newFolderContext.project?.type ?? "unknown"})`
244
242
  : null;
package/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;GAeG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgIH,gCA8BC;AAoCD,gDASC;AAQD,wBAsBC;AAOD,8BA4BC;AAOD,8CA+BC;AAMD,kCAoBC;AAMD,oCAgBC;AAMD,oCAmBC;AA2DD,4DAIC;AAKD,0DAIC;AAKD,oCAEC;AAMD,4BAWC;AAzdD,2CAA6B;AAC7B,uCAAyB;AACzB,uCAAyB;AAEzB,8EAA8E;AAE9E,sEAIwC;AAExC,kEAIsC;AAEtC,kEAEsC;AAEtC,oEAEuC;AAEvC,sDAA0D;AAoE1D,8EAA8E;AAEjE,QAAA,YAAY,GAAG,OAAO,CAAC;AACvB,QAAA,eAAe,GAAG,OAAO,CAAC;AAC1B,QAAA,MAAM,GAAG;IACpB,UAAU;IACV,SAAS;IACT,QAAQ;IACR,SAAS;IACT,UAAU;IACV,MAAM;IACN,UAAU;CACF,CAAC;AAIX,8EAA8E;AAE9E,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,yBAAyB,CAAC,CAAC;AAEtE,SAAS,oBAAoB;IAC3B,OAAO;QACL,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,aAAa,CAAC;QACvC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,YAAY,CAAC;QAC5C,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,OAAO,EAAE,aAAa,CAAC;KAC3D,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,SAAgB,UAAU;IACxB,IAAI,QAAQ,GAAe,EAAE,CAAC;IAE9B,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC;QACpD,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAe,CAAC;IAC3C,CAAC;IAAC,MAAM,CAAC;QACP,oDAAoD;QACpD,QAAQ,GAAG;YACT,YAAY,EAAE,EAAE,aAAa,EAAE,cAAc,EAAE,cAAc,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE;YAC1F,IAAI,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE,yBAAyB,EAAE,IAAI,EAAE,oBAAoB,EAAE,KAAK,EAAE;YACzF,SAAS,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,UAAU,EAAE;YACpD,YAAY,EAAE,EAAE,cAAc,EAAE,IAAI,EAAE,uBAAuB,EAAE,GAAG,EAAE,cAAc,EAAE,IAAI,EAAE;SAC3F,CAAC;IACJ,CAAC;IAED,oDAAoD;IACpD,KAAK,MAAM,UAAU,IAAI,oBAAoB,EAAE,EAAE,CAAC;QAChD,IAAI,CAAC;YACH,IAAI,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;gBAC9B,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;gBACjD,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAe,CAAC;gBACjD,OAAO,SAAS,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;YACzC,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,SAAS;QACX,CAAC;IACH,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;GAEG;AACH,SAAS,SAAS,CAAmB,IAAO,EAAE,QAAoB;IAChE,MAAM,MAAM,GAAG,EAAE,GAAG,IAAI,EAAE,CAAC;IAE3B,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAgB,EAAE,CAAC;QACvD,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC;QAC1B,MAAM,WAAW,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC;QAElC,IACE,WAAW,KAAK,IAAI;YACpB,OAAO,WAAW,KAAK,QAAQ;YAC/B,CAAC,KAAK,CAAC,OAAO,CAAC,WAAW,CAAC;YAC3B,OAAO,OAAO,KAAK,QAAQ;YAC3B,OAAO,KAAK,IAAI,EAChB,CAAC;YACD,MAAM,CAAC,GAAG,CAAC,GAAG,SAAS,CACrB,OAAkC,EAClC,WAAsC,CACzB,CAAC;QAClB,CAAC;aAAM,IAAI,WAAW,KAAK,SAAS,EAAE,CAAC;YACrC,MAAM,CAAC,GAAG,CAAC,GAAG,WAAyB,CAAC;QAC1C,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,8EAA8E;AAE9E;;GAEG;AACH,SAAgB,kBAAkB;IAChC,OAAO;QACL,SAAS,EAAE,IAAI,IAAI,EAAE;QACrB,UAAU,EAAE,EAAE;QACd,YAAY,EAAE,EAAE;QAChB,eAAe,EAAE,IAAI;QACrB,aAAa,EAAE,IAAI;QACnB,eAAe,EAAE,IAAI;KACtB,CAAC;AACJ,CAAC;AAED,+EAA+E;AAE/E;;;GAGG;AACH,SAAgB,MAAM;IACpB,MAAM,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC;IACpC,MAAM,KAAK,GAAG,QAAQ,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAE/D,IAAI,KAAK,GAAG,EAAE,EAAE,CAAC;QACf,OAAO;YACL,EAAE,EAAE,KAAK;YACT,OAAO,EAAE,0CAA0C,WAAW,mBAAmB;SAClF,CAAC;IACJ,CAAC;IAED,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAC5B,MAAM,YAAY,GAAG,oBAAoB,EAAE,CAAC,IAAI,CAAC,CAAC,CAAS,EAAE,EAAE;QAC7D,IAAI,CAAC;YAAC,OAAO,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;QAAC,CAAC;QAAC,MAAM,CAAC;YAAC,OAAO,KAAK,CAAC;QAAC,CAAC;IAC1D,CAAC,CAAC,IAAI,UAAU,CAAC;IAEjB,OAAO;QACL,EAAE,EAAE,IAAI;QACR,OAAO,EAAE,SAAS,uBAAe,oBAAoB,YAAY,sBAC/D,MAAM,CAAC,SAAS,EAAE,OAAO,KAAK,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAC/C,GAAG;KACJ,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,SAAgB,SAAS,CAAC,KAAmB;IAC3C,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAE5B,IAAI,CAAC,IAAA,4BAAgB,GAAE,EAAE,CAAC;QACxB,OAAO,EAAE,gBAAgB,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC;IACxD,CAAC;IAED,wBAAwB;IACxB,MAAM,cAAc,GAAG,IAAA,uBAAmB,GAAE,CAAC;IAC7C,IAAI,cAAc,EAAE,CAAC;QACnB,MAAM,SAAS,GAAG,IAAA,yCAAqB,GAAE,CAAC;QAC1C,KAAK,CAAC,eAAe,GAAG,SAAS,CAAC,OAAO,IAAI,IAAI,CAAC;IACpD,CAAC;IAED,sBAAsB;IACtB,MAAM,YAAY,GAAG,IAAA,qBAAiB,GAAE,CAAC;IACzC,KAAK,CAAC,aAAa,GAAG,IAAA,qCAAmB,GAAE,CAAC;IAE5C,MAAM,YAAY,GAAa,EAAE,CAAC;IAClC,IAAI,cAAc,CAAC,MAAM;QAAE,YAAY,CAAC,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;IACpE,IAAI,YAAY,CAAC,MAAM;QAAE,YAAY,CAAC,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;IAChE,YAAY,CAAC,IAAI,CAAC,oBAAoB,CAAC,MAAM,CAAC,CAAC,CAAC;IAEhD,OAAO;QACL,gBAAgB,EAAE,YAAY,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC;QAC3D,QAAQ,EAAE,cAAc,CAAC,QAAQ;QACjC,MAAM;KACP,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,SAAgB,iBAAiB,CAAC,KAAmB;IAInD,IAAI,CAAC,IAAA,4BAAgB,GAAE,EAAE,CAAC;QACxB,OAAO,EAAE,gBAAgB,EAAE,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IACjD,CAAC;IAED,MAAM,cAAc,GAAG,IAAA,uBAAmB,GAAE,CAAC;IAC7C,MAAM,YAAY,GAAG,IAAA,qBAAiB,GAAE,CAAC;IACzC,MAAM,gBAAgB,GAAG,IAAA,qCAAmB,GAAE,CAAC;IAE/C,MAAM,eAAe,GAAG,KAAK,CAAC,aAAa,EAAE,OAAO,EAAE,IAAI,CAAC;IAC3D,MAAM,UAAU,GAAG,gBAAgB,EAAE,OAAO,EAAE,IAAI,CAAC;IAEnD,KAAK,CAAC,aAAa,GAAG,gBAAgB,CAAC;IACvC,IAAI,IAAA,yCAAqB,GAAE,CAAC,OAAO,EAAE,CAAC;QACpC,KAAK,CAAC,eAAe,GAAG,IAAA,yCAAqB,GAAE,CAAC,OAAO,IAAI,IAAI,CAAC;IAClE,CAAC;IAED,MAAM,YAAY,GAAG,CAAC,cAAc,CAAC,MAAM,EAAE,YAAY,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAElF,MAAM,OAAO,GACX,UAAU,IAAI,UAAU,KAAK,eAAe;QAC1C,CAAC,CAAC,6BAA6B,UAAU,OAAO,gBAAgB,CAAC,OAAO,EAAE,IAAI,IAAI,SAAS,GAAG;QAC9F,CAAC,CAAC,IAAI,CAAC;IAEX,OAAO;QACL,gBAAgB,EAAE,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC;QAC3C,OAAO;KACR,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,SAAgB,WAAW,CAAC,OAAyB;IACnD,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,YAAY,EAAE,GAAG,OAAO,CAAC;IACvD,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAE5B,qBAAqB;IACrB,IAAI,CAAC,YAAY,CAAC,UAAU,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;QACjD,YAAY,CAAC,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAC1C,CAAC;IAED,6CAA6C;IAC7C,IAAI,MAAM,CAAC,SAAS,EAAE,OAAO,KAAK,KAAK,EAAE,CAAC;QACxC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC;IAC1C,CAAC;IAED,MAAM,WAAW,GAAG,IAAA,qBAAiB,EAAC,EAAE,SAAS,EAAE,SAAS,EAAE,CAAC,CAAC;IAEhE,OAAO;QACL,OAAO,EAAE,IAAI,EAAE,gDAAgD;QAC/D,SAAS,EAAE,WAAW,CAAC,MAAM;KAC9B,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,SAAgB,YAAY,CAAC,KAAmB;IAC9C,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAC5B,MAAM,eAAe,GAAG,IAAI,CAAC,KAAK,CAChC,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,SAAS,CAAC,OAAO,EAAE,CAAC,GAAG,KAAM,CAClD,CAAC;IAEF,MAAM,aAAa,GAAG,IAAA,sBAAkB,EAAC;QACvC,sBAAsB,EAAE,eAAe;QACvC,UAAU,EAAE,KAAK,CAAC,UAAU;QAC5B,YAAY,EAAE,KAAK,CAAC,YAAY;KACjC,CAAC,CAAC;IAEH,OAAO;QACL,KAAK,EAAE,MAAM,CAAC,YAAY,EAAE,cAAc,KAAK,KAAK,CAAC,CAAC,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI;QACjF,OAAO,EAAE,MAAM,CAAC,YAAY,EAAE,cAAc,KAAK,KAAK,CAAC,CAAC,CAAC,aAAa,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI;KAC5F,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,SAAgB,YAAY,CAAC,KAAmB;IAC9C,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAC5B,MAAM,MAAM,GAAG,MAAM,CAAC,YAAY,EAAE,uBAAuB,IAAI,GAAG,CAAC;IAEnE,IAAI,CAAC,MAAM,CAAC,YAAY,EAAE,cAAc;QAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IAEnE,MAAM,cAAc,GAAG,IAAI,CAAC,KAAK,CAC/B,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,SAAS,CAAC,OAAO,EAAE,CAAC,GAAG,KAAM,CAClD,CAAC;IAEF,0CAA0C;IAC1C,IAAI,cAAc,IAAI,MAAM,IAAI,KAAK,CAAC,eAAe,KAAK,IAAI,EAAE,CAAC;QAC/D,KAAK,CAAC,eAAe,GAAG,cAAc,CAAC;QACvC,OAAO;YACL,OAAO,EAAE,8BAA8B,cAAc,+DAA+D;SACrH,CAAC;IACJ,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;AAC3B,CAAC;AAED,8EAA8E;AAE9E;;;GAGG;AACH,SAAS,oBAAoB,CAAC,MAAkB;IAC9C,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,IAAI,MAAM,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC;QACzB,KAAK,CAAC,IAAI,CAAC,iBAAiB,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;IACrD,CAAC;IAED,IAAI,MAAM,CAAC,OAAO,EAAE,aAAa,EAAE,CAAC;QAClC,MAAM,UAAU,GAA2B;YACzC,CAAC,EAAE,qBAAqB;YACxB,CAAC,EAAE,sBAAsB;YACzB,CAAC,EAAE,mBAAmB;YACtB,CAAC,EAAE,mBAAmB;YACtB,CAAC,EAAE,qBAAqB;YACxB,CAAC,EAAE,sBAAsB;SAC1B,CAAC;QACF,KAAK,CAAC,IAAI,CACR,kBAAkB,UAAU,CAAC,MAAM,CAAC,OAAO,CAAC,aAAa,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,aAAa,EAAE,CAC7F,CAAC;IACJ,CAAC;IAED,IAAI,MAAM,CAAC,OAAO,EAAE,gBAAgB,EAAE,CAAC;QACrC,KAAK,CAAC,IAAI,CAAC,qBAAqB,MAAM,CAAC,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAAC;IACrE,CAAC;IAED,IAAI,MAAM,CAAC,YAAY,EAAE,aAAa,EAAE,CAAC;QACvC,KAAK,CAAC,IAAI,CAAC,iCAAiC,MAAM,CAAC,YAAY,CAAC,aAAa,EAAE,CAAC,CAAC;IACnF,CAAC;IAED,IAAI,MAAM,CAAC,IAAI,EAAE,yBAAyB,EAAE,CAAC;QAC3C,KAAK,CAAC,IAAI,CAAC,iDAAiD,CAAC,CAAC;IAChE,CAAC;IAED,IAAI,MAAM,CAAC,IAAI,EAAE,oBAAoB,EAAE,CAAC;QACtC,KAAK,CAAC,IAAI,CAAC,0CAA0C,CAAC,CAAC;IACzD,CAAC;IAED,IAAI,CAAC,KAAK,CAAC,MAAM;QAAE,OAAO,EAAE,CAAC;IAE7B,OAAO;QACL,kCAAkC;QAClC,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC;KACrC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC;AAED,8EAA8E;AAE9E;;;GAGG;AACH,SAAgB,wBAAwB,CACtC,KAAmB;IAEnB,OAAO,KAAK,CAAC,eAAe,CAAC;AAC/B,CAAC;AAED;;GAEG;AACH,SAAgB,uBAAuB,CACrC,KAAmB;IAEnB,OAAO,KAAK,CAAC,aAAa,EAAE,OAAO,IAAI,IAAI,CAAC;AAC9C,CAAC;AAED;;GAEG;AACH,SAAgB,YAAY,CAAC,IAAY;IACvC,OAAQ,cAA4B,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;AACtD,CAAC;AAED;;;GAGG;AACH,SAAgB,QAAQ;IACtB,OAAO;QACL,sBAAsB,uBAAe,EAAE;QACvC,+CAA+C;QAC/C,EAAE;QACF,mBAAmB,cAAM,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE;QACvC,sFAAsF;QACtF,iCAAiC;QACjC,EAAE;QACF,yEAAyE;KAC1E,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC"}
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.2.0-alpha.3",
3
+ "version": "0.2.0-beta.1",
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,7 +32,7 @@
32
32
  },
33
33
  "pi": {
34
34
  "extensions": [
35
- "./extensions/workspace.js",
35
+ "./extensions/gatekeeper.js",
36
36
  "./extensions/semester-detector.js",
37
37
  "./extensions/folder-detector.js",
38
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.2.0-alpha.3",
4
- "built_at": "2026-06-05T17:49:06.388Z",
3
+ "version": "0.2.0-beta.1",
4
+ "built_at": "2026-06-06T09:28:24.401Z",
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.2.0-alpha.3
2
+ version: 0.2.0-beta.1
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
@@ -7,13 +7,43 @@ author: ""
7
7
  license: MIT
8
8
  pi_version: ">=1.0.0"
9
9
 
10
+ # Core system prompt that defines the academic persona
11
+ system: SYSTEM.md
12
+
13
+ # Skills (slash commands) registered by this package
14
+ skills:
15
+ - name: homework
16
+ path: skills/homework/SKILL.md
17
+ description: "Break down problems, provide guided hints, and walk through step-by-step implementation"
18
+ - name: project
19
+ path: skills/project/SKILL.md
20
+ description: "Full project kickoff: requirements → architecture → tech stack → scaffolding"
21
+ - name: review
22
+ path: skills/review/SKILL.md
23
+ description: "Strict TA-level code review covering style, efficiency, edge cases, and security"
24
+ - name: explain
25
+ path: skills/explain/SKILL.md
26
+ description: "Concept explanations with analogies, Mermaid diagrams, and connections to prior knowledge"
27
+ - name: leetcode
28
+ path: skills/leetcode/SKILL.md
29
+ description: "Problem parsing, optimized solutions with time/space complexity analysis"
30
+ - name: exam
31
+ path: skills/exam/SKILL.md
32
+ description: "Practice questions, mind maps, and revision plans for upcoming exams"
33
+ - name: research
34
+ path: skills/research/SKILL.md
35
+ description: "Paper summarization, arXiv search, and literature review assistance"
36
+ - name: semester
37
+ path: skills/semester/SKILL.md
38
+ description: "Manage semester context: scaffold a new SEMESTER.md (--init), update fields (--update), or inspect what Pisces detects (--status)"
39
+
10
40
  # Extensions that run automatically in the background
11
41
  extensions:
12
- - name: workspace
13
- path: extensions/workspace.js
14
- description: "Shared .pisces walk-up utility required by all other extensions at runtime"
42
+ - name: gatekeeper
43
+ path: extensions/gatekeeper.js
44
+ description: "Gates all Pisces resources behind .pisces workspace marker; manages /pisces command"
15
45
  triggers:
16
- - on_startup
46
+ - resources_discover
17
47
  - name: semester-detector
18
48
  path: extensions/semester-detector.js
19
49
  description: "Auto-detects semester context from SEMESTER.md and folder structures"
@@ -1,108 +0,0 @@
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