Phase 1 Specification and Invariants
Relevant Source Files
This page summarizes the foundational specifications, architectural requirements, and safety invariants established for Phase 1 of the PALEE (Personal Active Learning & Evaluation Engine) CLI. Phase 1 focuses on a deterministic, AI-free core that handles storage, spaced repetition, and dependency management with high reliability.
1. Solution Architecture
PALEE is designed with a strict separation of concerns, ensuring that the engine remains deterministic and reliable even when AI features are added in later phases planning/palee_cli_spec.md
1.1 Architectural Layers
| Layer | Responsibility | Key Files |
|---|---|---|
| Storage | Obsidian vault as source of truth, atomic writes, and locking. | src/storage/ |
| Engine Core | Pure library for SM-2, mastery, and dependency graphs. | src/engine/ |
| Tool Interface | Validated mutation contract for state changes. | src/types.ts |
| CLI Layer | Deterministic commands (e.g., next, plan, review). | src/cli/, bin/palee.ts |
Sources: planning/palee_cli_spec.md
1.2 Data Flow: Command Execution
The following diagram illustrates how a deterministic command (like palee review) flows through the system entities.
CLI to Storage Data Flow
Sources: planning/palee_cli_spec.mdplanning/palee_cli_spec.mdplanning/invariants.md
2. System Invariants
Invariants are non-negotiable rules that the codebase must satisfy to ensure data integrity and algorithmic correctness.
2.1 Storage Invariants
- Frontmatter Preservation: Updating a PALEE field must preserve the Markdown body byte-for-byte planning/invariants.md — INV-01
- Optimistic Concurrency Control (OCC): Any change in file fingerprint during an operation must trigger a conflict (Exit Code 4) and abort the write planning/invariants.md — INV-03
- Atomic Writes: Temporary files and renames are used to prevent file truncation during failures planning/invariants.md — INV-08
- Locking: Locks become stale after 60s on Windows and 120s elsewhere; heartbeats occur every 15s planning/invariants.md — INV-05
2.2 SM-2 and Mastery Invariants
- SM-2 Bounds: The
ease_factormust never drop below1.30planning/invariants.md — INV-14 - Interval Logic: A
quality < 3result resets repetition to 0 and interval to 1 planning/invariants.md — INV-16 - Mastery Calculation:
topic_masteryis calculated asround((conceptual + practical + debug + (feynman * 2)) / 5, 4)planning/invariants.md — INV-21
Sources: planning/invariants.mdplanning/palee_cli_spec.md
3. Command Contracts
Phase 1 implements a set of deterministic commands designed for both human use and machine integration via the --json flag.
| Command | Purpose | Output/Contract |
|---|---|---|
adopt | Injects palee_id and schema into a note. | Adds palee_schema: 1planning/palee_cli_spec.md |
next | Suggests the next topic based on due date and dependencies. | Supports --json for automation planning/palee_cli_spec.md |
plan | Generates an ordered study session. | Respects depends_on graph planning/palee_cli_spec.md |
validate | Checks for cycles and missing dependencies. | Reports exact cycle paths planning/invariants.md — INV-25 |
Topic Identification Logic
The system uses a stable palee_id as the primary identifier. Topic matching is one shared resolver, resolveTopicQuery (src/cli/topic-query.ts), used by review, assess, progress and session: an exact palee_id wins outright, and otherwise a partial ID substring or a case-insensitive title substring must match exactly one topic — no match, or several candidates, errors with exit code 2 and lists the candidates (src/cli/review.ts, src/cli/assess.ts, src/cli/progress.ts). When nothing matched by ID or title, the query is compared against each note's vault-relative path, because next, plan and adopt print that path as a topic's identifier and refusing it back was a defect of the same size as accepting it (#313); the path comparison is exact after separator folding, case-folded only on win32, and it can never shadow an ID/title match. session start/session draft/session end resolve --topic through the same resolver (#302), so a query naming nothing or several things is refused at exit 2 instead of being written into .palee/sessions/ verbatim, and a query that resolves is recorded as the topic's canonical palee_id rather than the words the learner typed. When the flag is omitted the fallback stays hot memory's active_topic and is deliberately not re-resolved (resolveSessionTopic in src/cli/session.ts): hot.md is canonical, and a learner must still be able to end a session whose note was renamed or deleted mid-flight. The full precedence ladder — exact ID, exact title/filename, legacy alias, normalized slug, then token-distance match — is the specified contract planning/invariants.md with the interactive disambiguation contract in planning/palee_cli_spec.md, and is tracked as Planned in 08-2
Entity Mapping: Natural Language to Code
Sources: src/types.tssrc/engine/sm2.tssrc/engine/dependency.tssrc/storage/vault-walker.ts
4. Phase 1 Completion Status
All Phase 1 gates have been verified as of August 2026.
Resolved Issues & Implemented Features
- JSON Support: Implemented across all reading commands (
next,plan,progress,dashboard,validate,session list) planning/palee_cli_spec.md - Batch Adoption: Fully implemented in
palee adoptwith--all,--include,--exclude,--tag, and--dry-runsrc/cli/adopt.ts - Markdown Roadmap Import: Supports importing from
.mdfiles containing YAML frontmatter or YAML code fences src/storage/roadmap-parser.ts - Difficulty Normalization: A runtime helper now maps numeric (1-5) and string inputs to the
Difficultyenum planning/invariants.md - Empty States: Actionable onboarding guidance replaces empty terminal dumps planning/palee_cli_spec.md
Known Gaps (Phase 2)
- AI Integration:
testandtutorare not shipped; they exist only as Phase 2 design. See Future AI Module & Phase 2 Design and planning/PHASE_2_GAPS.md. - Broader Auto-Fix:
validate --fixships three conservative repairs - rebuilding.palee/hot.mdand.palee/index.md, recomputingtopic_masterywhen all four pillars are present, and resetting invalid SM-2 fields to adopt defaults via OCC-safe atomic writes. A general transactional fix engine for everyfixablefinding remains future work; see ADR-0035 and ADR-0008.
