diff options
| author | Bobby <[email protected]> | 2026-04-22 07:51:18 +0530 |
|---|---|---|
| committer | Bobby <[email protected]> | 2026-04-22 07:51:18 +0530 |
| commit | 6e8adbaabedba12e81bf0fdfe3dc42108255bd11 (patch) | |
| tree | 6d0cb2f5d6d029ea93432a1f906ab74bcdfb7917 | |
| parent | 22912c4af19b9055ed95779c4d16020fe3a449eb (diff) | |
| download | hollowdark-6e8adbaabedba12e81bf0fdfe3dc42108255bd11.tar.xz hollowdark-6e8adbaabedba12e81bf0fdfe3dc42108255bd11.zip | |
Migrate remaining relative imports to @hollowdark/*; strip //-comments and doc references, JSDoc-only
49 files changed, 190 insertions, 220 deletions
diff --git a/app/app.d.ts b/app/app.d.ts index a59afa2..242ec56 100644 --- a/app/app.d.ts +++ b/app/app.d.ts @@ -1,13 +1,6 @@ -// See https://svelte.dev/docs/kit/types#app.d.ts for details on these types. -// Populate App interfaces as systems come online. declare global { namespace App { - // interface Error {} - // interface Locals {} - // interface PageData {} - // interface PageState {} - // interface Platform {} } } diff --git a/engine/career/career.ts b/engine/career/career.ts index aa19584..e8a5af2 100644 --- a/engine/career/career.ts +++ b/engine/career/career.ts @@ -1,5 +1,5 @@ import type { GameTime } from '@hollowdark/time/gameTime' -import type { InstitutionId } from '../entities/base' +import type { InstitutionId } from '@hollowdark/engine/entities/base' export type CareerTrajectory = 'rising' | 'steady' | 'declining' | 'stalled' diff --git a/engine/economics/affordability.ts b/engine/economics/affordability.ts index ef57d3f..827ccd8 100644 --- a/engine/economics/affordability.ts +++ b/engine/economics/affordability.ts @@ -1,8 +1,7 @@ /** * The "What you could afford" surface on the Money screen. Hidden numbers * resolve into qualitative feasibility labels so the player answers - * "can I afford this?" without ever seeing a number (docs/09-economy.md - * §"The 'What you could afford' design"). + * "can I afford this?" without ever seeing a number. */ export type Feasibility = | 'comfortable' diff --git a/engine/economics/economic.ts b/engine/economics/economic.ts index 1197cde..2d37ced 100644 --- a/engine/economics/economic.ts +++ b/engine/economics/economic.ts @@ -1,9 +1,8 @@ /** - * Economic state. All numbers in "marks" (the world's universal currency). - * The player never sees any of these — they surface as prose and qualitative - * affordability context (docs/09-economy.md, ARCHITECTURE.md §14). + * A coarse wealth tier derived from the hidden economic state. Never + * displayed numerically; informs surface prose ("struggling", "comfortable", + * "old money"). */ - export type EconomicClass = | 'destitute' | 'struggling' @@ -44,6 +43,11 @@ export interface Debt { readonly apr: number } +/** + * Hidden economic state for a character. All numbers are in "marks" (the + * world's universal currency). Never surfaced to the player as digits — + * the simulation drives prose and qualitative affordability context. + */ export interface EconomicState { readonly cashOnHand: number readonly accounts: readonly Account[] diff --git a/engine/entities/base.ts b/engine/entities/base.ts index 84b9acf..c1cf6d8 100644 --- a/engine/entities/base.ts +++ b/engine/entities/base.ts @@ -4,7 +4,6 @@ import type { Brand } from '@hollowdark/utils/types/brand' /** * Branded IDs — string at runtime, distinct at compile time so a PersonId * can't silently flow into a slot that expects a RelationshipId. - * (utils/types/brand.ts) */ export type PersonId = Brand<string, 'PersonId'> export type RelationshipId = Brand<string, 'RelationshipId'> @@ -26,7 +25,6 @@ export type EntityKind = 'person' | 'relationship' | 'institution' | 'place' | ' * their specific id/kind pair — `Person extends BaseEntity<PersonId, 'person'>`. * `deterministicSeed` powers lazy Tier 3 regeneration: given the seed, the * entity's trajectory is fully reproducible without persisted state. - * (ARCHITECTURE.md §26) */ export interface BaseEntity<Id extends string = string, K extends EntityKind = EntityKind> { readonly id: Id diff --git a/engine/entities/event-log-entry.ts b/engine/entities/event-log-entry.ts index f31536d..1e107f4 100644 --- a/engine/entities/event-log-entry.ts +++ b/engine/entities/event-log-entry.ts @@ -1,5 +1,5 @@ import type { GameTime } from '@hollowdark/time/gameTime' -import type { EventLogEntryId, PersonId } from './base' +import type { EventLogEntryId, PersonId } from '@hollowdark/engine/entities/base' /** * Consequences logged against a specific event resolution. The shape is diff --git a/engine/entities/flow-entry.ts b/engine/entities/flow-entry.ts index bd781d5..ba2b11a 100644 --- a/engine/entities/flow-entry.ts +++ b/engine/entities/flow-entry.ts @@ -1,5 +1,5 @@ import type { GameTime } from '@hollowdark/time/gameTime' -import type { FlowEntryId, PersonId, PlaceId, WorldEventId } from './base' +import type { FlowEntryId, PersonId, PlaceId, WorldEventId } from '@hollowdark/engine/entities/base' /** * A compact snapshot of the context that produced a flow passage. Kept diff --git a/engine/entities/institution.ts b/engine/entities/institution.ts index 4b3c050..d89aac2 100644 --- a/engine/entities/institution.ts +++ b/engine/entities/institution.ts @@ -1,6 +1,6 @@ import type { GameTime } from '@hollowdark/time/gameTime' -import type { BaseEntity, InstitutionId, PersonId, PlaceId } from './base' -import type { CultureDescriptor } from './place' +import type { BaseEntity, InstitutionId, PersonId, PlaceId } from '@hollowdark/engine/entities/base' +import type { CultureDescriptor } from '@hollowdark/engine/entities/place' export type InstitutionType = | 'company' diff --git a/engine/entities/memoir.ts b/engine/entities/memoir.ts index c0f44f3..1f3f37f 100644 --- a/engine/entities/memoir.ts +++ b/engine/entities/memoir.ts @@ -1,5 +1,5 @@ import type { GameTime } from '@hollowdark/time/gameTime' -import type { EventLogEntryId, MemoirId, PersonId } from './base' +import type { EventLogEntryId, MemoirId, PersonId } from '@hollowdark/engine/entities/base' export interface MemoirChapter { readonly order: number @@ -12,9 +12,10 @@ export interface MemoirChapter { } /** - * Generated at character death. 15,000–30,000 words, 8–15 chapters. Persists - * forever in the world's archive; descendants may find it on the Memoirs - * shelf or referenced in flow (docs/14-memoirs.md, ARCHITECTURE.md §17). + * A character's generated life story. Produced at death, 15,000–30,000 + * words across 8–15 chapters. Persists forever in the world's archive; + * descendants may find it on the Memoirs shelf or see it referenced in + * their own flow. */ export interface Memoir { readonly id: MemoirId diff --git a/engine/entities/person-name.ts b/engine/entities/person-name.ts index 5f84b41..8c234dc 100644 --- a/engine/entities/person-name.ts +++ b/engine/entities/person-name.ts @@ -1,8 +1,8 @@ /** * A character's name as tracked by the simulation. Surnames follow - * inheritance rules per region/era (docs/19-names.md) — including keep- - * maiden, hyphenate, matrilineal, and ad-hoc changes — so the structure - * preserves both the current surname and the maiden form when relevant. + * inheritance rules per region and era — including keep-maiden, hyphenate, + * matrilineal, and ad-hoc changes — so the structure preserves both the + * current surname and the maiden form when relevant. */ export interface PersonName { readonly given: string diff --git a/engine/entities/person.ts b/engine/entities/person.ts index beabede..1dc28a1 100644 --- a/engine/entities/person.ts +++ b/engine/entities/person.ts @@ -1,26 +1,26 @@ import type { GameTime } from '@hollowdark/time/gameTime' -import type { CareerState } from '../career/career' -import type { EconomicState } from '../economics/economic' -import type { Condition, HealthState } from '../health/health' -import type { MentalHealthState } from '../health/mental-health' -import type { Dependency } from '../state/dependency' -import type { MoodState } from '../state/mood' -import type { SatisfactionProfile } from '../state/satisfaction' -import type { Scar } from '../state/scar' -import type { AttachmentDistribution } from '../traits/attachment' -import type { BigFiveProfile } from '../traits/big-five' -import type { CoreBeliefs } from '../traits/core-beliefs' -import type { DarkTriadProfile } from '../traits/dark-triad' -import type { SexualOrientation } from '../traits/orientation' -import type { ValuesOrientation } from '../traits/values' -import type { BaseEntity, PersonId, PlaceId, RelationshipId } from './base' -import type { EventLogEntry } from './event-log-entry' -import type { PersonName } from './person-name' -import type { ReputationProfile } from './reputation' -import type { ResidenceEntry } from './residence' -import type { StatusDescriptor } from './status' - -/** Modes of death per docs/20-death-textures.md. */ +import type { CareerState } from '@hollowdark/engine/career/career' +import type { EconomicState } from '@hollowdark/engine/economics/economic' +import type { Condition, HealthState } from '@hollowdark/engine/health/health' +import type { MentalHealthState } from '@hollowdark/engine/health/mental-health' +import type { Dependency } from '@hollowdark/engine/state/dependency' +import type { MoodState } from '@hollowdark/engine/state/mood' +import type { SatisfactionProfile } from '@hollowdark/engine/state/satisfaction' +import type { Scar } from '@hollowdark/engine/state/scar' +import type { AttachmentDistribution } from '@hollowdark/engine/traits/attachment' +import type { BigFiveProfile } from '@hollowdark/engine/traits/big-five' +import type { CoreBeliefs } from '@hollowdark/engine/traits/core-beliefs' +import type { DarkTriadProfile } from '@hollowdark/engine/traits/dark-triad' +import type { SexualOrientation } from '@hollowdark/engine/traits/orientation' +import type { ValuesOrientation } from '@hollowdark/engine/traits/values' +import type { BaseEntity, PersonId, PlaceId, RelationshipId } from '@hollowdark/engine/entities/base' +import type { EventLogEntry } from '@hollowdark/engine/entities/event-log-entry' +import type { PersonName } from '@hollowdark/engine/entities/person-name' +import type { ReputationProfile } from '@hollowdark/engine/entities/reputation' +import type { ResidenceEntry } from '@hollowdark/engine/entities/residence' +import type { StatusDescriptor } from '@hollowdark/engine/entities/status' + +/** The ten modes of death the simulation can resolve. */ export type DeathMode = | 'expected_old_age' | 'sudden_accident' @@ -35,7 +35,7 @@ export type DeathMode = /** * The defining demographic facts of a birth, captured in prose-ready form. * The familyContext string is the one-paragraph summary the opening scene - * draws on (docs/17-first-hour.md §"Birth moment"). + * draws on. */ export interface BirthRecord { readonly date: GameTime @@ -51,15 +51,15 @@ export interface DeathRecord { } /** - * NPC simulation fidelity tier. 1 = full weekly simulation (~10-30 entities), - * 2 = quarterly compressed, 3 = generated on demand from seed. - * See docs/06-autonomy.md §"Tiered simulation fidelity". + * NPC simulation fidelity tier. 1 = full weekly simulation (~10–30 + * close-orbit entities), 2 = quarterly compressed (dormant relatives, + * drifted friends), 3 = generated on demand from seed (everyone else). */ export type SimulationTier = 1 | 2 | 3 /** * Person — the main simulated entity. Players and NPCs share this shape. - * Fields are grouped by trait layer (docs/04-traits.md): + * Fields are grouped by trait layer: * * Layer 1 temperament (Big Five + Dark Triad) — mostly stable * Layer 2 developmental (attachment, core beliefs, values, orientation) @@ -75,65 +75,52 @@ export interface Person extends BaseEntity<PersonId, 'person'> { readonly birth: BirthRecord readonly death: DeathRecord | null - // Layer 1 — temperament readonly bigFive: BigFiveProfile readonly darkTriad: DarkTriadProfile - // Layer 2 — developmental readonly attachment: AttachmentDistribution readonly coreBeliefs: CoreBeliefs readonly conscienceCapacity: number readonly values: ValuesOrientation readonly orientation: SexualOrientation - // Layer 3 — fluctuating state readonly mood: MoodState readonly stress: number readonly energy: number readonly traumaLoad: number readonly satisfaction: SatisfactionProfile - // Layer 4 — acquired readonly skills: ReadonlyMap<string, number> readonly knowledge: ReadonlyMap<string, number> readonly habits: readonly string[] readonly dependencies: readonly Dependency[] readonly scars: readonly Scar[] - // Layer 5 — social readonly reputation: ReputationProfile readonly status: StatusDescriptor readonly networkCapital: number - // Health readonly health: HealthState readonly chronicConditions: readonly Condition[] readonly mentalHealthState: MentalHealthState - // Economic / career readonly economic: EconomicState readonly career: CareerState - // Relationships + location readonly relationshipIds: readonly RelationshipId[] readonly currentPlaceId: PlaceId readonly residenceHistory: readonly ResidenceEntry[] - // Simulation metadata readonly tier: SimulationTier readonly lastSimulatedAt: GameTime - // Event history readonly eventLog: readonly EventLogEntry[] readonly memorableMoments: readonly string[] - // Player-character flags readonly isPlayerCharacter: boolean readonly playerCharacterStartedAt: GameTime | null readonly playerCharacterEndedAt: GameTime | null - // Family (denormalised for fast access; the authoritative source is the - // Relationship entities keyed family_parent / family_child / family_spouse) readonly parentIds: readonly [PersonId | null, PersonId | null] readonly childIds: readonly PersonId[] readonly spouseIds: readonly PersonId[] diff --git a/engine/entities/place.ts b/engine/entities/place.ts index 2a38c41..8ec1f9b 100644 --- a/engine/entities/place.ts +++ b/engine/entities/place.ts @@ -1,4 +1,4 @@ -import type { BaseEntity, PersonId, PlaceId } from './base' +import type { BaseEntity, PersonId, PlaceId } from '@hollowdark/engine/entities/base' export type PlaceType = 'region' | 'city' | 'neighborhood' | 'specific_location' @@ -40,7 +40,6 @@ export interface Place extends BaseEntity<PlaceId, 'place'> { readonly type: PlaceType readonly parentPlaceId: PlaceId | null - // Present for regions and cities; null for specific locations. readonly culture: CultureDescriptor | null readonly climate: ClimateDescriptor | null readonly economy: EconomicCharacter | null @@ -48,7 +47,6 @@ export interface Place extends BaseEntity<PlaceId, 'place'> { readonly population: number - // Present for specific locations (houses, workplaces); null for containers. readonly ownerId: PersonId | null readonly currentResidents: readonly PersonId[] readonly propertyValue: number | null diff --git a/engine/entities/relationship.ts b/engine/entities/relationship.ts index ec00007..2a7710b 100644 --- a/engine/entities/relationship.ts +++ b/engine/entities/relationship.ts @@ -1,5 +1,5 @@ import type { GameTime } from '@hollowdark/time/gameTime' -import type { BaseEntity, PersonId, RelationshipId } from './base' +import type { BaseEntity, PersonId, RelationshipId } from '@hollowdark/engine/entities/base' export type RelationType = | 'family_parent' @@ -30,10 +30,9 @@ export type RelationType = export type RelationshipState = 'warm' | 'neutral' | 'strained' | 'ruptured' | 'dormant' /** - * The four axes of intimacy (docs/07-relationships.md §"Relationship state - * vector"). Each 0–1. Tracked separately because a marriage can be high - * on practical and low on emotional — that's a specific life texture, not - * a compatibility score. + * The four axes of intimacy. Each 0–1. Tracked separately because a + * marriage can be high on practical and low on emotional — that's a + * specific life texture, not a compatibility score. */ export interface IntimacyAxes { readonly emotional: number @@ -88,9 +87,9 @@ export interface LoveLanguageMatrix { } /** - * Asymmetric perception: A and B each have their own mental model of the - * relationship. Large asymmetries fire scenes (confession, rebuff, shocked - * realisation). See docs/07-relationships.md §"Asymmetric perception". + * Asymmetric perception: A and B each carry their own mental model of the + * relationship. Large asymmetries fire scenes — confession, rebuff, + * shocked realisation. */ export interface RelationshipPerception { readonly perceivedType: RelationType @@ -162,15 +161,12 @@ export interface Relationship extends BaseEntity<RelationshipId, 'relationship'> readonly lastInteractionAt: GameTime readonly interactionFrequency: number - // Romantic-only details; null when the relationship isn't romantic. readonly romanticPhase: RomanticPhase | null readonly sexualActivity: SexualActivityState | null readonly infidelityHistory: readonly InfidelityEvent[] readonly commitmentLevel: number - // Family-only. readonly familyRelationType: FamilyRelation | null - // Professional-only. readonly workRelationType: WorkRelation | null } diff --git a/engine/entities/residence.ts b/engine/entities/residence.ts index a052c42..83ddce8 100644 --- a/engine/entities/residence.ts +++ b/engine/entities/residence.ts @@ -1,5 +1,5 @@ import type { GameTime } from '@hollowdark/time/gameTime' -import type { PlaceId } from './base' +import type { PlaceId } from '@hollowdark/engine/entities/base' /** A span of time a character lived at a specific place. Open-ended if the * character still lives there. */ diff --git a/engine/entities/routine.ts b/engine/entities/routine.ts index 251cbde..a7068c1 100644 --- a/engine/entities/routine.ts +++ b/engine/entities/routine.ts @@ -1,5 +1,5 @@ import type { GameTime } from '@hollowdark/time/gameTime' -import type { PersonId, RoutineId } from './base' +import type { PersonId, RoutineId } from '@hollowdark/engine/entities/base' export type RoutineCategory = 'work' | 'relationships' | 'self' | 'home' | 'play' | 'service' @@ -27,7 +27,7 @@ export interface RoutineItem { /** * Persistent weekly commitments for a character. Routines run silently in * the flow stream — the player sets them once, they keep running until - * changed (docs/05-time-system.md §"Routines and flow"). + * changed. */ export interface Routine { readonly id: RoutineId diff --git a/engine/entities/scheduled-event.ts b/engine/entities/scheduled-event.ts index 08be670..254e979 100644 --- a/engine/entities/scheduled-event.ts +++ b/engine/entities/scheduled-event.ts @@ -1,10 +1,10 @@ import type { GameTime } from '@hollowdark/time/gameTime' -import type { PersonId, ScheduledEventId } from './base' +import type { PersonId, ScheduledEventId } from '@hollowdark/engine/entities/base' /** * A future event trigger, either at a fixed time or when conditions hold. * Taking a bribe at 30 might schedule a `bribery_audit` at +15 years with - * elevated weight (ARCHITECTURE.md §6 §"Scheduled events"). + * elevated weight. */ export interface ConditionalTrigger { readonly kind: 'conditional' diff --git a/engine/entities/world-event.ts b/engine/entities/world-event.ts index 8b4e2a6..ca158cc 100644 --- a/engine/entities/world-event.ts +++ b/engine/entities/world-event.ts @@ -1,5 +1,5 @@ import type { GameTime } from '@hollowdark/time/gameTime' -import type { BaseEntity, PersonId, PlaceId, WorldEventId } from './base' +import type { BaseEntity, PersonId, PlaceId, WorldEventId } from '@hollowdark/engine/entities/base' export type EventCategory = | 'pandemic' @@ -17,8 +17,8 @@ export type EventCategory = export type SeverityLevel = 'mild' | 'moderate' | 'severe' | 'catastrophic' /** - * A named macro event decorating the timeline. See docs/02-world-events.md. - * The character-level impact of each event is applied per-person via + * A named macro event decorating the timeline — a pandemic, war, cultural + * shift, economic crash. Character-level impact is applied per-person via * templates referenced by contentRef; this entity is the world-scale record. */ export interface WorldEvent extends BaseEntity<WorldEventId, 'world_event'> { diff --git a/engine/entities/world.ts b/engine/entities/world.ts index 920fe05..8d0b328 100644 --- a/engine/entities/world.ts +++ b/engine/entities/world.ts @@ -1,11 +1,11 @@ import type { GameTime } from '@hollowdark/time/gameTime' -import type { PersonId, PlaceId, WorldEventId, WorldId } from './base' -import type { ScheduledEvent } from './scheduled-event' +import type { PersonId, PlaceId, WorldEventId, WorldId } from '@hollowdark/engine/entities/base' +import type { ScheduledEvent } from '@hollowdark/engine/entities/scheduled-event' /** - * Macro economic state tracked at the world scale. Individual characters' - * economics are derived against this background (docs/09-economy.md - * §"Macro economy"). + * Macro economic state tracked at the world scale — inflation, employment, + * market index, recession depth. Individual characters' economics derive + * against this background. */ export interface MacroEconomicState { readonly inflationAnnual: number @@ -33,14 +33,14 @@ export interface CrisisState { } /** - * The world container. One continuous world per player (ARCHITECTURE.md §16, - * docs/16-world-continuity.md). Time in this world never resets once - * created; successive player characters advance it forward. + * The world container. One continuous world per player. Time in this world + * never resets once created; successive player characters advance it forward. + * `createdAt` is a real-world ISO timestamp, not a `GameTime`. */ export interface World { readonly id: WorldId readonly seed: string - readonly createdAt: string // ISO timestamp, real-world clock — not a GameTime + readonly createdAt: string readonly currentGameTime: GameTime diff --git a/engine/health/health.ts b/engine/health/health.ts index e08433d..4c69d34 100644 --- a/engine/health/health.ts +++ b/engine/health/health.ts @@ -41,10 +41,9 @@ export interface Condition { } /** - * A condition the simulation tracks but the character doesn't yet know about. - * Surface paths include worsening symptoms, doctor visits, routine screens, - * or incidental discovery (docs/08-mental-health.md §"Suicide risk" for the - * comparable mental-health pattern; this covers physical equivalents). + * A condition the simulation tracks but the character doesn't yet know + * about. Surface paths include worsening symptoms, doctor visits, routine + * screens, or incidental discovery. */ export interface UndiagnosedCondition { readonly id: string diff --git a/engine/health/mental-health.ts b/engine/health/mental-health.ts index 7130177..2e54e71 100644 --- a/engine/health/mental-health.ts +++ b/engine/health/mental-health.ts @@ -48,7 +48,7 @@ export interface Medication { /** * Hidden even from the character until crisis. The simulation knows; the - * prose surfaces behaviour, not numbers (docs/08-mental-health.md §"Suicide"). + * prose surfaces behaviour, never numbers. */ export interface SuicidalRisk { readonly current: number diff --git a/engine/state/dependency.ts b/engine/state/dependency.ts index 47787da..e3aca72 100644 --- a/engine/state/dependency.ts +++ b/engine/state/dependency.ts @@ -1,8 +1,7 @@ import type { GameTime } from '@hollowdark/time/gameTime' /** - * A substance or behavioural dependency at a given stage of progression. - * Stages mirror docs/08-mental-health.md §"Addiction modeled honestly": + * A substance or behavioural dependency at a given stage of progression: * experimentation → regular use → problem use → dependence → crisis → * recovery | chronic | death. */ diff --git a/engine/state/mood.ts b/engine/state/mood.ts index 501a699..205b5ec 100644 --- a/engine/state/mood.ts +++ b/engine/state/mood.ts @@ -4,7 +4,6 @@ import type { GameTime } from '@hollowdark/time/gameTime' * Current-week emotional state on the valence × arousal plane. * valence -1 (negative) to +1 (positive) * arousal -1 (calm) to +1 (activated) - * See docs/08-mental-health.md §"Separate variables". */ export interface MoodState { readonly valence: number diff --git a/engine/state/satisfaction.ts b/engine/state/satisfaction.ts index a10421b..eae65ec 100644 --- a/engine/state/satisfaction.ts +++ b/engine/state/satisfaction.ts @@ -1,8 +1,7 @@ /** * Life satisfaction split into hedonic (day-to-day pleasure) and eudaimonic - * (sense of meaning / purpose). They can diverge, and eudaimonic matters - * more for end-of-life peace (docs/13-spirituality.md §"Life satisfaction - * is distinct from happiness"). Each 0–1. + * (sense of meaning / purpose). They can diverge; eudaimonic matters more + * for end-of-life peace. Each 0–1. */ export interface SatisfactionProfile { readonly hedonic: number diff --git a/engine/traits/attachment.ts b/engine/traits/attachment.ts index 7af4c1b..eae77fa 100644 --- a/engine/traits/attachment.ts +++ b/engine/traits/attachment.ts @@ -1,7 +1,7 @@ /** * Attachment is tracked as a distribution, not a single tag. Fractions sum * to 1.0; a character is rarely purely one style. Set by age 3 based on - * caregiver behaviour, mostly fixed thereafter (docs/04-traits.md §"Layer 2"). + * caregiver behaviour, mostly fixed thereafter. */ export interface AttachmentDistribution { readonly secure: number diff --git a/engine/traits/big-five.ts b/engine/traits/big-five.ts index 425c91c..dbf5bd7 100644 --- a/engine/traits/big-five.ts +++ b/engine/traits/big-five.ts @@ -1,6 +1,6 @@ /** - * Big Five temperament profile, each 0–100. Mostly stable across a life - * with slow drift under sustained conditions. See docs/04-traits.md §"Layer 1". + * Big Five temperament profile. Each axis is 0–100, mostly stable across + * a life with slow drift under sustained conditions. */ export interface BigFiveProfile { readonly openness: number diff --git a/engine/traits/core-beliefs.ts b/engine/traits/core-beliefs.ts index 4e3b85a..f35daa0 100644 --- a/engine/traits/core-beliefs.ts +++ b/engine/traits/core-beliefs.ts @@ -1,6 +1,6 @@ /** - * Core beliefs shape how adult events are interpreted (docs/04-traits.md - * §"Layer 2"). Each 0–100. Formed in early childhood, harder to shift after. + * Core beliefs shape how adult events are interpreted. Each axis is 0–100, + * formed in early childhood and harder to shift after. */ export interface CoreBeliefs { readonly selfWorth: number diff --git a/engine/traits/dark-triad.ts b/engine/traits/dark-triad.ts index e8e1450..fff49c5 100644 --- a/engine/traits/dark-triad.ts +++ b/engine/traits/dark-triad.ts @@ -1,7 +1,7 @@ /** - * Dark Triad profile, each 0–100. Distribution is skewed low — most - * characters sit in the 20–40 range; a small minority above 60 drives - * specific life shapes (docs/04-traits.md §"Dark Triad characters in play"). + * Dark Triad profile. Each axis is 0–100. Distribution in the simulation + * skews low — most characters sit in the 20–40 range; a small minority + * above 60 drives specific life shapes. */ export interface DarkTriadProfile { readonly narcissism: number diff --git a/engine/traits/orientation.ts b/engine/traits/orientation.ts index 60decd9..e72a9cf 100644 --- a/engine/traits/orientation.ts +++ b/engine/traits/orientation.ts @@ -1,6 +1,6 @@ /** * Gender identity and sexual orientation. Continuous axes plus a discrete - * gender tag. See docs/04-traits.md §"Layer 2" and docs/10-sexuality.md. + * gender tag. * * sexualAttraction 0 = hetero-exclusive, 100 = homo-exclusive * romanticAttraction independent continuous axis diff --git a/engine/traits/values.ts b/engine/traits/values.ts index 0d67d16..83ae529 100644 --- a/engine/traits/values.ts +++ b/engine/traits/values.ts @@ -1,7 +1,7 @@ /** * Values orientation. Each axis is 0–100 where 0 anchors the left-named - * pole and 100 the right (e.g., tradition_vs_novelty: 0 = deeply traditional, - * 100 = novelty-seeking). See docs/04-traits.md §"Layer 2". + * pole and 100 the right (e.g., `tradition_vs_novelty`: 0 = deeply + * traditional, 100 = novelty-seeking). */ export interface ValuesOrientation { readonly tradition_vs_novelty: number diff --git a/hooks/client.ts b/hooks/client.ts index b65ecdc..844ac2c 100644 --- a/hooks/client.ts +++ b/hooks/client.ts @@ -1,9 +1,5 @@ -// Client-side setup runs once when the app mounts. -// Later: service worker registration, audio unlock on first gesture, -// persistent-storage request, IndexedDB hydration. Empty for now. import type { ClientInit } from '@sveltejs/kit' export const init: ClientInit = async () => { - // Intentionally empty. Systems attach here as they come online. } diff --git a/persistence/db.ts b/persistence/db.ts index 213e19b..d8647b0 100644 --- a/persistence/db.ts +++ b/persistence/db.ts @@ -20,7 +20,7 @@ import { CONTENT_CACHE_SCHEMA_V1, USER_DATA_DB_NAME, USER_DATA_SCHEMA_V1 -} from './schema' +} from '@hollowdark/persistence/schema' /** * A single key/value pair on the Settings table. Keys are short slugs @@ -62,8 +62,8 @@ export interface CachedAudioTrack { /** * User save data — the player's world(s). Persists forever on device, - * untouched by content updates (technical/04-persistence.md §"Core - * decisions"). Changes to this schema require a migration. + * untouched by content updates. Changes to this schema require a + * migration in `persistence/migrations` (added later). */ export class HollowdarkUserData extends Dexie { worlds!: Table<World, string> @@ -88,7 +88,7 @@ export class HollowdarkUserData extends Dexie { /** * Content cache — the compiled JSON chunks the client fetched from the * CDN. Independently versioned from user data; can be cleared without - * touching saves (ARCHITECTURE.md §3). + * touching saves. */ export class HollowdarkContentCache extends Dexie { content!: Table<CachedContentChunk, string> diff --git a/persistence/schema.ts b/persistence/schema.ts index 4d11edd..8d381d0 100644 --- a/persistence/schema.ts +++ b/persistence/schema.ts @@ -1,23 +1,17 @@ /** - * IndexedDB schema strings for each of the three Dexie databases. + * IndexedDB schema for the user-data database. The string values follow + * Dexie's index notation: * - * The schema is versioned deliberately — any change here requires a - * migration in persistence/migrations.ts (added later). Snapshot tests - * lock these strings so accidental drift shows up as a failing test - * rather than a silent mismatch between code and on-device data. - * - * Index syntax recap: * &field primary key (unique) * ++id auto-incrementing primary key * field plain index on a scalar * [a+b] compound index * *field multi-entry index on an array field * - * See ARCHITECTURE.md §24 for the user-data schema and §7 for the content - * cache; technical/04-persistence.md for the two-database separation - * (user data persists forever, content is replaceable per update). + * Frozen at module load so a runtime typo on the wrong key throws rather + * than silently mutating the schema object. Snapshot tests lock these + * strings; any change here requires a migration. */ - export const USER_DATA_SCHEMA_V1 = Object.freeze({ worlds: '&id, seed, currentPlayerCharacterId', people: @@ -35,16 +29,19 @@ export const USER_DATA_SCHEMA_V1 = Object.freeze({ settings: '&key' }) +/** IndexedDB schema for the content cache — replaceable per content update. */ export const CONTENT_CACHE_SCHEMA_V1 = Object.freeze({ content: '&chunkId, version, fetchedAt', manifest: '&id' }) +/** IndexedDB schema for the audio cache — blobs + a manifest row. */ export const AUDIO_CACHE_SCHEMA_V1 = Object.freeze({ audio: '&trackId, version, fetchedAt', manifest: '&id' }) +/** Current persistence schema version. Bump when any schema above changes. */ export const SCHEMA_VERSION = 1 as const export const USER_DATA_DB_NAME = 'HollowdarkUserData' as const diff --git a/rng/seeded.ts b/rng/seeded.ts index 52c4719..6d9f991 100644 --- a/rng/seeded.ts +++ b/rng/seeded.ts @@ -1,13 +1,12 @@ -import { deriveSeed, hashString } from './derive' +import { deriveSeed, hashString } from '@hollowdark/rng/derive' /** * Seeded PRNG. All gameplay randomness routes through this interface — - * Math.random is forbidden in gameplay code (see ARCHITECTURE.md §26 - * and eslint.config.js). + * Math.random is forbidden in gameplay code (see the ESLint rule). * * Guarantees: * - Same seed produces the same infinite sequence, bit-for-bit. - * - sub(label) produces a deterministic child stream, independent of + * - `sub(label)` produces a deterministic child stream, independent of * how the parent stream is consumed. * - Byte-level reproducibility across runs and machines. */ @@ -101,8 +100,6 @@ class SeededRNGImpl implements SeededRNG { cumulative += weight if (roll < cumulative) return value } - // Numerical safety: if we fall off the end due to floating-point drift, - // return the last item rather than throw. return items[items.length - 1]![0] } diff --git a/routes/+layout.svelte b/routes/+layout.svelte index d62f17d..35fb2d7 100644 --- a/routes/+layout.svelte +++ b/routes/+layout.svelte @@ -1,5 +1,4 @@ <script lang="ts"> - // Global CSS is loaded from static/css/app.css via <link> in app/app.html. let { children } = $props() </script> diff --git a/routes/+layout.ts b/routes/+layout.ts index 0b9e7c5..a032602 100644 --- a/routes/+layout.ts +++ b/routes/+layout.ts @@ -1,3 +1,2 @@ -// Pre-render everything. Static output matches adapter-static. export const prerender = true export const ssr = false diff --git a/routes/+page.svelte b/routes/+page.svelte index 00e0ed0..eeff5b2 100644 --- a/routes/+page.svelte +++ b/routes/+page.svelte @@ -1,5 +1,4 @@ <script lang="ts"> - // Main play screen. Placeholder until the flow stream is wired up in step 4+. </script> <main class="placeholder"> diff --git a/tests/determinism/rng.test.ts b/tests/determinism/rng.test.ts index 57a1e10..5d003b0 100644 --- a/tests/determinism/rng.test.ts +++ b/tests/determinism/rng.test.ts @@ -157,8 +157,6 @@ describe('createRNG — output shape', () => { ]) if (pick === 'rare') lowCount++ } - // Expected ~5, allow plenty of slack for variance; just confirm the - // distribution isn't inverted. expect(lowCount).toBeLessThan(50) }) @@ -212,15 +210,9 @@ describe('SeededRNG.sub — sub-RNG derivation', () => { }) describe('byte-level determinism snapshot', () => { - // Locks the PRNG implementation. Saved worlds depend on exact byte - // reproduction — if this test breaks, it means the PRNG changed, and - // every existing save relying on this seed will diverge. Treat failure - // as a migration concern, not a "just update the snapshot" fix. test('createRNG("hollowdark").next() × 5 matches canonical sequence', () => { const rng = createRNG('hollowdark') const first5 = [rng.next(), rng.next(), rng.next(), rng.next(), rng.next()] - // Values computed from the current mulberry32 + xmur3 implementation. - // Reproducible locally via: createRNG('hollowdark').next() × 5. expect(first5).toMatchInlineSnapshot(` [ 0.14088608953170478, diff --git a/tests/unit/time/calendar.test.ts b/tests/unit/time/calendar.test.ts index ee8d789..efbec97 100644 --- a/tests/unit/time/calendar.test.ts +++ b/tests/unit/time/calendar.test.ts @@ -72,10 +72,10 @@ describe('monthSeason', () => { }) test('specific month → season mappings', () => { - expect(monthSeason(1)).toBe('spring') // Thawing - expect(monthSeason(4)).toBe('summer') // Highsun - expect(monthSeason(7)).toBe('autumn') // Firstfall - expect(monthSeason(10)).toBe('winter') // Rainfall + expect(monthSeason(1)).toBe('spring') + expect(monthSeason(4)).toBe('summer') + expect(monthSeason(7)).toBe('autumn') + expect(monthSeason(10)).toBe('winter') expect(monthSeason(13)).toBe('festival') }) }) diff --git a/tests/unit/time/gameTime.test.ts b/tests/unit/time/gameTime.test.ts index ca6f4b1..9503e60 100644 --- a/tests/unit/time/gameTime.test.ts +++ b/tests/unit/time/gameTime.test.ts @@ -137,7 +137,6 @@ describe('addWeeks', () => { }) test('52 weeks lands in the festival, not at next year', () => { - // 52 × 7 = 364 days; Thawing 1 + 364 = Festival 5 (day 365 - 1) expect(addWeeks(makeGameTime(1111, 1, 1), 52)).toMatchObject({ year: 1111, month: 13, @@ -146,8 +145,6 @@ describe('addWeeks', () => { }) test('negative weeks moves backward', () => { - // Greening 1 (doy 31) minus 7 days = Thawing 24 (doy 24). - // Months are 30 days in this calendar, not 31. expect(addWeeks(makeGameTime(1111, 2, 1), -1)).toMatchObject({ year: 1111, month: 1, @@ -174,7 +171,6 @@ describe('addMonths', () => { }) test('overflow into next year wraps through the 13-month cycle', () => { - // Rimefrost 15 + 2 months → Festival → Thawing next year, day preserved (15) expect(addMonths(makeGameTime(1111, 12, 15), 2)).toMatchObject({ year: 1112, month: 1, diff --git a/tests/unit/utils/result.test.ts b/tests/unit/utils/result.test.ts index bdd4923..49cf86f 100644 --- a/tests/unit/utils/result.test.ts +++ b/tests/unit/utils/result.test.ts @@ -67,7 +67,6 @@ describe('type-narrowing', () => { test('isOk narrows to Ok<T>', () => { const r: Result<number, string> = ok(10) if (isOk(r)) { - // Type-level check — if isOk doesn't narrow, this line fails to compile. const n: number = r.value expect(n).toBe(10) } else { diff --git a/time/calendar.ts b/time/calendar.ts index ce61de4..e2f229f 100644 --- a/time/calendar.ts +++ b/time/calendar.ts @@ -1,8 +1,7 @@ /** - * The Hollowdark calendar: 12 months × 30 days + a 5-day year-end festival, - * 365 days per year, 7-day weeks. + * Number of days in a regular month. * - * Month order (per docs/01-world.md and style-bible/00-style-bible.md): + * Month order: * * spring 1 Thawing 2 Greening 3 Blossomtide * summer 4 Highsun 5 Amberhaze 6 Harvestmark @@ -10,20 +9,30 @@ * winter 10 Rainfall 11 Hollowdark 12 Rimefrost * festival 13 Year's End Festival (5 days) * - * The year begins with Thawing (spring) and closes with the festival, - * which sits between Rimefrost and the next year's Thawing. This matches - * the style bible's cold-half / warm-half grouping and the "year-end - * festival" phrasing in world lore. + * The year begins with Thawing and closes with the festival, which sits + * between Rimefrost and the next year's Thawing. */ - export const DAYS_PER_MONTH = 30 + +/** Twelve named months — all except the festival. */ export const REGULAR_MONTH_COUNT = 12 + +/** Days in the Year's End Festival — the thirteenth "month". */ export const FESTIVAL_DAYS = 5 + +/** Month index for the festival. */ export const FESTIVAL_MONTH = 13 -export const MONTHS_PER_YEAR = REGULAR_MONTH_COUNT + 1 // 12 regular + festival -export const DAYS_PER_YEAR = REGULAR_MONTH_COUNT * DAYS_PER_MONTH + FESTIVAL_DAYS // 365 + +/** Total month slots in the calendar cycle (12 regular + festival). */ +export const MONTHS_PER_YEAR = REGULAR_MONTH_COUNT + 1 + +/** Days in a year: 12 × 30 + 5 = 365. */ +export const DAYS_PER_YEAR = REGULAR_MONTH_COUNT * DAYS_PER_MONTH + FESTIVAL_DAYS + +/** Seven-day weeks. */ export const DAYS_PER_WEEK = 7 +/** Month names in calendar order. Index 0 is Thawing; index 12 is the festival. */ export const MONTH_NAMES = [ 'Thawing', 'Greening', @@ -40,23 +49,25 @@ export const MONTH_NAMES = [ "Year's End Festival" ] as const +/** The named-month type derived from `MONTH_NAMES`. */ export type MonthName = (typeof MONTH_NAMES)[number] +/** Four regular seasons plus a distinct `festival` tag for the year-end. */ export type Season = 'spring' | 'summer' | 'autumn' | 'winter' | 'festival' const SEASON_BY_MONTH: readonly Season[] = [ - 'spring', // Thawing - 'spring', // Greening - 'spring', // Blossomtide - 'summer', // Highsun - 'summer', // Amberhaze - 'summer', // Harvestmark - 'autumn', // Firstfall - 'autumn', // Stormturn - 'autumn', // Ashfall - 'winter', // Rainfall - 'winter', // Hollowdark - 'winter', // Rimefrost + 'spring', + 'spring', + 'spring', + 'summer', + 'summer', + 'summer', + 'autumn', + 'autumn', + 'autumn', + 'winter', + 'winter', + 'winter', 'festival' ] @@ -66,21 +77,33 @@ function validateMonth(monthIndex: number): void { } } +/** + * Return the named month for a 1-based month index. Throws on invalid input. + * @param monthIndex 1 (Thawing) through 13 (Year's End Festival). + */ export function monthName(monthIndex: number): MonthName { validateMonth(monthIndex) return MONTH_NAMES[monthIndex - 1] as MonthName } +/** + * Return the season label for a 1-based month index. The festival has its + * own tag ('festival') rather than reusing one of the four seasons. + */ export function monthSeason(monthIndex: number): Season { validateMonth(monthIndex) return SEASON_BY_MONTH[monthIndex - 1] as Season } +/** + * Days in the given month. 30 for regular months, 5 for the festival. + */ export function daysInMonth(monthIndex: number): number { validateMonth(monthIndex) return monthIndex === FESTIVAL_MONTH ? FESTIVAL_DAYS : DAYS_PER_MONTH } +/** True when the supplied month index is the festival slot. */ export function isFestival(monthIndex: number): boolean { return monthIndex === FESTIVAL_MONTH } diff --git a/time/gameTime.ts b/time/gameTime.ts index 2f2fed7..adebc4f 100644 --- a/time/gameTime.ts +++ b/time/gameTime.ts @@ -8,16 +8,15 @@ import { REGULAR_MONTH_COUNT, daysInMonth, monthName -} from './calendar' +} from '@hollowdark/time/calendar' /** * A position in game time. Immutable — all arithmetic returns a new value. * - * year integer (negative allowed for pre-1111 historical events) + * year integer (negative allowed for pre-epoch historical events) * month 1..12 for regular months, 13 for year-end festival * day 1..30 for regular months, 1..5 for festival * tickOfDay 0 outside crisis mode; crisis mode subdivides the day - * (docs/22-crisis-mode.md) */ export interface GameTime { readonly year: number @@ -61,23 +60,21 @@ function absoluteDays(time: GameTime): number { } function fromAbsoluteDays(abs: number, tickOfDay: number): GameTime { - // Guard against non-integer arithmetic drift — time is whole days only, - // tickOfDay handles sub-day resolution in crisis mode. if (!Number.isFinite(abs)) { throw new Error(`Non-finite absolute day count: ${abs}`) } const year = Math.floor(abs / DAYS_PER_YEAR) - const rem = abs - year * DAYS_PER_YEAR // 0..364 - const doy = rem + 1 // 1..365 - const festivalStart = REGULAR_MONTH_COUNT * DAYS_PER_MONTH + 1 // 361 + const rem = abs - year * DAYS_PER_YEAR + const doy = rem + 1 + const festivalStart = REGULAR_MONTH_COUNT * DAYS_PER_MONTH + 1 let month: number let day: number if (doy >= festivalStart) { month = FESTIVAL_MONTH - day = doy - festivalStart + 1 // 1..5 + day = doy - festivalStart + 1 } else { - month = Math.floor((doy - 1) / DAYS_PER_MONTH) + 1 // 1..12 - day = ((doy - 1) % DAYS_PER_MONTH) + 1 // 1..30 + month = Math.floor((doy - 1) / DAYS_PER_MONTH) + 1 + day = ((doy - 1) % DAYS_PER_MONTH) + 1 } return { year, month, day, tickOfDay } } @@ -105,7 +102,6 @@ export function addMonths(time: GameTime, months: number): GameTime { if (!Number.isInteger(months)) { throw new Error(`addMonths requires an integer (got ${months})`) } - // Zero-based cycle arithmetic: months are 1..13, so we work in 0..12. const totalCycles = (time.month - 1) + months const yearDelta = Math.floor(totalCycles / MONTHS_PER_YEAR) const monthIndex = ((totalCycles % MONTHS_PER_YEAR) + MONTHS_PER_YEAR) % MONTHS_PER_YEAR @@ -171,7 +167,6 @@ export function toAbsoluteDays(time: GameTime): number { return absoluteDays(time) } -// Re-exports for convenience at the 'time' import. export { DAYS_PER_MONTH, DAYS_PER_WEEK, diff --git a/time/granularity.ts b/time/granularity.ts index 0643c47..1acb122 100644 --- a/time/granularity.ts +++ b/time/granularity.ts @@ -1,12 +1,7 @@ /** - * Tick granularity by life stage. - * - * One tick represents a different span of time depending on the character's - * age — infancy advances in years because there isn't weekly texture worth - * resolving, adulthood in weeks because that's the rhythm the design lives - * at. See docs/05-time-system.md and ARCHITECTURE.md §5. + * The eight life stages a character moves through. Used to pick how much + * wall-clock time one simulation tick represents at a given age. */ - export type LifeStage = | 'infancy' | 'early_childhood' @@ -17,8 +12,15 @@ export type LifeStage = | 'late_adult' | 'elderly' +/** How much game time one tick advances. */ export type TickUnit = 'year' | 'season' | 'month' | 'week' +/** + * Tick granularity per life stage. Infancy advances in years because + * there isn't weekly texture worth resolving; adulthood in weeks because + * that's the rhythm the design lives at; elderly in months as the pace + * slows again. + */ export const TICK_UNIT_BY_LIFE_STAGE: Readonly<Record<LifeStage, TickUnit>> = { infancy: 'year', early_childhood: 'season', @@ -30,6 +32,9 @@ export const TICK_UNIT_BY_LIFE_STAGE: Readonly<Record<LifeStage, TickUnit>> = { elderly: 'month' } +/** + * Bucket an age in whole years into its life stage. Throws on negative age. + */ export function lifeStageForAge(ageYears: number): LifeStage { if (ageYears < 0) throw new Error(`Invalid age: ${ageYears}`) if (ageYears < 3) return 'infancy' @@ -42,6 +47,7 @@ export function lifeStageForAge(ageYears: number): LifeStage { return 'elderly' } +/** Shortcut: map an age directly to its tick unit. */ export function tickUnitForAge(ageYears: number): TickUnit { return TICK_UNIT_BY_LIFE_STAGE[lifeStageForAge(ageYears)] } diff --git a/time/speed.ts b/time/speed.ts index 9a9bb11..d5cba2e 100644 --- a/time/speed.ts +++ b/time/speed.ts @@ -1,11 +1,11 @@ /** - * Player-controlled simulation speed. Only three states ever exist - * (docs/05-time-system.md): time is stopped, running at reading pace, - * or running fast with compressed flow. - * - * Scenes auto-set the effective speed to 'paused'; the intended speed is - * preserved so the simulation returns to it when the scene resolves. + * Player-controlled simulation speed. Only three states ever exist: time + * is stopped, running at reading pace, or running fast with compressed + * flow. Scenes auto-set the effective speed to `paused`; the intended + * speed is preserved so the simulation returns to it when the scene + * resolves. */ export type Speed = 'paused' | 'play' | 'fast' +/** The three speeds, in canonical order. */ export const SPEEDS: readonly Speed[] = ['paused', 'play', 'fast'] diff --git a/utils/result/constructors.ts b/utils/result/constructors.ts index b0ed958..6fec0f4 100644 --- a/utils/result/constructors.ts +++ b/utils/result/constructors.ts @@ -1,4 +1,4 @@ -import type { Err, Ok } from './types' +import type { Err, Ok } from '@hollowdark/utils/result/types' export function ok<T>(value: T): Ok<T> { return { ok: true, value } diff --git a/utils/result/map.ts b/utils/result/map.ts index 9cf44a1..6d8697e 100644 --- a/utils/result/map.ts +++ b/utils/result/map.ts @@ -1,5 +1,5 @@ -import { err, ok } from './constructors' -import type { Result } from './types' +import { err, ok } from '@hollowdark/utils/result/constructors' +import type { Result } from '@hollowdark/utils/result/types' /** Map the value of an ok result; pass errors through unchanged. */ export function mapResult<T, U, E>(r: Result<T, E>, f: (value: T) => U): Result<U, E> { diff --git a/utils/result/predicates.ts b/utils/result/predicates.ts index 315eb0d..16e37af 100644 --- a/utils/result/predicates.ts +++ b/utils/result/predicates.ts @@ -1,4 +1,4 @@ -import type { Err, Ok, Result } from './types' +import type { Err, Ok, Result } from '@hollowdark/utils/result/types' export function isOk<T, E>(r: Result<T, E>): r is Ok<T> { return r.ok diff --git a/utils/result/types.ts b/utils/result/types.ts index ee95c08..e22856f 100644 --- a/utils/result/types.ts +++ b/utils/result/types.ts @@ -8,7 +8,7 @@ export type Err<E> = { readonly ok: false; readonly error: E } * Result<T, E> — a recoverable-error return type for functions that can * fail without throwing. Used at system boundaries (save/load, content * validation, manifest fetch) where the caller needs to decide whether a - * failure is fatal. Internal pure logic uses plain returns and throws - * Error for programmer errors (rules/01-code-style.md). + * failure is fatal. Internal pure logic still throws `Error` for + * programmer errors. */ export type Result<T, E = Error> = Ok<T> | Err<E> diff --git a/utils/result/unwrap.ts b/utils/result/unwrap.ts index 84e658e..8f980dd 100644 --- a/utils/result/unwrap.ts +++ b/utils/result/unwrap.ts @@ -1,4 +1,4 @@ -import type { Result } from './types' +import type { Result } from '@hollowdark/utils/result/types' /** * Extract the value from an ok result; throw on error. Reserve for tests |
