@bernierllc/planning-session-core
v1.0.2
Published
Crash-resistant planning session state management with automatic version tracking for BernierLLC ecosystem
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
