@aethrekh/pisces-core

Pisces Core — domain-agnostic learning engine for Pi Coding Agent

Packages

Package details

extension

Install @aethrekh/pisces-core from npm and Pi will load the resources declared by the package manifest.

$ pi install npm:@aethrekh/pisces-core
Package
@aethrekh/pisces-core
Version
0.3.0-beta.0
Published
Aug 21, 2026
Downloads
848/mo · 84/wk
Author
aethrekh
License
UNLICENSED
Types
extension
Size
1.4 MB
Dependencies
0 dependencies · 2 peers
Pi manifest JSON
{
  "extensions": [
    "./src/extensions/workspace-gate.ts",
    "./src/attempt-capture.ts",
    "./src/extensions/integrity-guard.ts",
    "./src/extensions/progress-tracker.ts",
    "./src/extensions/input-revamp.ts"
  ]
}

Security note

Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.

README

@aethrekh/pisces-core

Domain-agnostic learning engine for Pi Coding Agent. Provides rubric-driven evaluation, integrity enforcement, attempt history, and a teaching persona that adapts to any subject — not just CS.

This package is the foundation. Domain packages (pisces-cs, pisces-sysdesign, etc.) sit on top of it, contributing subject-specific rubrics without modifying the engine itself.


What it does

Capability How
Teaching persona SYSTEM.md injected as the Pisces AI identity on every session
Workspace gating Skills and themes only activate inside a .pisces-marked directory
Attempt evaluation /attempt command feeds submitted work + rubric + gap history to the model
Integrity enforcement on_input extension blocks code-generation requests during graded evaluations
Gap memory Attempt history persists across sessions; recurring weaknesses surface automatically
Burnout nudges Session length tracking with configurable break reminders
Custom input bar Replaces Pi's default prompt with a framed bar showing workspace state and session cost

Installation

pi install npm:@aethrekh/pisces-core

Alternatively, for local development:

pi install /path/to/packages/core

The postinstall script copies SYSTEM.md to ~/.pi/agent/APPEND_SYSTEM.md (persona injection) and installs the pisces-editorial-noir theme to ~/.pi/agent/themes/.


Quick start

# 1. Install (or add to local Pi settings)
pi install npm:@aethrekh/pisces-core
pi install npm:@aethrekh/pisces-cli   # workspace commands (/pisces)

# 2. Navigate to your workspace and activate
cd ~/my-project
pi
/pisces --activate

# 3. Submit work for evaluation
/attempt function twoSum(nums, target) { ... }

Workspace activation

Skills and the /attempt command are off by default. They activate only when Pi is started from a directory that has a .pisces marker file at or above it.

~/my-project/           ← .pisces lives here
├── module-1/
│   └── lab1/           ← start Pi here; workspace-gate walks up and activates
└── module-2/

Workspace state is detected once at resources_discover (before session start) and cached for the session. Pi's working directory is fixed at startup — a mid-session cd does not re-trigger detection.

Use @aethrekh/pisces-cli for the /pisces command that creates and removes .pisces markers.


/attempt command

The primary user-facing command. Submits work to the model for rubric-driven evaluation.

/attempt <your code or text>
/attempt --type essay <your text>
/attempt --goal "implement binary search" <your code>

Flags:

Flag Description
--type code|essay|generic Override the inferred attempt type (inferred from content by default)
--goal "description" Describe what you were trying to achieve (stored in attempt history)

What happens:

  1. Workspace state is checked — redirects to /pisces --activate if no .pisces found.
  2. The active rubric is loaded from .pisces/rubric.json (domain rubric) or the built-in generic-attempt rubric.
  3. Recent gap history is fetched from ~/.pisces/attempt-history.json.
  4. Rubric + gaps + submitted content are injected into the conversation.
  5. The model evaluates and scores against the rubric criteria.
  6. The attempt record (without the score — scoring is model-side) is written to history.

Rubric resolution

The calibration engine searches for a rubric in this order:

Priority Path Source
1 .pisces/rubric.json (workspace-relative) Dropped by a domain package on activation
2 Built-in generic-attempt/rubric.json Bundled with pisces-core

When no domain rubric is present, the built-in five-criterion rubric is used:

Criterion Weight
Functional Correctness & Robustness 30%
Conceptual Understanding 25%
Code Quality & Readability 20%
Design, Modularity & Algorithms 15%
Documentation & Reflection 10%

Extensions

Five extensions run automatically. All are gated behind workspace activation except where noted.

workspace-gateresources_discover

Controls which skill and theme paths Pi discovers at session start. Returns skillPaths pointing at the bundled skills directory only when a .pisces marker is found. This is the sole gating mechanism — no .pisces, no skills.

attempt-capturesession_start

Registers the /attempt Pi command. See the command section above.

integrity-guardon_input

Monitors every message for academic integrity risk. Two guard layers:

  1. General patterns — phrases like "write the complete solution for my assignment" or "do my homework" trigger a redirect to guided-learning mode.
  2. Graded-skill routing — within a gradedSkills session (e.g. immediately after /attempt), code-generation requests like "fix this" or "rewrite this" are blocked.

Risk levels: nonelowmediumhigh. Only high produces a hard redirect; lower levels inject a warning comment into the context.

The active safeSkills and gradedSkills lists come from the loaded RubricSpec.integrityProfile. Domain packages can override these via setIntegrityProfile().

progress-trackeron_session_end

Tracks session duration and skill usage. At session end:

  • If productivity.burnout_nudges is enabled and the session exceeded session_warning_minutes, surfaces a break reminder.
  • If productivity.weekly_summary is enabled, shows a compact weekly activity table.

input-revampsession_start

Replaces Pi's default input bar with a framed prompt bar:

╭─ 🐠 Pisces · active ────────────────────────── 5.2% · $0.015 · 8.3K out ─╮
│ › your message here                                                         │
╰──────────────────────────────────────────────── T3 · $0.008 · OUT 4.1K ───╯

Features: typing-speed whitening on the border, animated thinking VU-meter, submit flash, real-time session cost and token count.


Configuration

Config is loaded via a priority chain — first match wins:

  1. .pisces.json in the current working directory
  2. ~/.pi/pisces.json
  3. ~/.config/pisces/config.json
  4. Built-in defaults
{
  "student": {
    "name": "Alex",
    "year_of_study": 2,
    "timezone": "America/New_York"
  },
  "explanations": {
    "default_depth": "intermediate",
    "prefer_visuals": true,
    "use_analogies": true
  },
  "integrity": {
    "enabled": true,
    "strictness": "balanced"
  },
  "productivity": {
    "burnout_nudges": true,
    "session_warning_minutes": 180,
    "weekly_summary": true
  }
}

Full schema: config/schema.json

Defaults: config/defaults.json

Config fields

student

Field Type Default Description
name string First name for personalised greetings
year_of_study integer (1–8) 1 Year of study for depth calibration
timezone string Timezone string, e.g. America/New_York

explanations

Field Type Default Description
default_depth beginner|intermediate|advanced intermediate Explanation depth when not specified
prefer_visuals boolean true Prefer diagrams for structural concepts
use_analogies boolean true Include real-world analogies

integrity

Field Type Default Description
enabled boolean true Enable the integrity guard
strictness strict|balanced|relaxed balanced Aggressiveness of integrity pattern matching

productivity

Field Type Default Description
burnout_nudges boolean true Show break reminders after long sessions
session_warning_minutes integer 180 Minutes before a break reminder appears
weekly_summary boolean true Show a weekly activity table at session end

Attempt history

Attempt records are stored in ~/.pisces/attempt-history.json. The file is capped at 200 records (oldest pruned first). Each record:

{
  "id": "m5ix2kfz9",
  "timestamp": "2026-07-03T10:22:00.000Z",
  "skillName": "attempt",
  "attemptType": "code",
  "goal": "implement binary search tree",
  "gaps": [],
  "strengths": [],
  "score": null
}

The gaps and strengths arrays are populated after the model evaluates the attempt. On subsequent /attempt invocations, a compact deduplicated summary of unresolved gaps is injected into the conversation so the model can check for recurring weaknesses.


Public API (for domain packages)

@aethrekh/pisces-core exports the following for use by domain packages and pisces-cli:

import {
  // Workspace detection
  findWorkspace,       // (cwd: string) => WorkspaceResult
  getWorkspaceState,   // () => WorkspaceResult  (cached singleton)
  syncWorkspaceState,  // (cwd: string) => WorkspaceResult  (update cache)

  // Config
  loadConfig,          // () => PiscesConfig
  deepMerge,           // (base, override) => merged config
  getConfigSearchPaths, // () => string[]

  // Lifecycle hooks (for custom integrations)
  onLoad,
  onStartup,
  onDirectoryChange,
  onSkillCall,
  onMidSession,
  onSessionEnd,
  createSessionState,

  // Metadata
  PACKAGE_VERSION,
  SKILLS,
  isValidSkill,
} from "@aethrekh/pisces-core";

For domain package authors

A domain package extends Pisces Core by:

  1. Providing a rubric — ship a rubric.json validated against @aethrekh/rubric-schema. On workspace activation, write it to .pisces/rubric.json in the learner's workspace root.
  2. Registering its skills — declare additional skills in pi-package.yaml. Skills are gated by workspace-gate.ts automatically via resources_discover.
  3. Optionally setting the integrity profile — call setIntegrityProfile({ safeSkills, gradedSkills }) from pisces-core/integrity-guard to override the default routing rules.

Pisces Core resolves the domain rubric at /attempt time with no further configuration needed.


Package scripts

pnpm build            # Compile src/ → dist/ and scripts/ → dist/scripts/
pnpm test             # Run Jest test suite
pnpm test:coverage    # With coverage (70% branch / 80% line thresholds)
pnpm typecheck        # Type-check without emit
pnpm lint             # ESLint over src/ and scripts/
pnpm check            # typecheck + lint + test:coverage (CI gate)
pnpm validate         # Validate package.json, pi-package.yaml, and skill frontmatter
pnpm pack             # Bundle into dist/pack/ and dist/*.tar.gz
pnpm release          # Cut a release: bump version, update CHANGELOG, tag, pack

Architecture

packages/core/
├── SYSTEM.md                        # Pisces teaching persona (Pi system prompt)
├── pi-package.yaml                  # Pi runtime manifest
├── config/
│   ├── schema.json                  # Config schema
│   └── defaults.json                # Default values
└── src/
    ├── index.ts                     # Public API + lifecycle hooks
    ├── pi-adapter.ts                # Isolation layer for all Pi SDK calls
    ├── workspace-detector.ts        # .pisces discovery + singleton cache
    ├── attempt-capture.ts           # /attempt Pi command
    ├── calibration-engine.ts        # Rubric loading + feedback context builder
    ├── correction-memory.ts         # Attempt history read/write
    ├── memory-policy.ts             # Write/inject validation (anti-softening)
    ├── postinstall.ts               # Copies SYSTEM.md + theme on install
    ├── extensions/
    │   ├── workspace-gate.ts        # resources_discover gating
    │   ├── integrity-guard.ts       # on_input pattern matching
    │   ├── progress-tracker.ts      # on_session_end burnout nudges
    │   ├── input-revamp.ts          # session_start custom input bar
    │   └── lib/
    │       ├── config.ts            # Config loader (deepMerge, search paths)
    │       └── ui.ts                # Shared UI primitives (row, sep, skillsList)
    ├── skills/
    │   └── generic-attempt/
    │       ├── SKILL.md             # Evaluation mode prompt
    │       └── rubric.json          # Built-in 5-criterion rubric
    └── themes/
        └── pisces-editorial-noir.json

License

MIT