Code Kits

The full registry of Kits, their spec node types, output artifacts, and topological batch ordering.

Code Kits

Praetor's generation pipeline is made up of Kits — each one responsible for a single type of implementation node. The Kit Registry maps an implNodeType string to the Kit that handles it.

This page documents every registered Kit, ordered by the topological batch in which it runs.


Topological Batch Order

Kits and deterministic pipeline steps run in dependency order. Later batches can import types and contracts from earlier batches.

Batch 0:  [DETERMINISTIC] ScaffoldStep
Batch 1:  [DETERMINISTIC] SharedTypesStep + DesignSystemStep
Batch 2:  [KIT] EntityKit, SchemaKit, GuardKit
Batch 3:  [KIT] AuthKit
Batch 4:  [DETERMINISTIC] MigrationStep
Batch 5:  [KIT] ServiceKit
Batch 6:  [KIT] OperationKit
Batch 7:  [KIT] EndpointKit
Batch 8:  [KIT] APIClientKit
Batch 9:  [KIT] ComponentKit, UIStateKit
Batch 10: [KIT] PageKit
Batch 11: [KIT] LayoutKit, NavigationKit
Batch 12: [KIT] WorkflowKit, NotificationKit, AutomationKit
Batch 13: [DETERMINISTIC] TestInfraStep
Batch 14: [DETERMINISTIC] CICDStep

Deterministic steps produce output from templates with no LLM. Kit batches may involve an LLM in their APPLY phase.


Core Application Kits

KitimplNodeTypeOutput artifactsVerification strategy
EntityKitimpl_entitysrc/db/schema/{tableName}.ts, drizzle.config.ts, drizzle/migrations/{ts}_create_{table}.sqlAll required columns present in Drizzle schema; TypeScript types exported; primary key present
SchemaKitimpl_schemasrc/schemas/{name}.ts (Zod)Schema exports a named Zod object; all required fields present; .parse() call does not throw on valid input
GuardKitimpl_guardsrc/guards/{name}.tsGuard exports a Hono middleware function; auth check logic present; 401/403 responses covered
AuthKitimpl_authsrc/auth/service.ts, src/auth/jwt.ts, src/auth/password.ts, src/auth/middleware.ts, src/app/api/auth/[...nextauth]/route.tsSession service exports login/register/logout; JWT sign and verify present; password hash function exported
ServiceKitimpl_servicesrc/services/{name}.tsService class exported; all operations from spec present as method stubs; constructor accepts repository or DB
OperationKitimpl_operationsrc/operations/{name}.tsOperation function exported; parameter types match spec; return type matches spec
EndpointKitimpl_endpointsrc/api/routes/{label-slug}.tsHono route handler exported; method and path match spec; request validation present; response shape matches spec
APIClientKitimpl_api_clientsrc/lib/api-client.ts or src/integrations/{name}/{name}-client.tsTyped client class exported; one method per endpoint; parameter types match backend contract
RLSKitimpl_rls_policysrc/db/migrations/rls_{table}.sql, src/db/migrations/rls_setup.sqlRLS policies cover SELECT, INSERT, UPDATE, DELETE; tenant filter uses correct column; SET app.tenant_id helper present
WorkflowKitimpl_workflowsrc/workflows/{name}.ts (Inngest function), src/api/inngest.tsInngest function exported; id and name fields present; at least one step.run call; event trigger name matches spec
NotificationKitimpl_notificationsrc/notifications/{name}.tsNotification function exported; template renders to string; email/SMS sender type matches
AutomationKitimpl_ai_automationsrc/integrations/quickbooks/quickbooks-client.ts (or similar)Integration client exported; all declared methods present; error handling wraps external calls

UI Kits

KitimplNodeTypeOutput artifactsVerification strategy
ComponentKitimpl_ui_componentsrc/components/{name-kebab}.tsx'use client' directive present; component name exported as default; all entity type names imported; mutation hooks wired for triggered endpoints
PageKitimpl_ui_pagesrc/app/{route}/page.tsxPage component exported as default; data-loading hooks present; auth guard applied if requiresAuth: true; route group matches auth requirement
LayoutKitimpl_ui_layoutsrc/app/{path}/layout.tsx, src/components/layout/sidebar.tsx, src/components/layout/top-nav.tsx, src/components/layout/breadcrumbs.tsxLayout wraps {children}; sidebar imports navigation manifest; breadcrumbs follow route structure
NavigationKitimpl_ui_navsrc/lib/navigation.ts, src/lib/route-manifest.tsNavigation manifest includes all registered pages; route paths match page spec; auth-required routes flagged
DataLayerKit (not currently registered)impl_data_layersrc/lib/hooks/{entity}.hooks.ts (React Query hooks)Query hooks exported for each declared endpoint; mutation hooks present for write endpoints; types match backend contract
UIStateKitimpl_ui_statesrc/lib/stores/{name}.ts (Zustand store)Store exported; all declared state slices present; action functions exported

Mobile Kits

KitimplNodeTypeOutput artifactsVerification strategy
MobileComponentKitimpl_mobile_componentReact Native component .tsxComponent exported; StyleSheet used; platform-safe properties only
MobileScreenKitimpl_mobile_screenReact Native screen .tsxScreen exported; navigation params typed; SafeAreaView present
MobileLayoutKitimpl_mobile_layoutReact Native layout component .tsxLayout exported; children prop typed; navigation container wired
MobileFormKitimpl_mobile_formReact Native form component .tsxForm exported; all fields present; submit handler calls correct mutation

Frappe / ERPNext Config Kits

These Kits handle ERPNext DocType configuration nodes. They produce JSON configuration files rather than TypeScript source. See Config Kits for full coverage.

KitimplNodeTypeOutput artifactsVerification strategy
NamingSeriesKitspec_naming_seriessrc/services/naming/{name}.naming.ts, src/db/migrations/create_naming_counters.sqlparsePattern exported; generateId handles all 4 pattern types (hash, prompt, field, prefix-year-counter)
ChildTableKitspec_child_tablesrc/db/schema/{table}.ts, src/types/{name}.ts, src/api/routes/{name}-child.tsParent FK columns present (parentId, parentType, parentField, idx); Hono router exported; CRUD routes present
LinkFieldKitspec_link_fieldLink field helper and type resolverForeign key type resolves to correct entity; nullable unless required
SubmittableKitspec_submittableSubmit/cancel/amend workflow helpersWorkflow states cover Draft → Submitted → Cancelled; status field present
DocLifecycleKitspec_lifecyclesrc/services/lifecycle/{name}-lifecycle.tsAll 9 hooks exported (beforeInsert, afterInsert, validate, beforeSave, afterSave, onSubmit, onCancel, onAmend, onTrash); lifecycle class implements typed interface
AmendmentKitspec_amendmentAmendment workflow helpers and migrationamended_from field present; amendment chain traversal exported
DynamicLinkKitspec_dynamic_linkDynamic link resolverTarget doctype resolver handles polymorphic references
ReportKitspec_reportReport query and rendererReport function exported; query result typed; at least one column defined
PrintFormatKitspec_print_formatPrint format templateHTML/Jinja template present; entity fields referenced correctly
EmailTemplateKitspec_email_templateEmail template moduleTemplate renders subject and body; variable substitution present
AttachmentKitspec_attachmentAttachment handling utilitiesUpload, retrieve, and delete functions exported; file size limit respected
ActivityKitspec_activityActivity log serviceLog function exported; activity record includes user, timestamp, and action
TagKitspec_tagTag service and migrationTag CRUD helpers exported; tag-to-entity join table created
SharingKitspec_sharingDocument sharing serviceShare, revoke, and check-access functions exported
VersioningKitspec_versionVersion history serviceCreate-version and restore-version exported; diff computation present
WebFormKitspec_web_formPublic web form route and rendererForm route exports GET and POST handlers; CSRF protection present

Kit Registry lookup

The pipeline uses a single call to dispatch to the correct Kit:

import { getKit, initializeKits } from './kits/kit-registry.js'

// At startup — loads all Kit modules and triggers self-registration
await initializeKits()

// At generation time — O(1) Map lookup
const kit = getKit(implNode.implNodeType)
if (!kit) {
  log.warn({ implNodeType: implNode.implNodeType }, 'No Kit registered for this node type — skipping')
  continue
}

const output = kit.generate(input)

If no Kit is registered for an impl node type, that node is skipped and a warning is recorded in the generation run summary. It does not block other nodes.


Adding a new Kit

  1. Create src/services/codegen/kits/{name}-kit.ts
  2. Implement CodegenKit (or MultiNodeCodegenKit if you need all nodes at once)
  3. Call registerKit(new MyKit()) at the bottom of the file
  4. Add await import('./my-kit.js') inside initializeKits() in kit-registry.ts

The Kit will be available immediately after the next initializeKits() call.

Command Palette

Search for a command to run...