Package Exports
- @bernierllc/planning-session-core
- @bernierllc/planning-session-core/dist/index.js
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (@bernierllc/planning-session-core) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
@bernierllc/planning-session-core
Crash-resistant planning session state management with automatic version tracking for BernierLLC ecosystem.
Installation
npm install @bernierllc/planning-session-coreFeatures
- Crash-resistant session management - Automatic version tracking with recovery utilities
- State machine validation - Type-safe status transitions (active → paused → converted → archived)
- Automatic versioning - Content changes create new versions automatically
- Repository context tracking - Link sessions to git repositories and local paths
- Conversion tracking - Track conversion from planning sessions to projects and work items
- Query and filtering - Flexible session discovery by status, repository, project, and dates
- Statistics - Real-time session analytics and metrics
Quick Start
import { PlanningSessionManager } from '@bernierllc/planning-session-core';
import { InMemorySessionStorage, InMemoryVersionStorage } from './storage';
// Create manager with storage implementations
const manager = new PlanningSessionManager(
sessionStorage,
versionStorage,
{
auto_version: true, // Auto-create versions on content changes
logger: console // Optional logger for debugging
}
);
// Create a new planning session
const result = await manager.create({
title: 'Authentication System Planning',
description: 'Design OAuth2 implementation',
repository_path: '/projects/auth-service',
initial_content: '# Auth System\n\n## Requirements\n...'
});
if (result.success) {
console.log('Created session:', result.data.id);
}Core Concepts
Planning Sessions
A planning session represents a planning/design document with version history:
- Identity: Unique ID, title, description
- Repository Context: Git URL, local path, working directory
- Status: Active, paused, converted, or archived
- Content: Current markdown content with version number
- Conversion Tracking: Links to projects and work items created from session
- Metadata: Extensible custom metadata storage
Status Management (State Machine)
active ──┬──> paused ──> active (can resume)
├──> converted ──> archived (one-way)
└──> archived (terminal state)- active: Currently being worked on
- paused: Temporarily stopped (can resume)
- converted: Converted to project/work items (read-only)
- archived: Permanently archived (no transitions)
Automatic Versioning
Every content change creates a new version:
- Version 1: Initial content
- Version 2: After first update
- Version 3: After second update
Versions include:
- Full content snapshot
- Change summary (optional)
- Changed fields tracking
- Creation timestamp and author
API Reference
Creating Sessions
const result = await manager.create({
title: 'E-commerce Platform Planning',
description: 'Design shopping cart and checkout flow',
repository_path: '/projects/ecommerce',
repository_url: 'https://github.com/company/ecommerce',
initial_content: '# Shopping Cart\n\n## Requirements',
created_by: 'agent:planning-assistant',
metadata: { priority: 'high' }
});Updating Sessions
// Update creates new version automatically
const updateResult = await manager.update(sessionId, {
content: updatedMarkdownContent,
change_summary: 'Added payment processing requirements',
updated_by: 'agent:planning-assistant'
});
// Check current version
console.log('New version:', updateResult.data.current_version);Status Management
// Pause session
await manager.pause(sessionId, 'Waiting for stakeholder feedback');
// Resume session
await manager.resume(sessionId);
// Convert session to work items
await manager.markConverted(sessionId, {
project_id: 'project-123',
work_item_ids: ['wi-1', 'wi-2', 'wi-3'],
converted_by: 'agent:work-item-creator'
});
// Archive session
await manager.archive(sessionId);Version History
// Get all versions
const versions = await manager.getVersions(sessionId);
for (const version of versions.data) {
console.log(`v${version.version_number}: ${version.change_summary}`);
}
// Compare versions
const diff = await manager.compareVersions(sessionId, 1, 3);
console.log(`Lines added: ${diff.data.lines_added}`);
console.log(`Lines removed: ${diff.data.lines_removed}`);
// Restore to previous version
await manager.restoreVersion(sessionId, 2, 'user:john');Querying Sessions
// Get active sessions
const active = await manager.findActive();
// Find sessions by repository
const repoSessions = await manager.findByRepository('/projects/auth-service');
// Query with filters
const filtered = await manager.list({
status: ['active', 'paused'],
created_after: new Date('2025-01-01'),
has_content: true,
repository_path: '/projects/app'
});Crash Recovery
import { SessionRecovery } from '@bernierllc/planning-session-core';
// Find stale sessions (inactive for 24+ hours)
const stale = await SessionRecovery.findStale(storage);
console.log(`Found ${stale.stale_sessions.length} stale sessions`);
for (const session of stale.stale_sessions) {
const action = stale.recommendations[session.id];
console.log(`Session ${session.id}: recommend ${action}`);
if (action === 'pause') {
await manager.pause(session.id, 'Auto-paused: inactive for 24+ hours');
} else if (action === 'archive') {
await manager.archive(session.id);
}
}
// Restore from history
const restored = await SessionRecovery.restoreFromHistory(sessionId, manager);Statistics
const stats = await manager.getStatistics();
console.log(`Total sessions: ${stats.data.total_sessions}`);
console.log(`Active: ${stats.data.active_sessions}`);
console.log(`Paused: ${stats.data.paused_sessions}`);
console.log(`Converted: ${stats.data.converted_sessions}`);
console.log(`Average versions per session: ${stats.data.average_versions_per_session}`);Storage Implementation
This package provides storage interfaces that you must implement:
import { PrismaClient } from '@prisma/client';
import { PlanningSessionStorage, PlanningSession, SessionFilters } from '@bernierllc/planning-session-core';
class PrismaSessionStorage implements PlanningSessionStorage {
constructor(private prisma: PrismaClient) {}
async save(session: PlanningSession): Promise<void> {
await this.prisma.planningSession.upsert({
where: { id: session.id },
create: session,
update: session
});
}
async get(id: string): Promise<PlanningSession | null> {
return await this.prisma.planningSession.findUnique({
where: { id }
});
}
async query(filters: SessionFilters): Promise<PlanningSession[]> {
return await this.prisma.planningSession.findMany({
where: {
status: Array.isArray(filters.status)
? { in: filters.status }
: filters.status,
// ... other filters
}
});
}
async delete(id: string): Promise<void> {
await this.prisma.planningSession.delete({ where: { id } });
}
}See the design spec at plans/packages/core/planning-session-core.md for complete storage implementation examples.
Integration Status
- Logger: Integrated (optional) - Pass logger in options for operation logging
- Docs-Suite: Ready - Complete TypeDoc API documentation
- NeverHub: Optional - Publish session events, subscribe to work item completion
License
Copyright (c) 2025 Bernier LLC. All rights reserved.
See Also
- @bernierllc/work-item-core - Work item management (receives converted sessions)
- @bernierllc/version-store - Future unified version management
- @bernierllc/validators-core - Input validation utilities