Skip to content

P0-F: Williams Bound Policy Foundation (BLOCKS: all hotpath-aware modules) #17

@github-actions

Description

@github-actions

Why: The HotpathPolicy and SalienceEngine are the central source of truth for the Williams Bound architecture. Every subsequent module (ingest, query, hierarchy, Daydreamer) depends on them. Implementing these first ensures the bound is enforced from day one rather than retrofitted.

  • P0-F1: Implement core/HotpathPolicy.ts

    • computeCapacity(graphMass: number): number — H(t) = ⌈c · √(t · log₂(1+t))⌉
    • computeSalience(hebbianIn: number, recency: number, queryHits: number, weights?: SalienceWeights): number — σ = α·H_in + β·R + γ·Q
    • deriveTierQuotas(capacity: number, quotaRatios?: TierQuotaRatios): TierQuotas — allocate H(t) across shelf/volume/book/page tiers
    • deriveCommunityQuotas(tierBudget: number, communitySizes: number[]): number[] — proportional with min(1) guarantee
    • Export a frozen DEFAULT_HOTPATH_POLICY object containing all constants: c = 0.5, α = 0.5, β = 0.3, γ = 0.2, q_s = 0.10, q_v = 0.20, q_b = 0.20, q_p = 0.50
    • Keep strictly separate from core/ModelDefaults.ts (policy-derived ≠ model-derived)
  • P0-F2: Add HotpathPolicy test coverage (tests/HotpathPolicy.test.ts)

    • H(t) grows sublinearly: verify H(10_000) / 10_000 < H(1_000) / 1_000
    • H(t) is monotonically non-decreasing over a representative range: verify H(t+1) >= H(t) for each t in [0, 1, 2, 10, 100, 1_000, 10_000, 100_000]
    • H(t) is a finite integer ≥ 1 for edge inputs: t = 0, t = 1, t = Number.MAX_SAFE_INTEGER; result must never be NaN, Infinity, or < 1
    • Derived tier-quota counts sum exactly to capacity: deriveTierQuotas(cap).shelf + .volume + .book + .page === cap for cap in [1, 10, 100, 1_000]
    • Community quota counts sum exactly to tier_budget: sum(deriveCommunityQuotas(budget, sizes)) === budget for representative (budget, sizes) inputs including edge cases (budget = 0, empty sizes array, budget < sizes.length)
    • Community quotas never produce NaN, Infinity, or negative values for any valid input, including sizes with a single community or all equal sizes
    • Salience is deterministic for same inputs
    • Salience clamps output to a finite number: never NaN or Infinity for extreme weight or hit-count values
  • P0-F3: Extend core/types.ts

    • Add PageActivity interface: { pageId: Hash; queryHitCount: number; lastQueryAt: string; communityId?: string }
    • Add HotpathEntry interface: { entityId: Hash; tier: 'shelf' | 'volume' | 'book' | 'page'; salience: number; communityId?: string }
    • Add TierQuotas type: { shelf: number; volume: number; book: number; page: number }
    • Add hotpath method signatures to MetadataStore interface:
      • putHotpathEntry(entry: HotpathEntry): Promise<void>
      • getHotpathEntries(tier?: HotpathEntry['tier']): Promise<HotpathEntry[]>
      • evictWeakest(tier: HotpathEntry['tier'], communityId?: string): Promise<void>
      • getResidentCount(): Promise<number>
      • putPageActivity(activity: PageActivity): Promise<void>
      • getPageActivity(pageId: Hash): Promise<PageActivity | undefined>
  • P0-F4: Extend storage/IndexedDbMetadataStore.ts

    • Add hotpath_index object store keyed by entityId; secondary index by tier
    • Add page_activity object store keyed by pageId
    • Implement all six new MetadataStore hotpath methods
    • Extend tests/Persistence.test.ts with hotpath store tests:
      • put/get/evict cycle for HotpathEntry
      • put/get for PageActivity
      • getResidentCount returns correct value after multiple puts

Exit Criteria: HotpathPolicy module passes all tests; types.ts has hotpath interfaces; IndexedDB hotpath stores are implemented and tested.

Metadata

Metadata

Labels

P0: criticalCritical path — blocks all dependent worklayer: daydreamerBackground consolidation (LTP/LTD, recalc)

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions