@vue-skuilder/db 0.1.22 → 0.1.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. package/dist/{contentSource-BP9hznNV.d.ts → contentSource-BotbOOfX.d.ts} +227 -3
  2. package/dist/{contentSource-DsJadoBU.d.cts → contentSource-C90LH-OH.d.cts} +227 -3
  3. package/dist/core/index.d.cts +220 -6
  4. package/dist/core/index.d.ts +220 -6
  5. package/dist/core/index.js +2052 -559
  6. package/dist/core/index.js.map +1 -1
  7. package/dist/core/index.mjs +2035 -555
  8. package/dist/core/index.mjs.map +1 -1
  9. package/dist/{dataLayerProvider-CHYrQ5pB.d.cts → dataLayerProvider-DGKp4zFB.d.cts} +1 -1
  10. package/dist/{dataLayerProvider-MDTxXq2l.d.ts → dataLayerProvider-SBpz9jQf.d.ts} +1 -1
  11. package/dist/impl/couch/index.d.cts +11 -3
  12. package/dist/impl/couch/index.d.ts +11 -3
  13. package/dist/impl/couch/index.js +1811 -574
  14. package/dist/impl/couch/index.js.map +1 -1
  15. package/dist/impl/couch/index.mjs +1792 -550
  16. package/dist/impl/couch/index.mjs.map +1 -1
  17. package/dist/impl/static/index.d.cts +4 -4
  18. package/dist/impl/static/index.d.ts +4 -4
  19. package/dist/impl/static/index.js +1797 -560
  20. package/dist/impl/static/index.js.map +1 -1
  21. package/dist/impl/static/index.mjs +1789 -547
  22. package/dist/impl/static/index.mjs.map +1 -1
  23. package/dist/{index-Dj0SEgk3.d.ts → index-BWvO-_rJ.d.ts} +1 -1
  24. package/dist/{index-B_j6u5E4.d.cts → index-Ba7hYbHj.d.cts} +1 -1
  25. package/dist/index.d.cts +150 -12
  26. package/dist/index.d.ts +150 -12
  27. package/dist/index.js +2658 -791
  28. package/dist/index.js.map +1 -1
  29. package/dist/index.mjs +2584 -747
  30. package/dist/index.mjs.map +1 -1
  31. package/dist/{types-DQaXnuoc.d.ts → types-CJrLM1Ew.d.ts} +1 -1
  32. package/dist/{types-Bn0itutr.d.cts → types-W8n-B6HG.d.cts} +1 -1
  33. package/dist/{types-legacy-DDY4N-Uq.d.cts → types-legacy-JXDxinpU.d.cts} +5 -1
  34. package/dist/{types-legacy-DDY4N-Uq.d.ts → types-legacy-JXDxinpU.d.ts} +5 -1
  35. package/dist/util/packer/index.d.cts +3 -3
  36. package/dist/util/packer/index.d.ts +3 -3
  37. package/docs/brainstorm-navigation-paradigm.md +40 -34
  38. package/docs/future-orchestration-vision.md +216 -0
  39. package/docs/navigators-architecture.md +188 -5
  40. package/docs/todo-strategy-authoring.md +8 -6
  41. package/package.json +3 -3
  42. package/src/core/index.ts +2 -0
  43. package/src/core/interfaces/contentSource.ts +7 -0
  44. package/src/core/interfaces/userDB.ts +6 -0
  45. package/src/core/navigators/Pipeline.ts +46 -0
  46. package/src/core/navigators/PipelineAssembler.ts +14 -1
  47. package/src/core/navigators/filters/WeightedFilter.ts +141 -0
  48. package/src/core/navigators/filters/types.ts +4 -0
  49. package/src/core/navigators/generators/CompositeGenerator.ts +61 -19
  50. package/src/core/navigators/generators/types.ts +4 -0
  51. package/src/core/navigators/index.ts +194 -13
  52. package/src/core/orchestration/gradient.ts +133 -0
  53. package/src/core/orchestration/index.ts +210 -0
  54. package/src/core/orchestration/learning.ts +250 -0
  55. package/src/core/orchestration/recording.ts +92 -0
  56. package/src/core/orchestration/signal.ts +67 -0
  57. package/src/core/types/contentNavigationStrategy.ts +38 -0
  58. package/src/core/types/learningState.ts +77 -0
  59. package/src/core/types/types-legacy.ts +4 -0
  60. package/src/core/types/userOutcome.ts +51 -0
  61. package/src/courseConfigRegistration.ts +546 -0
  62. package/src/factory.ts +6 -0
  63. package/src/impl/common/BaseUserDB.ts +16 -0
  64. package/src/index.ts +2 -0
  65. package/src/study/SessionController.ts +64 -1
  66. package/tests/core/navigators/Pipeline.test.ts +2 -0
  67. package/docs/todo-evolutionary-orchestration.md +0 -310
@@ -1,5 +1,5 @@
1
1
  import { CourseConfig } from '@vue-skuilder/common';
2
- import { D as DocType } from './types-legacy-DDY4N-Uq.js';
2
+ import { D as DocType } from './types-legacy-JXDxinpU.js';
3
3
 
4
4
  interface StaticCourseManifest {
5
5
  version: string;
@@ -1,5 +1,5 @@
1
1
  import { CourseConfig } from '@vue-skuilder/common';
2
- import { D as DocType } from './types-legacy-DDY4N-Uq.cjs';
2
+ import { D as DocType } from './types-legacy-JXDxinpU.cjs';
3
3
 
4
4
  interface StaticCourseManifest {
5
5
  version: string;
@@ -14,7 +14,9 @@ declare enum DocType {
14
14
  SCHEDULED_CARD = "SCHEDULED_CARD",
15
15
  TAG = "TAG",
16
16
  NAVIGATION_STRATEGY = "NAVIGATION_STRATEGY",
17
- STRATEGY_STATE = "STRATEGY_STATE"
17
+ STRATEGY_STATE = "STRATEGY_STATE",
18
+ USER_OUTCOME = "USER_OUTCOME",
19
+ STRATEGY_LEARNING_STATE = "STRATEGY_LEARNING_STATE"
18
20
  }
19
21
  interface QualifiedCardID {
20
22
  courseID: string;
@@ -91,6 +93,8 @@ declare const DocTypePrefixes: {
91
93
  readonly PEDAGOGY: "PEDAGOGY";
92
94
  readonly NAVIGATION_STRATEGY: "NAVIGATION_STRATEGY";
93
95
  readonly STRATEGY_STATE: "STRATEGY_STATE";
96
+ readonly USER_OUTCOME: "USER_OUTCOME";
97
+ readonly STRATEGY_LEARNING_STATE: "STRATEGY_LEARNING_STATE";
94
98
  };
95
99
  interface CardHistory<T extends CardRecord> {
96
100
  _id: PouchDB.Core.DocumentId;
@@ -14,7 +14,9 @@ declare enum DocType {
14
14
  SCHEDULED_CARD = "SCHEDULED_CARD",
15
15
  TAG = "TAG",
16
16
  NAVIGATION_STRATEGY = "NAVIGATION_STRATEGY",
17
- STRATEGY_STATE = "STRATEGY_STATE"
17
+ STRATEGY_STATE = "STRATEGY_STATE",
18
+ USER_OUTCOME = "USER_OUTCOME",
19
+ STRATEGY_LEARNING_STATE = "STRATEGY_LEARNING_STATE"
18
20
  }
19
21
  interface QualifiedCardID {
20
22
  courseID: string;
@@ -91,6 +93,8 @@ declare const DocTypePrefixes: {
91
93
  readonly PEDAGOGY: "PEDAGOGY";
92
94
  readonly NAVIGATION_STRATEGY: "NAVIGATION_STRATEGY";
93
95
  readonly STRATEGY_STATE: "STRATEGY_STATE";
96
+ readonly USER_OUTCOME: "USER_OUTCOME";
97
+ readonly STRATEGY_LEARNING_STATE: "STRATEGY_LEARNING_STATE";
94
98
  };
95
99
  interface CardHistory<T extends CardRecord> {
96
100
  _id: PouchDB.Core.DocumentId;
@@ -1,5 +1,5 @@
1
- export { A as AttachmentData, C as ChunkMetadata, D as DesignDocument, I as IndexMetadata, a as PackedCourseData, P as PackerConfig, S as StaticCourseManifest } from '../../types-Bn0itutr.cjs';
2
- export { C as CouchDBToStaticPacker } from '../../index-B_j6u5E4.cjs';
1
+ export { A as AttachmentData, C as ChunkMetadata, D as DesignDocument, I as IndexMetadata, a as PackedCourseData, P as PackerConfig, S as StaticCourseManifest } from '../../types-W8n-B6HG.cjs';
2
+ export { C as CouchDBToStaticPacker } from '../../index-Ba7hYbHj.cjs';
3
3
  import '@vue-skuilder/common';
4
- import '../../types-legacy-DDY4N-Uq.cjs';
4
+ import '../../types-legacy-JXDxinpU.cjs';
5
5
  import 'moment';
@@ -1,5 +1,5 @@
1
- export { A as AttachmentData, C as ChunkMetadata, D as DesignDocument, I as IndexMetadata, a as PackedCourseData, P as PackerConfig, S as StaticCourseManifest } from '../../types-DQaXnuoc.js';
2
- export { C as CouchDBToStaticPacker } from '../../index-Dj0SEgk3.js';
1
+ export { A as AttachmentData, C as ChunkMetadata, D as DesignDocument, I as IndexMetadata, a as PackedCourseData, P as PackerConfig, S as StaticCourseManifest } from '../../types-CJrLM1Ew.js';
2
+ export { C as CouchDBToStaticPacker } from '../../index-BWvO-_rJ.js';
3
3
  import '@vue-skuilder/common';
4
- import '../../types-legacy-DDY4N-Uq.js';
4
+ import '../../types-legacy-JXDxinpU.js';
5
5
  import 'moment';
@@ -1,6 +1,10 @@
1
1
  # Brainstorm: Navigation Paradigm Exploration
2
2
 
3
3
  > **Status:** Informal brainstorming. Not a design doc or TODO.
4
+ >
5
+ > **Note:** Many concepts explored here have since been implemented.
6
+ > See `navigators-architecture.md` for current architecture and
7
+ > `devlog/1032-orchestrator` for evolutionary orchestration implementation.
4
8
 
5
9
  This document explores the navigation strategy paradigm: what other strategy types
6
10
  might exist, where the current design shines or struggles, and what alternative
@@ -79,7 +83,8 @@ Trigger-response generators need:
79
83
  4. **Exit criteria** — When does intervention end?
80
84
 
81
85
  This argues for strategies having **lifecycle state**, not just stateless scoring.
82
- See `todo-strategy-state-storage.md` for related concerns.
86
+ **Update:** Strategy state storage is now implemented via `StrategyStateDoc` see
87
+ `navigators-architecture.md` for details.
83
88
 
84
89
  ---
85
90
 
@@ -138,7 +143,7 @@ Strategies are instantiated per-request. No persistence of:
138
143
  - "Last time I surfaced tag X was..."
139
144
  - "This user responds well to strategy Y"
140
145
 
141
- **Mitigation:** `todo-strategy-state-storage.md` (not implemented)
146
+ **Mitigation:** ✅ Implemented via `StrategyStateDoc` — see `navigators-architecture.md`
142
147
 
143
148
  ### 2. Pull-Only Model
144
149
 
@@ -255,25 +260,30 @@ rules:
255
260
  **Pros:** Declarative, inspectable, author-configurable
256
261
  **Cons:** Limited expressiveness, new DSL to maintain
257
262
 
258
- ### 4. Bandit Selection (Planned)
263
+ ### 4. Bandit-Style Selection (IMPLEMENTED ✅)
259
264
 
260
- Instead of a fixed pipeline, select among N candidate pipelines:
265
+ Strategies carry **learnable weights** that automatically tune based on outcomes:
261
266
 
262
267
  ```
263
- PipelineA: ELO
264
- PipelineB: Hierarchy(ELO)
265
- PipelineC: Interference(Hierarchy(ELO))
266
-
267
- Orchestrator selects pipeline per-session based on:
268
- - User cohort
269
- - Historical effectiveness
270
- - Exploration/exploitation balance
268
+ Strategy weights = { weight: 1.2, confidence: 0.8, sampleSize: 500 }
269
+
270
+ Users are distributed across weight space via deviation:
271
+ effectiveWeight = peakWeight + deviation * spread
272
+
273
+ Gradient learning correlates deviation with outcomes:
274
+ +deviation +outcome → increase peak
275
+ +deviation → -outcome decrease peak
271
276
  ```
272
277
 
273
- **Pros:** Learns what works, self-improving
274
- **Cons:** Requires outcome measurement, cold-start problem
278
+ **Implemented features:**
279
+ - LearnableWeight on strategies
280
+ - Deviation-based cohort distribution
281
+ - Outcome recording per user/period
282
+ - Gradient computation via linear regression
283
+ - Automatic weight updates
284
+ - Observability API endpoints
275
285
 
276
- See `todo-evolutionary-orchestration.md`.
286
+ See `navigators-architecture.md` for details.
277
287
 
278
288
  ### 5. LLM-Guided Selection
279
289
 
@@ -316,23 +326,20 @@ Solver finds valid card sequence.
316
326
 
317
327
  Rather than wholesale paradigm shift, extend current model:
318
328
 
319
- ### Near-term (compatible with naive orchestration)
329
+ ### Completed
320
330
 
321
- 1. **Richer context** — Pass session state to strategies
322
- 2. **Trigger-response generator** — New generator type with activation state
323
- 3. **Session-scoped state** — Allow strategies to persist within-session
331
+ 1. **Pipeline architecture** — Generators + Filters with provenance tracking
332
+ 2. **Strategy state storage** — User-scoped persistence via `StrategyStateDoc`
333
+ 3. **Evolutionary orchestration** — Learnable weights with gradient learning
334
+ 4. **Outcome measurement** — `UserOutcomeRecord` for tracking effectiveness
335
+ 5. **Observability** — API endpoints and admin dashboard
324
336
 
325
- ### Medium-term (with strategy state storage)
337
+ ### Still Applicable
326
338
 
327
- 4. **Cross-session state** — Strategies remember past sessions
328
- 5. **Event hooks** — Strategies can subscribe to card results
329
- 6. **Intervention protocol** — Active intervention preempts normal generation
330
-
331
- ### Long-term (with evolutionary orchestration)
332
-
333
- 7. **Bandit selection** among pipelines
334
- 8. **Outcome measurement** for strategy effectiveness
335
- 9. **Hybrid architectures** where blackboard/reactive patterns augment pipeline
339
+ 1. **Trigger-response generators** — Event-driven strategies with activation state
340
+ 2. **Richer context** — Session state, temporal context
341
+ 3. **Event hooks** — Strategies subscribing to card results
342
+ 4. **Intervention protocol** — Active intervention preempts normal generation
336
343
 
337
344
  ---
338
345
 
@@ -362,8 +369,7 @@ Rather than wholesale paradigm shift, extend current model:
362
369
 
363
370
  ## Related Documents
364
371
 
365
- - `navigators-architecture.md` — Current architecture
366
- - `todo-naive-orchestration.md` — Pipeline assembly (prerequisite)
367
- - `todo-strategy-state-storage.md` — State persistence
368
- - `todo-evolutionary-orchestration.md` — Bandit selection vision
369
- - `todo-provenance.md` — Audit trail (transparency)
372
+ - `navigators-architecture.md` — Current architecture (includes evolutionary orchestration)
373
+ - `future-orchestration-vision.md` — Remaining vision items (programmable strategies, self-healing)
374
+ - `todo-strategy-authoring.md` — Strategy creation tools (UI complete)
375
+ - `devlog/1032-orchestrator` — Evolutionary orchestration implementation
@@ -0,0 +1,216 @@
1
+ # Future Orchestration Vision
2
+
3
+ This document tracks aspirational features for the evolutionary orchestration system
4
+ that extend beyond the current implementation.
5
+
6
+ ## Status: VISION / NOT STARTED
7
+
8
+ > **Prerequisite:** The core orchestration system (learnable weights, deviation-based
9
+ > distribution, gradient learning) is implemented. See `navigators-architecture.md`
10
+ > for the current architecture.
11
+
12
+ ---
13
+
14
+ ## Implemented (Reference)
15
+
16
+ The following are **complete** and documented in `navigators-architecture.md`:
17
+
18
+ - ✅ LearnableWeight interface with weight, confidence, sampleSize
19
+ - ✅ Deviation-based weight distribution (bell curve sampling)
20
+ - ✅ UserOutcomeRecord for tracking learning outcomes
21
+ - ✅ Gradient computation via linear regression
22
+ - ✅ Automatic weight updates based on gradient
23
+ - ✅ Observability API endpoints (6 endpoints)
24
+ - ✅ Admin dashboard in platform-ui
25
+
26
+ ---
27
+
28
+ ## Remaining Vision
29
+
30
+ ### 1. Parameterizable / Programmable Strategies
31
+
32
+ **Goal:** Enable template-based prerequisite rules that generalize across courses.
33
+
34
+ ```typescript
35
+ interface ParameterizedPrerequisite {
36
+ pattern: "grade-{n} & {subject}";
37
+ implies: "grade-{n+1} & {subject}";
38
+ constraints: {
39
+ n: { type: "number", min: 1, max: 12 },
40
+ subject: { type: "tag-category", category: "academic-subject" }
41
+ };
42
+ }
43
+ ```
44
+
45
+ **Example use cases:**
46
+ - `grade-3 & geometry` → requires `grade-2 & geometry`
47
+ - `unit-{n} & {topic}` → requires `unit-{n-1} & {topic}`
48
+ - Cross-course strategy reuse without copy-paste
49
+
50
+ **What's needed:**
51
+ 1. Template syntax design
52
+ 2. Variable binding and substitution
53
+ 3. Rule engine to evaluate parameterized rules
54
+ 4. Cross-course strategy registry
55
+
56
+ ---
57
+
58
+ ### 2. Self-Healing Content
59
+
60
+ **Goal:** Automatically identify learning barriers and surface them to authors.
61
+
62
+ **Barrier signals:**
63
+ - High failure rate on specific cards/tags
64
+ - ELO stagnation on specific topics
65
+ - Long dwell time before mastery
66
+ - Drop-off (users abandon at specific points)
67
+ - Cohort-wide plateau detection
68
+
69
+ **Components needed:**
70
+ 1. **Barrier Detection Pipeline** — Analyze outcomes to identify stuck points
71
+ 2. **Alert System** — Notify authors of identified barriers
72
+ 3. **Intervention Hooks** — Enable targeted content insertion
73
+ 4. **Feedback Loop** — Measure whether interventions resolve barriers
74
+
75
+ **Example flow:**
76
+ ```
77
+ Detection: 40% of users fail on "long-division-with-remainders" after
78
+ mastering "long-division-no-remainder"
79
+
80
+ Alert: "Learning barrier detected between division topics.
81
+ Consider intermediate content for remainder concept."
82
+
83
+ Author action: Adds 5 cards on "remainder as leftover" concept
84
+
85
+ Feedback: Barrier detection re-runs, measures improvement
86
+ ```
87
+
88
+ ---
89
+
90
+ ### 3. Cross-Course Strategy Sharing
91
+
92
+ **Goal:** Strategies that prove effective in one course can be shared and
93
+ adapted to other courses.
94
+
95
+ **Components:**
96
+ - Strategy export/import format
97
+ - Cross-course strategy registry
98
+ - Adaptation hints for tag mapping
99
+ - Reputation/effectiveness scores from source course
100
+
101
+ ---
102
+
103
+ ### 4. Author Incentive Mechanisms
104
+
105
+ **Goal:** Create feedback loops that reward authors for effective content.
106
+
107
+ **Potential signals:**
108
+ - User outcomes correlated with specific content
109
+ - Content utility weights (cards that consistently help)
110
+ - Barrier resolution credit
111
+
112
+ **Considerations:**
113
+ - How to attribute outcomes to specific content when many cards contribute?
114
+ - How to handle content that is effective but not "fun"?
115
+ - Privacy implications of tracking detailed content effectiveness
116
+
117
+ ---
118
+
119
+ ### 5. Trigger-Response Generators
120
+
121
+ **Goal:** Event-driven generators that activate under specific conditions.
122
+
123
+ ```typescript
124
+ interface TriggerResponseGenerator {
125
+ trigger: {
126
+ condition: 'failureSpike' | 'plateau' | 'returnAfterGap' | 'frustration';
127
+ parameters: Record<string, number>;
128
+ };
129
+ response: {
130
+ mode: 'remedial' | 'confidence-building' | 'capstone';
131
+ targetTags?: string[];
132
+ duration?: { cards?: number; minutes?: number };
133
+ };
134
+ }
135
+ ```
136
+
137
+ **Example triggers:**
138
+ - Frustration signal (N failures in M minutes) → easier content
139
+ - Plateau detection (no ELO movement for K sessions) → challenging content
140
+ - Inactivity return (first session after gap) → review-heavy session
141
+
142
+ **What's needed:**
143
+ - Event bus / signal mechanism for strategies to observe events
144
+ - Activation state tracking ("I am currently intervening on tag T")
145
+ - Priority over base generator (preempt vs blend)
146
+ - Exit criteria (when does intervention end)
147
+
148
+ See `brainstorm-navigation-paradigm.md` for detailed exploration.
149
+
150
+ ---
151
+
152
+ ### 6. Cohort-Aware Calibration
153
+
154
+ **Goal:** Use population data to improve cold-start behavior.
155
+
156
+ **Applications:**
157
+ - Initial card difficulty estimates from population performance
158
+ - Initial interval estimates based on similar users
159
+ - Strategy weight priors from population effectiveness
160
+
161
+ ---
162
+
163
+ ### 7. LLM-Guided Selection (Experimental)
164
+
165
+ **Goal:** Use language models to interpret learner state and select content.
166
+
167
+ ```
168
+ Given:
169
+ - User profile: { elo: 950, strugglingWith: ['vowel-sounds'], ... }
170
+ - Session context: { duration: 12min, cardsSeen: 8, recentFailures: 2 }
171
+ - Available cards: [...]
172
+
173
+ Select the next 5 cards and explain reasoning.
174
+ ```
175
+
176
+ **Considerations:**
177
+ - Latency and cost
178
+ - Unpredictability and debugging difficulty
179
+ - When is LLM guidance worth the overhead?
180
+
181
+ ---
182
+
183
+ ## Design Decisions Ahead
184
+
185
+ ### Centralized vs Decentralized Orchestration
186
+
187
+ **Option A: Central Orchestrator Service**
188
+ - Single service decides strategy application
189
+ - Cleaner cohort tracking
190
+ - Requires backend infrastructure
191
+
192
+ **Option B: Client-Side Orchestration**
193
+ - Each client computes its own strategy set
194
+ - Works offline
195
+ - Harder to track cohorts
196
+
197
+ **Current:** Hybrid — client computes from synced registry, outcomes reported to backend.
198
+
199
+ ### Outcome Attribution
200
+
201
+ When multiple strategies are active, how do we attribute outcomes?
202
+
203
+ - All strategies get credit/blame equally?
204
+ - Weight by score contribution?
205
+ - Require isolated A/B cells?
206
+
207
+ **Current:** Equal attribution. Future work may instrument isolated testing.
208
+
209
+ ---
210
+
211
+ ## Related Documents
212
+
213
+ - `navigators-architecture.md` — Current implementation (complete)
214
+ - `brainstorm-navigation-paradigm.md` — Exploration of alternative mechanisms
215
+ - `todo-strategy-authoring.md` — Strategy creation tools
216
+ - `devlog/1032-orchestrator` — Implementation details
@@ -5,6 +5,9 @@
5
5
  The navigation strategy system selects and scores cards for study sessions. It uses a
6
6
  **Pipeline architecture** where generators produce candidates and filters transform scores.
7
7
 
8
+ An **Evolutionary Orchestration** layer enables strategies to carry learnable weights that
9
+ automatically tune toward optimal values based on observed learning outcomes.
10
+
8
11
  ## Core Concepts
9
12
 
10
13
  ### WeightedCard
@@ -27,6 +30,7 @@ interface StrategyContribution {
27
30
  action: 'generated' | 'passed' | 'boosted' | 'penalized';
28
31
  score: number; // Score after this strategy
29
32
  reason: string; // Human-readable explanation
33
+ deviation?: number; // User's deviation from peak weight (evolutionary)
30
34
  }
31
35
  ```
32
36
 
@@ -82,7 +86,7 @@ class Pipeline {
82
86
  )
83
87
 
84
88
  async getWeightedCards(limit: number): Promise<WeightedCard[]> {
85
- // Build shared context (user ELO, etc.)
89
+ // Build shared context (user ELO, orchestration context, etc.)
86
90
  const context = await this.buildContext();
87
91
 
88
92
  // Generate candidates
@@ -104,7 +108,7 @@ class Pipeline {
104
108
  ```
105
109
 
106
110
  **Responsibilities:**
107
- - **Context building** — Fetches shared data (user ELO) once for all strategies
111
+ - **Context building** — Fetches shared data (user ELO, orchestration context) once for all strategies
108
112
  - **Data hydration** — Pre-fetches commonly needed data (tags) in batch queries
109
113
  - **Filter orchestration** — Applies filters in sequence, accumulating provenance
110
114
  - **Result selection** — Removes zero-scores, sorts, and returns top N
@@ -170,7 +174,8 @@ provenance: [
170
174
  strategyId: 'NAVIGATION_STRATEGY-hierarchy-phonics',
171
175
  action: 'passed',
172
176
  score: 0.85,
173
- reason: 'Prerequisites met, tags: letter-sounds'
177
+ reason: 'Prerequisites met, tags: letter-sounds',
178
+ deviation: 0.23 // User's position on bell curve for this strategy
174
179
  },
175
180
  {
176
181
  strategy: 'eloDistance',
@@ -185,6 +190,171 @@ provenance: [
185
190
 
186
191
  Use `getCardOrigin(card)` to extract 'new', 'review', or 'failed' from provenance.
187
192
 
193
+ ---
194
+
195
+ ## Evolutionary Orchestration
196
+
197
+ The orchestration layer enables strategies to **learn optimal weights** from observed
198
+ learning outcomes. Instead of fixed configuration, strategies carry **learnable weights**
199
+ that automatically tune toward effectiveness.
200
+
201
+ ### LearnableWeight
202
+
203
+ Every strategy can carry a learnable weight:
204
+
205
+ ```typescript
206
+ interface LearnableWeight {
207
+ weight: number; // Peak value, 1.0 = neutral, range [0.1, 3.0]
208
+ confidence: number; // 0-1, controls exploration width
209
+ sampleSize: number; // Total observations for this strategy
210
+
211
+ history?: Array<{ // Optional: for visualization
212
+ timestamp: string;
213
+ weight: number;
214
+ confidence: number;
215
+ gradient: number;
216
+ }>;
217
+ }
218
+ ```
219
+
220
+ Strategies extend with:
221
+
222
+ ```typescript
223
+ interface ContentNavigationStrategyData {
224
+ // ... existing fields ...
225
+ learnable?: LearnableWeight; // Omitted = default weight 1.0
226
+ staticWeight?: boolean; // If true, not subject to learning
227
+ }
228
+ ```
229
+
230
+ ### Deviation-Based Weight Distribution
231
+
232
+ Each user experiences a **stable deviation** from the peak weight:
233
+
234
+ ```
235
+ effectiveWeight(user, strategy) = peakWeight + deviation * spread
236
+
237
+ where:
238
+ deviation = hash(userId, strategyId, salt) → [-1, 1] // stable per user
239
+ spread = max(MIN_SPREAD, (1 - confidence) * MAX_SPREAD)
240
+ ```
241
+
242
+ **Key insight:** Deviation is constant for a user. As confidence grows and spread
243
+ shrinks, all users are pulled toward the optimal peak.
244
+
245
+ ```typescript
246
+ // Example: Low confidence = wide exploration
247
+ { weight: 1.0, confidence: 0.2 }
248
+ → spread = 0.8 * MAX_SPREAD
249
+ → users range from weight 0.6 to 1.4
250
+
251
+ // Example: High confidence = narrow convergence
252
+ { weight: 1.2, confidence: 0.9 }
253
+ → spread = 0.1 * MAX_SPREAD
254
+ → users cluster around weight 1.15 to 1.25
255
+ ```
256
+
257
+ ### Outcome Recording
258
+
259
+ At the end of each learning period, user outcomes are recorded:
260
+
261
+ ```typescript
262
+ interface UserOutcomeRecord {
263
+ _id: `USER_OUTCOME::${courseId}::${periodId}`;
264
+ docType: DocType.USER_OUTCOME;
265
+ userId: string;
266
+ courseId: string;
267
+ periodStart: string;
268
+ periodEnd: string;
269
+ strategyExposures: Array<{
270
+ strategyId: string;
271
+ deviation: number; // User's stable deviation for this strategy
272
+ }>;
273
+ outcomeValue: number; // 0-1 learning outcome signal
274
+ }
275
+ ```
276
+
277
+ The outcome signal combines multiple factors:
278
+ - Accuracy within target zone (not too easy, not too hard)
279
+ - ELO progression
280
+ - Session completion
281
+
282
+ ### Gradient Learning
283
+
284
+ The system discovers optimal weights by correlating **deviation with outcomes**
285
+ across users:
286
+
287
+ ```
288
+ +deviation → +outcome = positive gradient → increase peak weight
289
+ +deviation → -outcome = negative gradient → decrease peak weight
290
+ flat gradient = at optimum, increase confidence
291
+ ```
292
+
293
+ Linear regression on (deviation, outcome) pairs produces:
294
+ - **Gradient**: Direction to adjust peak
295
+ - **R²**: Signal quality (high = consistent effect)
296
+ - **Sample size**: Update confidence
297
+
298
+ ### Weight Update Cycle
299
+
300
+ Periodically (or on-demand), the system updates strategy weights:
301
+
302
+ ```typescript
303
+ async function runPeriodUpdate(courseId: string): Promise<void> {
304
+ for (const strategy of await getLearnableStrategies(courseId)) {
305
+ const observations = await aggregateOutcomesForGradient(strategy);
306
+ const { gradient, rSquared } = computeStrategyGradient(observations);
307
+ await updateStrategyWeight(strategy, gradient, rSquared);
308
+ }
309
+ }
310
+ ```
311
+
312
+ **Update rules:**
313
+ - Positive gradient → increase peak weight
314
+ - Negative gradient → decrease peak weight
315
+ - Consistent observations → increase confidence
316
+ - Noisy observations → decrease confidence
317
+
318
+ ### Observability
319
+
320
+ The orchestration layer exposes API endpoints for monitoring:
321
+
322
+ | Endpoint | Purpose |
323
+ |----------|---------|
324
+ | `GET /orchestration/:courseId/state` | All learning states |
325
+ | `GET /orchestration/:courseId/weights` | Current weights summary |
326
+ | `GET /orchestration/:courseId/strategy/:id/history` | Weight trajectory over time |
327
+ | `GET /orchestration/:courseId/strategy/:id/scatter` | Deviation vs outcome data |
328
+ | `GET /orchestration/:courseId/strategy/:id/distribution` | Bell curve visualization |
329
+ | `POST /orchestration/:courseId/update` | Trigger period update |
330
+
331
+ An admin dashboard in platform-ui visualizes strategy weights, confidence,
332
+ gradient direction, and historical trajectories.
333
+
334
+ ### Lifecycle
335
+
336
+ ```
337
+ New strategy: Low confidence → wide spread → noisy gradient → big adjustments
338
+ Learning: Gradient visible → peak drifts → confidence grows → spread shrinks
339
+ Converged: High confidence → minimum spread → flat gradient → stable
340
+ Disturbed: Gradient reappears → peak drifts → adapts to new optimal
341
+ ```
342
+
343
+ ### Static vs Learnable
344
+
345
+ Set `staticWeight: true` for foundational strategies that should not be tuned:
346
+
347
+ ```typescript
348
+ {
349
+ strategyType: 'hierarchyDefinition',
350
+ name: 'Core Prerequisites',
351
+ staticWeight: true, // Never tuned by orchestration
352
+ // learnable field ignored
353
+ }
354
+ ```
355
+
356
+ ---
357
+
188
358
  ## Creating New Strategies
189
359
 
190
360
  ### Generator
@@ -249,6 +419,8 @@ class MyFilter extends ContentNavigator implements CardFilter {
249
419
 
250
420
  Register in `NavigatorRoles` as `NavigatorRole.FILTER`.
251
421
 
422
+ ---
423
+
252
424
  ## Strategy State Storage
253
425
 
254
426
  Strategies can persist user-scoped state (preferences, learned patterns, temporal tracking)
@@ -294,7 +466,7 @@ interface StrategyStateDoc<T> {
294
466
  courseId: string;
295
467
  strategyKey: string;
296
468
  data: T; // Strategy-specific payload
297
- updatedAt: string; // ISO timestamp
469
+ updatedAt: string;
298
470
  }
299
471
  ```
300
472
 
@@ -332,6 +504,8 @@ return { ...card, score: card.score * multiplier };
332
504
  - All sliders share global max for consistent visual comparison
333
505
  - Writes to strategy state via `userDB.putStrategyState()`
334
506
 
507
+ ---
508
+
335
509
  ## File Reference
336
510
 
337
511
  | File | Purpose |
@@ -355,9 +529,18 @@ return { ...card, score: card.score * multiplier };
355
529
  | `core/navigators/inferredPreference.ts` | Inferred preference navigator (stub) |
356
530
  | `core/types/strategyState.ts` | `StrategyStateDoc`, `StrategyStateId` |
357
531
  | `impl/couch/courseDB.ts` | `createNavigator()` entry point |
532
+ | `core/orchestration/index.ts` | OrchestrationContext, deviation logic |
533
+ | `core/orchestration/gradient.ts` | Gradient computation |
534
+ | `core/orchestration/learning.ts` | Weight updates, period orchestration |
535
+ | `core/orchestration/signal.ts` | Outcome signal computation |
536
+ | `core/orchestration/recording.ts` | User outcome recording |
537
+ | `core/types/learningState.ts` | `StrategyLearningState` |
538
+ | `core/types/userOutcome.ts` | `UserOutcomeRecord` |
539
+ | `express/routes/orchestration.ts` | Observability API endpoints |
358
540
 
359
541
  ## Related Documentation
360
542
 
361
543
  - `todo-strategy-authoring.md` — UX and DX for authoring strategies
362
- - `todo-evolutionary-orchestration.md` — Long-term adaptive strategy vision
544
+ - `future-orchestration-vision.md` — Long-term adaptive strategy vision (beyond current implementation)
363
545
  - `devlog/1004` — Implementation details for tag hydration optimization
546
+ - `devlog/1032-orchestrator` — Evolutionary orchestration implementation details