From 8840c6664457ab6823f6110b89905b2d8e544a97 Mon Sep 17 00:00:00 2001 From: Kurt Overmier Date: Tue, 3 Mar 2026 05:16:46 -0600 Subject: [PATCH] refactor(adf): dismantle monolithic types.ts into domain-owned modules Split types.ts (258 LOC) into 6 focused domain files under types/: - ast.ts: AdfDocument, AdfSection, AdfContent, AdfMapEntry, AdfMetricEntry - decorations.ts: STANDARD_DECORATIONS, CANONICAL_KEY_ORDER - patch.ts: PatchOperation union and 7 op interfaces - manifest.ts: Manifest, ManifestModule, SyncEntry, CadenceEntry, MetricSource - bundle.ts: BundleResult - validation.ts: ConstraintStatus, ConstraintResult, WeightSummary, EvidenceResult, AdfLockfile, AdfSyncStatus Original types.ts replaced with barrel re-export for backward compatibility. Zero import changes needed across all consumers. Closes #10 Co-Authored-By: Claude Opus 4.6 --- packages/adf/src/types.ts | 259 +------------------------- packages/adf/src/types/ast.ts | 33 ++++ packages/adf/src/types/bundle.ts | 30 +++ packages/adf/src/types/decorations.ts | 41 ++++ packages/adf/src/types/index.ts | 6 + packages/adf/src/types/manifest.ts | 37 ++++ packages/adf/src/types/patch.ts | 59 ++++++ packages/adf/src/types/validation.ts | 46 +++++ 8 files changed, 254 insertions(+), 257 deletions(-) create mode 100644 packages/adf/src/types/ast.ts create mode 100644 packages/adf/src/types/bundle.ts create mode 100644 packages/adf/src/types/decorations.ts create mode 100644 packages/adf/src/types/index.ts create mode 100644 packages/adf/src/types/manifest.ts create mode 100644 packages/adf/src/types/patch.ts create mode 100644 packages/adf/src/types/validation.ts diff --git a/packages/adf/src/types.ts b/packages/adf/src/types.ts index e11c33b..bbdf524 100644 --- a/packages/adf/src/types.ts +++ b/packages/adf/src/types.ts @@ -1,257 +1,2 @@ -/** - * ADF (Attention-Directed Format) AST types. - * - * Defines the canonical data model for ADF documents, patch operations, - * manifest routing, and bundle output. - */ - -// ============================================================================ -// AST Types -// ============================================================================ - -export interface AdfDocument { - version: '0.1'; - sections: AdfSection[]; -} - -export interface AdfSection { - key: string; - decoration: string | null; - content: AdfContent; - weight?: 'load-bearing' | 'advisory'; -} - -export type AdfContent = - | { type: 'text'; value: string } - | { type: 'list'; items: string[] } - | { type: 'map'; entries: AdfMapEntry[] } - | { type: 'metric'; entries: AdfMetricEntry[] }; - -export interface AdfMapEntry { - key: string; - value: string; -} - -export interface AdfMetricEntry { - key: string; - value: number; - ceiling: number; - unit: string; -} - -// ============================================================================ -// Standard Decorations -// ============================================================================ - -export const STANDARD_DECORATIONS: Record = { - TASK: '\u{1F3AF}', - ROLE: '\u{1F9D1}', - CONTEXT: '\u{1F4CB}', - OUTPUT: '\u{2705}', - CONSTRAINTS: '\u{26A0}\u{FE0F}', - RULES: '\u{1F4D0}', - DEFAULT_LOAD: '\u{1F4E6}', - ON_DEMAND: '\u{1F4C2}', - FILES: '\u{1F5C2}\u{FE0F}', - TOOLS: '\u{1F6E0}\u{FE0F}', - RISKS: '\u{1F6A8}', - STATE: '\u{1F9E0}', - BUDGET: '\u{1F4B0}', - SYNC: '\u{1F504}', - CADENCE: '\u{1F4CA}', - GUIDE: '\u{1F4D6}', -}; - -export const CANONICAL_KEY_ORDER: string[] = [ - 'TASK', - 'ROLE', - 'CONTEXT', - 'OUTPUT', - 'CONSTRAINTS', - 'RULES', - 'DEFAULT_LOAD', - 'ON_DEMAND', - 'BUDGET', - 'SYNC', - 'CADENCE', - 'FILES', - 'TOOLS', - 'RISKS', - 'STATE', - 'GUIDE', -]; - -// ============================================================================ -// Patch Operations (Discriminated Union) -// ============================================================================ - -export interface AddBulletOp { - op: 'ADD_BULLET'; - section: string; - value: string; -} - -export interface ReplaceBulletOp { - op: 'REPLACE_BULLET'; - section: string; - index: number; - value: string; -} - -export interface RemoveBulletOp { - op: 'REMOVE_BULLET'; - section: string; - index: number; -} - -export interface AddSectionOp { - op: 'ADD_SECTION'; - key: string; - decoration?: string | null; - content: AdfContent; - weight?: 'load-bearing' | 'advisory'; -} - -export interface ReplaceSectionOp { - op: 'REPLACE_SECTION'; - key: string; - content: AdfContent; -} - -export interface RemoveSectionOp { - op: 'REMOVE_SECTION'; - key: string; -} - -export interface UpdateMetricOp { - op: 'UPDATE_METRIC'; - section: string; - key: string; - value: number; -} - -export type PatchOperation = - | AddBulletOp - | ReplaceBulletOp - | RemoveBulletOp - | AddSectionOp - | ReplaceSectionOp - | RemoveSectionOp - | UpdateMetricOp; - -// ============================================================================ -// Manifest Types -// ============================================================================ - -export interface Manifest { - version: '0.1'; - role?: string; - defaultLoad: string[]; - onDemand: ManifestModule[]; - rules: string[]; - tokenBudget?: number; - sync: SyncEntry[]; - cadence: CadenceEntry[]; - metrics: MetricSource[]; -} - -export interface SyncEntry { - source: string; - target: string; -} - -export interface ManifestModule { - path: string; - triggers: string[]; - loadPolicy: 'DEFAULT' | 'ON_DEMAND'; - tokenBudget?: number; -} - -export interface CadenceEntry { - check: string; - frequency: string; -} - -export interface MetricSource { - key: string; - path: string; -} - -// ============================================================================ -// Bundle Output -// ============================================================================ - -export interface BundleResult { - manifest: Manifest; - resolvedModules: string[]; - mergedDocument: AdfDocument; - tokenEstimate: number; - tokenBudget: number | null; - tokenUtilization: number | null; - perModuleTokens: Record; - moduleBudgetOverruns: Array<{ - module: string; - tokens: number; - budget: number; - }>; - triggerMatches: Array<{ - module: string; - trigger: string; - matched: boolean; - matchedKeywords: string[]; - loadReason: 'default' | 'trigger'; - }>; - unmatchedModules: string[]; - advisoryOnlyModules: string[]; -} - -// ============================================================================ -// Sync / Lockfile Types -// ============================================================================ - -/** - * .adf.lock file format: flat JSON map of source filename → sha256 prefix (16 hex chars). - * Generated by `charter adf sync --write`, checked by `charter adf sync --check`. - */ -export interface AdfLockfile { - [sourceFile: string]: string; -} - -export interface AdfSyncStatus { - source: string; - sourceHash: string; - lockedHash: string | null; - inSync: boolean; -} - -// ============================================================================ -// Constraint Validation -// ============================================================================ - -export type ConstraintStatus = 'pass' | 'fail' | 'warn'; - -export interface ConstraintResult { - section: string; - metric: string; - value: number; - ceiling: number; - unit: string; - status: ConstraintStatus; - message: string; - source: 'metric' | 'context'; -} - -export interface WeightSummary { - loadBearing: number; - advisory: number; - unweighted: number; - total: number; -} - -export interface EvidenceResult { - constraints: ConstraintResult[]; - weightSummary: WeightSummary; - allPassing: boolean; - failCount: number; - warnCount: number; -} +// Backward-compatible barrel — all domain types re-exported. +export * from './types/index'; diff --git a/packages/adf/src/types/ast.ts b/packages/adf/src/types/ast.ts new file mode 100644 index 0000000..8501df5 --- /dev/null +++ b/packages/adf/src/types/ast.ts @@ -0,0 +1,33 @@ +/** + * ADF AST Core — canonical document structure types. + */ + +export interface AdfDocument { + version: '0.1'; + sections: AdfSection[]; +} + +export interface AdfSection { + key: string; + decoration: string | null; + content: AdfContent; + weight?: 'load-bearing' | 'advisory'; +} + +export type AdfContent = + | { type: 'text'; value: string } + | { type: 'list'; items: string[] } + | { type: 'map'; entries: AdfMapEntry[] } + | { type: 'metric'; entries: AdfMetricEntry[] }; + +export interface AdfMapEntry { + key: string; + value: string; +} + +export interface AdfMetricEntry { + key: string; + value: number; + ceiling: number; + unit: string; +} diff --git a/packages/adf/src/types/bundle.ts b/packages/adf/src/types/bundle.ts new file mode 100644 index 0000000..4a17862 --- /dev/null +++ b/packages/adf/src/types/bundle.ts @@ -0,0 +1,30 @@ +/** + * ADF Bundle Output — result shape from bundleModules(). + */ + +import type { AdfDocument } from './ast'; +import type { Manifest } from './manifest'; + +export interface BundleResult { + manifest: Manifest; + resolvedModules: string[]; + mergedDocument: AdfDocument; + tokenEstimate: number; + tokenBudget: number | null; + tokenUtilization: number | null; + perModuleTokens: Record; + moduleBudgetOverruns: Array<{ + module: string; + tokens: number; + budget: number; + }>; + triggerMatches: Array<{ + module: string; + trigger: string; + matched: boolean; + matchedKeywords: string[]; + loadReason: 'default' | 'trigger'; + }>; + unmatchedModules: string[]; + advisoryOnlyModules: string[]; +} diff --git a/packages/adf/src/types/decorations.ts b/packages/adf/src/types/decorations.ts new file mode 100644 index 0000000..d9d9b30 --- /dev/null +++ b/packages/adf/src/types/decorations.ts @@ -0,0 +1,41 @@ +/** + * ADF Decorations — standard emoji decorations and canonical section ordering. + */ + +export const STANDARD_DECORATIONS: Record = { + TASK: '\u{1F3AF}', + ROLE: '\u{1F9D1}', + CONTEXT: '\u{1F4CB}', + OUTPUT: '\u{2705}', + CONSTRAINTS: '\u{26A0}\u{FE0F}', + RULES: '\u{1F4D0}', + DEFAULT_LOAD: '\u{1F4E6}', + ON_DEMAND: '\u{1F4C2}', + FILES: '\u{1F5C2}\u{FE0F}', + TOOLS: '\u{1F6E0}\u{FE0F}', + RISKS: '\u{1F6A8}', + STATE: '\u{1F9E0}', + BUDGET: '\u{1F4B0}', + SYNC: '\u{1F504}', + CADENCE: '\u{1F4CA}', + GUIDE: '\u{1F4D6}', +}; + +export const CANONICAL_KEY_ORDER: string[] = [ + 'TASK', + 'ROLE', + 'CONTEXT', + 'OUTPUT', + 'CONSTRAINTS', + 'RULES', + 'DEFAULT_LOAD', + 'ON_DEMAND', + 'BUDGET', + 'SYNC', + 'CADENCE', + 'FILES', + 'TOOLS', + 'RISKS', + 'STATE', + 'GUIDE', +]; diff --git a/packages/adf/src/types/index.ts b/packages/adf/src/types/index.ts new file mode 100644 index 0000000..c87db07 --- /dev/null +++ b/packages/adf/src/types/index.ts @@ -0,0 +1,6 @@ +export * from './ast'; +export * from './decorations'; +export * from './patch'; +export * from './manifest'; +export * from './bundle'; +export * from './validation'; diff --git a/packages/adf/src/types/manifest.ts b/packages/adf/src/types/manifest.ts new file mode 100644 index 0000000..c5f7934 --- /dev/null +++ b/packages/adf/src/types/manifest.ts @@ -0,0 +1,37 @@ +/** + * ADF Manifest — module routing, sync, cadence, and metric source types. + */ + +export interface Manifest { + version: '0.1'; + role?: string; + defaultLoad: string[]; + onDemand: ManifestModule[]; + rules: string[]; + tokenBudget?: number; + sync: SyncEntry[]; + cadence: CadenceEntry[]; + metrics: MetricSource[]; +} + +export interface SyncEntry { + source: string; + target: string; +} + +export interface ManifestModule { + path: string; + triggers: string[]; + loadPolicy: 'DEFAULT' | 'ON_DEMAND'; + tokenBudget?: number; +} + +export interface CadenceEntry { + check: string; + frequency: string; +} + +export interface MetricSource { + key: string; + path: string; +} diff --git a/packages/adf/src/types/patch.ts b/packages/adf/src/types/patch.ts new file mode 100644 index 0000000..f17a396 --- /dev/null +++ b/packages/adf/src/types/patch.ts @@ -0,0 +1,59 @@ +/** + * ADF Patch Operations — discriminated union of document delta operations. + */ + +import type { AdfContent } from './ast'; + +export interface AddBulletOp { + op: 'ADD_BULLET'; + section: string; + value: string; +} + +export interface ReplaceBulletOp { + op: 'REPLACE_BULLET'; + section: string; + index: number; + value: string; +} + +export interface RemoveBulletOp { + op: 'REMOVE_BULLET'; + section: string; + index: number; +} + +export interface AddSectionOp { + op: 'ADD_SECTION'; + key: string; + decoration?: string | null; + content: AdfContent; + weight?: 'load-bearing' | 'advisory'; +} + +export interface ReplaceSectionOp { + op: 'REPLACE_SECTION'; + key: string; + content: AdfContent; +} + +export interface RemoveSectionOp { + op: 'REMOVE_SECTION'; + key: string; +} + +export interface UpdateMetricOp { + op: 'UPDATE_METRIC'; + section: string; + key: string; + value: number; +} + +export type PatchOperation = + | AddBulletOp + | ReplaceBulletOp + | RemoveBulletOp + | AddSectionOp + | ReplaceSectionOp + | RemoveSectionOp + | UpdateMetricOp; diff --git a/packages/adf/src/types/validation.ts b/packages/adf/src/types/validation.ts new file mode 100644 index 0000000..b3b726c --- /dev/null +++ b/packages/adf/src/types/validation.ts @@ -0,0 +1,46 @@ +/** + * ADF Validation — constraint results, weight summaries, evidence, sync/lockfile types. + */ + +export type ConstraintStatus = 'pass' | 'fail' | 'warn'; + +export interface ConstraintResult { + section: string; + metric: string; + value: number; + ceiling: number; + unit: string; + status: ConstraintStatus; + message: string; + source: 'metric' | 'context'; +} + +export interface WeightSummary { + loadBearing: number; + advisory: number; + unweighted: number; + total: number; +} + +export interface EvidenceResult { + constraints: ConstraintResult[]; + weightSummary: WeightSummary; + allPassing: boolean; + failCount: number; + warnCount: number; +} + +/** + * .adf.lock file format: flat JSON map of source filename -> sha256 prefix (16 hex chars). + * Generated by `charter adf sync --write`, checked by `charter adf sync --check`. + */ +export interface AdfLockfile { + [sourceFile: string]: string; +} + +export interface AdfSyncStatus { + source: string; + sourceHash: string; + lockedHash: string | null; + inSync: boolean; +}