Context
Project: `/.forge/websites/kingofalldata.com` (note: PRIMER.md still says `/.kingdom/websites/...` — stale path, please update PRIMER while you're in there)
Alice currently has exactly one signal she can send from her LLM output back to the browser: `<<LEVEL_COMPLETE>>`. It's handled in `src/client/alice.js` around line 418 — detected, stripped from the rendered message, and triggers the level-complete UI.
koad wants to generalize this. Alice should be able to emit arbitrary session state updates mid-conversation, not just level-complete. Example use case:
Alice asks the student "do you have a computer, and if so what OS?" Student answers "Windows." Alice now knows something worth remembering for the rest of the session, and should be able to emit a signal like `session.set('student', {os: 'windows'})`.
Requirements
-
Signal format — design a simple inline signal Alice can emit in her response that gets parsed out and stripped before the message renders to the user. Suggest something like `<<SESSION_SET student {"os":"windows"}>>` or `<>` — pick whatever is easiest for the LLM to emit reliably and easiest to parse robustly. Must survive streaming SSE (signals may arrive in chunks — buffer until complete).
-
Merge, don't overwrite — this is the critical semantic. If `session.get('student')` is already `{name: 'Dave', level: 3}`, then `session.set('student', {os: 'windows'})` must result in `{name: 'Dave', level: 3, os: 'windows'}`. Deep merge preferred for nested objects. Never clobber.
-
Keep `<<LEVEL_COMPLETE>>` working — either re-express it inside the new signal scheme or keep it as a special case alongside. Don't break existing level progression.
-
Persistence — session state should live alongside existing chat persistence (localStorage today, eventually namespace profile). Student data collected this way is part of the content bubble that will be transferred on koad:io install. Treat it as permanent-until-user-clears.
-
Curriculum side — Alice's system prompt / curriculum instructions in `src/server/alice-curriculum.js` need to teach her when to emit these signals. Don't make her emit state for every message — only when she learns something worth remembering (OS, hardware, prior experience, name, goal, commitments, GTD readiness, etc.).
-
Debuggability — log signals to console on client when parsed, so we can watch Alice actually using them during development.
Out of scope (do not do in this pass)
Deliverables
- Signal parser in `src/client/alice.js` (or a sibling module if it gets big)
- `Session` helper with `get` / `set` (merge) / `clear` / `dump` — pick a clean name, session is already a loaded word in Meteor so maybe `StudentState` or `AliceMemory`
- Curriculum update in `src/server/alice-curriculum.js` teaching Alice the signal vocabulary
- PRIMER.md path fix (`
/.kingdom` → `/.forge`)
- Short note in the issue comment describing the final signal format you chose and why
Context on why this matters
This is the groundwork for the "content bubble" — everything Alice learns about the student in the browser eventually transfers to their sovereign entity dir on koad:io install. The more Alice can remember during the course, the richer the handoff. Signals are how Alice writes to that bubble.
Assigning: Vulcan
Context
Project: `
/.forge/websites/kingofalldata.com` (note: PRIMER.md still says `/.kingdom/websites/...` — stale path, please update PRIMER while you're in there)Alice currently has exactly one signal she can send from her LLM output back to the browser: `<<LEVEL_COMPLETE>>`. It's handled in `src/client/alice.js` around line 418 — detected, stripped from the rendered message, and triggers the level-complete UI.
koad wants to generalize this. Alice should be able to emit arbitrary session state updates mid-conversation, not just level-complete. Example use case:
Requirements
Signal format — design a simple inline signal Alice can emit in her response that gets parsed out and stripped before the message renders to the user. Suggest something like `<<SESSION_SET student {"os":"windows"}>>` or `<>` — pick whatever is easiest for the LLM to emit reliably and easiest to parse robustly. Must survive streaming SSE (signals may arrive in chunks — buffer until complete).
Merge, don't overwrite — this is the critical semantic. If `session.get('student')` is already `{name: 'Dave', level: 3}`, then `session.set('student', {os: 'windows'})` must result in `{name: 'Dave', level: 3, os: 'windows'}`. Deep merge preferred for nested objects. Never clobber.
Keep `<<LEVEL_COMPLETE>>` working — either re-express it inside the new signal scheme or keep it as a special case alongside. Don't break existing level progression.
Persistence — session state should live alongside existing chat persistence (localStorage today, eventually namespace profile). Student data collected this way is part of the content bubble that will be transferred on koad:io install. Treat it as permanent-until-user-clears.
Curriculum side — Alice's system prompt / curriculum instructions in `src/server/alice-curriculum.js` need to teach her when to emit these signals. Don't make her emit state for every message — only when she learns something worth remembering (OS, hardware, prior experience, name, goal, commitments, GTD readiness, etc.).
Debuggability — log signals to console on client when parsed, so we can watch Alice actually using them during development.
Out of scope (do not do in this pass)
Deliverables
/.kingdom` → `/.forge`)Context on why this matters
This is the groundwork for the "content bubble" — everything Alice learns about the student in the browser eventually transfers to their sovereign entity dir on koad:io install. The more Alice can remember during the course, the richer the handoff. Signals are how Alice writes to that bubble.
Assigning: Vulcan