SkillAgentSearch skills...

Codascon

A structural protocol for code organization with exhaustive compile-time type checking

Install / Use

/learn @scorpevans/Codascon
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

codascon

CI npm codascon npm odetovibe license

A structural protocol for code organization with exhaustive compile-time type checking.

Codascon distills high-level design patterns and SOLID principles into a zero-overhead TypeScript protocol. You describe what your domain looks like — which entities exist, which operations apply to them, and which strategies handle each combination — and your architectural intent is guarded with mathematical certainty. If a single edge case is unhandled, the compiler won't just warn you — it will stop you.

For larger domains, Odetovibe pairs with it to generate TypeScript scaffolding from a declarative YAML schema — keeping your business logic pure and your architecture predictable and unbreakable.

The Runtime: 10 lines of code.

The Power: Pure type-level enforcement via four primitives: Subject, Command, Template, and Strategy.


The Problem

Every codebase demands structural decisions before a line of business logic is written: which patterns apply, how responsibilities divide, where new code belongs. SOLID principles and design patterns provide guidance, but they remain advisory — there is no formal protocol that enforces them, and no two codebases look alike.

With N entity types and M operations, the naive approach scatters N×M branching logic — switch statements, instanceof checks, conditional chains — across the codebase. Add a new entity type and you must hunt down every branch that handles it. Miss one and you get a silent runtime bug, discovered in production.

The absence of a formal coding protocol compounds in several directions:

  • No consistent architecture. Without a shared structural schema, every codebase is a dialect. Onboarding, auditing, and refactoring all require re-learning local conventions before any real work begins.
  • No compiler-checkable guarantees. In dynamically typed languages, structurally incorrect code runs until it crashes. Even in statically typed languages, the compiler cannot enforce any structural requirements without a typed protocol.
  • Brittle change management. When business rules change, a developer must reason about the entire codebase to identify what needs updating. Without enforced isolation of concerns, every change carries hidden risk.

With the rise of AI-assisted development, these problems compound further. An LLM generating code without structural rails produces output that is internally inconsistent, architecturally divergent across iterations, and difficult to audit. The more code the AI writes, the more the absence of a formal protocol matters.

What Codascon Provides

1. Exhaustive compile-time coverage

Codascon's implementation in TypeScript provides exhaustive compile-time type checking; the dispatch mechanism will not fail at runtime. In other languages, the structural protocol still applies and brings the same organizational benefits, and the compile-time safety would depend on the extent of the implementation of Codascon as constrained by the language's type system.

2. Bounded scope of change

There is no N×M coverage matrix to keep in your head — the type system holds it. When a new Subject is added, every Command that must handle it shows a compile error at the exact call site. When a business rule changes for a specific entity-operation pair — say, extending how Orders are processed — you add a Strategy to the relevant Command and update its resolver logic. You do not have to consider the rest of the codebase.

3. Code architecture in YAML

Codascon provides a consistent schema for expressing code architecture. Every domain built on it follows the same structural shape — Subjects, Commands, Templates, and Strategies — with no dialect variation across codebases or teams. Via Odetovibe, that architecture can be expressed in a declarative YAML schema and scaffolded directly into code, giving you a versioned, reviewable record of your domain structure, separate from implementation. Because the schema is structured and human-readable, non-coders can read it directly — or it could be rendered into flowcharts and diagrams — to visualize and reason about the system's architecture without touching the code.

4. Structural rails for AI-generated code (Vibe coding)

With a formal protocol in place, an LLM can generate structurally correct code by construction. The same business logic produces the same code — regardless of which model generated it or when. You focus on the business domain; the protocol ensures the output is consistent and auditable.

Packages

| Package | Description | | ----------------------------------- | -------------------------------------------------------------------------------- | | codascon | The framework — Subject, Command, Template, Strategy, and type utilities | | odetovibe | CLI + library: YAML schema, validation, and TypeScript scaffolding codegen |

Quick Start

Install

npm install codascon
# or
pnpm add codascon

Define Subjects

A Subject is an entity in your domain. Codascon enforces that each Subject declares a resolverName — the method name its Commands must implement to handle it.

import { Subject } from "codascon";

interface Person {
  name: string;
}

class Student extends Subject implements Person {
  readonly resolverName = "resolveStudent" as const;
  constructor(
    public readonly name: string,
    public readonly year: number,
  ) {
    super();
  }
}

class Professor extends Subject implements Person {
  readonly resolverName = "resolveProfessor" as const;
  constructor(
    public readonly name: string,
    public readonly department: string,
  ) {
    super();
  }
}

Define a Command

A Command is an operation. Codascon enforces at the call site that a Command implements a resolver method per Subject — the resolver method inspects the Subject and the context, then returns a Template to execute. A defaultResolver can be provided as a fallback instead of listing all resolver methods.

import { Command } from "codascon";

class LogCommand extends Command<Person, { message: string }, void, [Student, Professor]> {
  readonly commandName = "log" as const;
  private readonly entry = new LogEntry(); // Strategy — defined below
  readonly defaultResolver = this.entry; // catch-all — fires for Professor and any other subject with no specific resolver
  resolveStudent(_s: Student) {
    return this.entry;
  }
}

Define Templates and their Strategies

A Template abstract class defines the execution contract for a Command. It may handle the full Subject union or be narrowed to a subset. Strategy classes provide the concrete implementations.

import { type Template, type CommandSubjectUnion } from "codascon";

// execute handles the full subject union (Student | Professor) — no subject narrowing needed here.
// LogEntry is a concrete empty Strategy; both resolvers share one singleton instance (entry).
abstract class LogTemplate implements Template<LogCommand> {
  execute(subject: CommandSubjectUnion<LogCommand>, entry: { message: string }): void {
    console.log(`[${subject.name}] ${entry.message}`);
  }
}

class LogEntry extends LogTemplate {}

Run

const log = new LogCommand();

log.run(new Student("Alice", 3), { message: "library card issued" });
// [Alice] library card issued

log.run(new Professor("Prof. Smith", "Physics"), { message: "lab access granted" });
// [Prof. Smith] lab access granted
command.run(subject, object)
  → subject.getCommandStrategy(command, object)       // double dispatch
    → command[subject.resolverName](subject, object)  // resolver selects a Template
      → returns a Template
  → template.execute(subject, object)                 // Template executes
  → returns result

Advanced Patterns

Parameterized Templates

A Template can carry its subject union as a type parameter — letting each Strategy narrow which Subjects it handles and access subject-specific fields directly:

interface Equipment {
  name: string;
  days?: number;
}

interface CheckoutResult {
  approved: boolean;
  daysGranted: number;
  note?: string;
}

class CheckoutCommand extends Command<Person, Equipment, CheckoutResult, [Student, Professor]> {
  readonly commandName = "checkout" as const;
  resolveStudent(_s: Student, _e: Equipment) {
    return new StudentCheckout();
  }
  resolveProfessor(_p: Professor, _e: Equipment) {
    return new ProfessorCheckout();
  }
}

abstract class CheckoutTemplate<
  SU extends CommandSubjectUnion<CheckoutCommand>,
> implements Template<CheckoutCommand, [], SU> {
  execute(subject: SU, equipment: Equipment): CheckoutResult {
    return this.approve(subject, equipment as Equipment & { days: number }); // days filled at runtime
  }
  protected abstract approve(subject: SU, equipment: Equipment & { days: number }): CheckoutResult;
}

// SU = Student — typed access to student.year
class StudentCheckout extends CheckoutTemplate<Student> {
  protected approve(student: Student, equipment: Equipment & { days: number }): CheckoutResult {
    return { approved: true, daysGranted: equipment.days, note: `year ${student.year}` };
  }
}
View on GitHub
GitHub Stars7
CategoryDevelopment
Updated13h ago
Forks0

Languages

TypeScript

Security Score

85/100

Audited on Mar 30, 2026

No findings