npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@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-core

Features

  • 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