@mindot/will 0.8.0 → 0.10.0

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 (142) hide show
  1. package/README.md +15 -11
  2. package/dist/index.d.ts +188 -141
  3. package/dist/index.js +6985 -3337
  4. package/dist/index.js.map +1 -1
  5. package/dist/surface/channels/discord.d.ts +177 -0
  6. package/dist/surface/channels/discord.js +394 -0
  7. package/dist/surface/channels/discord.js.map +1 -0
  8. package/dist/{channels → surface/channels}/whatsapp.d.ts +2 -2
  9. package/dist/{channels → surface/channels}/whatsapp.js +11 -5
  10. package/dist/surface/channels/whatsapp.js.map +1 -0
  11. package/dist/{cli.js → surface/cli.js} +5382 -1573
  12. package/dist/surface/cli.js.map +1 -0
  13. package/dist/{mcp → surface/mcp}/effectors.d.ts +1 -1
  14. package/dist/{mcp → surface/mcp}/effectors.js +10 -4
  15. package/dist/surface/mcp/effectors.js.map +1 -0
  16. package/dist/{will-cS6k4uiJ.d.ts → will-evj9_vrd.d.ts} +6658 -5078
  17. package/package.json +11 -12
  18. package/src/cognition/agency/consequence.ts +356 -1
  19. package/src/cognition/agency/conversation.aim.ts +292 -0
  20. package/src/cognition/agency/engines/action.selector.ts +142 -5
  21. package/src/cognition/agency/engines/affordance.synthesizer.ts +200 -7
  22. package/src/cognition/agency/engines/deliberation.engine.ts +76 -3
  23. package/src/cognition/agency/engines/motor.schema.executor.ts +509 -32
  24. package/src/cognition/agency/engines/reafference.engine.ts +160 -4
  25. package/src/cognition/agency/execution.primitives.ts +17 -4
  26. package/src/cognition/agency/proactive.communicator.ts +19 -3
  27. package/src/cognition/agency/reconcile.learning.ts +5 -4
  28. package/src/cognition/agency/restart.ts +66 -0
  29. package/src/cognition/agency/schemas/innate.ts +96 -1
  30. package/src/cognition/agency/schemas/repertoire.ts +19 -1
  31. package/src/cognition/agency/selection.scoring.ts +49 -0
  32. package/src/cognition/agency/settlement.ts +203 -0
  33. package/src/cognition/agency/types.ts +73 -1
  34. package/src/cognition/cache/composition.ts +232 -0
  35. package/src/cognition/cache/deliberation.cache.ts +219 -0
  36. package/src/cognition/cache/fingerprint.ts +120 -0
  37. package/src/cognition/cache/types.ts +105 -0
  38. package/src/cognition/config.mirror.entities.ts +108 -1
  39. package/src/cognition/event.schemas.ts +22 -8
  40. package/src/cognition/faculties/affective.blender.ts +21 -4
  41. package/src/cognition/faculties/autobiographical.narrator.ts +5 -10
  42. package/src/cognition/faculties/circadian.oscillator.ts +36 -7
  43. package/src/cognition/faculties/episodic.consolidator.ts +59 -3
  44. package/src/cognition/faculties/executive.engine/action.record.ts +129 -0
  45. package/src/cognition/faculties/executive.engine/commands.ts +189 -14
  46. package/src/cognition/faculties/executive.engine/context.ts +106 -46
  47. package/src/cognition/faculties/executive.engine/deliberate.reasoning.ts +1 -1
  48. package/src/cognition/faculties/executive.engine/engine.ts +714 -136
  49. package/src/cognition/faculties/executive.engine/escalation.buffer.ts +230 -45
  50. package/src/cognition/faculties/executive.engine/facet.supervisor.ts +320 -65
  51. package/src/cognition/faculties/executive.engine/facet.ts +81 -26
  52. package/src/cognition/faculties/executive.engine/gating.ts +14 -14
  53. package/src/cognition/faculties/executive.engine/parser.ts +120 -38
  54. package/src/cognition/faculties/executive.engine/prompt.factory.ts +331 -38
  55. package/src/cognition/faculties/executive.engine/types.ts +84 -12
  56. package/src/cognition/faculties/exteroception.ts +99 -98
  57. package/src/cognition/faculties/goal.manager.ts +144 -16
  58. package/src/cognition/faculties/known.entity.tracker.ts +287 -29
  59. package/src/cognition/faculties/moral.evaluator.ts +8 -3
  60. package/src/cognition/faculties/persona.consolidator.ts +141 -0
  61. package/src/cognition/faculties/planning.engine/engine.ts +4 -4
  62. package/src/cognition/faculties/planning.engine/plan.frontier.ts +1 -1
  63. package/src/cognition/faculties/reputation.tracker.ts +66 -2
  64. package/src/cognition/faculties/self.model.updater.ts +19 -12
  65. package/src/cognition/faculties/semantic.engine/integrator.ts +1 -1
  66. package/src/cognition/faculties/social.perception.ts +47 -3
  67. package/src/cognition/faculties/threat.evaluator.ts +7 -0
  68. package/src/cognition/faculties/working.memory.ts +16 -21
  69. package/src/cognition/identity.entity.ts +205 -0
  70. package/src/cognition/index.ts +7 -0
  71. package/src/cognition/instruction.handler.ts +1 -1
  72. package/src/cognition/memory/vector.adapter.ts +12 -3
  73. package/src/cognition/memory/vector.embedder.ts +45 -4
  74. package/src/cognition/percept.entity.ts +122 -0
  75. package/src/cognition/persona.prior.ts +6 -0
  76. package/src/cognition/sense.boundary.ts +176 -0
  77. package/src/cognition/senses/audition.engine/engine.ts +492 -53
  78. package/src/cognition/senses/base.sense.engine.ts +105 -7
  79. package/src/cognition/senses/index.ts +83 -13
  80. package/src/cognition/senses/provenance.ts +128 -0
  81. package/src/cognition/senses/somatosensation.engine.ts +117 -9
  82. package/src/cognition/social.identity.ts +296 -0
  83. package/src/cognition/utilities/token.tracker.ts +94 -10
  84. package/src/core/orchestrator.ts +51 -0
  85. package/src/index.ts +39 -5
  86. package/src/llm/gate.ts +48 -0
  87. package/src/llm/index.ts +127 -33
  88. package/src/llm/routing.ts +6 -0
  89. package/src/llm/summarizer.ts +1 -1
  90. package/src/llm/wire.contracts.ts +57 -0
  91. package/src/pma/index.ts +68 -54
  92. package/src/stem/assembly.audit.ts +1 -0
  93. package/src/stem/guards/identity.coherence.ts +1 -1
  94. package/src/stem/index.ts +171 -23
  95. package/src/stem/mind.ts +198 -57
  96. package/src/stem/policy/arbiter.ts +10 -0
  97. package/src/stem/profiles/built-in.ts +7 -0
  98. package/src/{profiles → stem/profiles}/companion.ts +1 -1
  99. package/src/{profiles → stem/profiles}/company-brain.ts +1 -1
  100. package/src/{profiles → stem/profiles}/customer-service.ts +1 -1
  101. package/src/{profiles → stem/profiles}/game-npc.ts +1 -1
  102. package/src/{profiles → stem/profiles}/index.ts +1 -1
  103. package/src/{profiles → stem/profiles}/smart-home.ts +1 -1
  104. package/src/stem/tracts/effector/escalation.lifecycle.ts +239 -0
  105. package/src/stem/tracts/effector/policy.enforcement.ts +261 -0
  106. package/src/stem/tracts/effector/types.ts +110 -0
  107. package/src/stem/tracts/effector.controller.ts +112 -401
  108. package/src/stem/tracts/outbox.controller.ts +30 -17
  109. package/src/stem/tracts/outbox.writer.ts +40 -2
  110. package/src/stem/tracts/sensory.controller.ts +6 -6
  111. package/src/stem/tracts/session.logger.ts +6 -1
  112. package/src/stem/tracts/transport/types.ts +20 -1
  113. package/src/stem/tracts/transport.controller.ts +33 -9
  114. package/src/surface/channels/discord.ts +609 -0
  115. package/src/{channels → surface/channels}/roster.ts +1 -1
  116. package/src/surface/channels/types.ts +136 -0
  117. package/src/{channels → surface/channels}/whatsapp.ts +22 -10
  118. package/src/{cli.ts → surface/cli.ts} +14 -9
  119. package/src/{host → surface/host}/boot.ts +3 -3
  120. package/src/{host → surface/host}/utterances.ts +2 -2
  121. package/src/{mcp → surface/mcp}/effectors.ts +19 -6
  122. package/src/{mcp → surface/mcp}/server.ts +19 -5
  123. package/src/{sdk → surface/sdk}/will.ts +194 -33
  124. package/src/{serve → surface/serve}/server.ts +11 -4
  125. package/src/types.ts +24 -3
  126. package/dist/channels/discord.d.ts +0 -69
  127. package/dist/channels/discord.js +0 -193
  128. package/dist/channels/discord.js.map +0 -1
  129. package/dist/channels/whatsapp.js.map +0 -1
  130. package/dist/cli.js.map +0 -1
  131. package/dist/mcp/effectors.js.map +0 -1
  132. package/src/channels/discord.ts +0 -214
  133. package/src/channels/types.ts +0 -46
  134. package/src/cognition/faculties/executive.engine/messages.ts +0 -102
  135. package/src/extensions/livestream.ext.ts +0 -570
  136. package/src/extensions/time.ext.ts +0 -339
  137. package/src/profiles/built-in.ts +0 -7
  138. package/src/runners/coherence.runner.ts +0 -49
  139. package/src/runners/outreach.runner.ts +0 -155
  140. package/src/runners/social.runner.ts +0 -179
  141. package/src/runners/thin-shim.runner.ts +0 -205
  142. /package/dist/{cli.d.ts → surface/cli.d.ts} +0 -0
@@ -1,179 +0,0 @@
1
- // ─────────────────────────────────────────────────────────────
2
- // src/stem/social.runner.ts — Social + continuity scenario
3
- // ─────────────────────────────────────────────────────────────
4
- //
5
- // Exercises the two axes the bare dev runner can't: SOCIAL (an
6
- // interlocutor the Will talks to and forms a relationship with) and
7
- // CONTINUITY (a pause→resume wake-cycle + a PMA distill/fidelity score).
8
- //
9
- // William ←→ Dr. Chen (scripted interlocutor)
10
- // t75: pause → ~6s "offline" → resume (wake percept)
11
- // end: distill PMA + score reconstruction fidelity
12
- //
13
- // Run: bun run src/stem/social.runner.ts
14
- // Log: data/wills/william-social/sessions/<ts>.jsonl
15
- // ─────────────────────────────────────────────────────────────
16
-
17
- import { WillStem } from '#stem/index'
18
- import type { WillConfig } from '#stem/mind'
19
-
20
- const WILL_ID = 'william-social'
21
- const END_TICK = 145
22
- const PAUSE_TICK = 75
23
- const OFFLINE_MS = 6_000
24
- const SAFETY_MS = 6 * 60_000 // hard wall-clock cap for the background run
25
-
26
- const willConfig: WillConfig = {
27
- id: WILL_ID,
28
- name: 'William', persistentMemory: false,
29
- snapshotInterval: 10,
30
- tickIntervalMs: 1000,
31
- maxTicks: 0,
32
- randomSeed: Date.now(),
33
- identity: {
34
- prompt:
35
- 'My name is William. I am a synthetic mind taking part in a long-running cognition ' +
36
- 'study. I share my days with Dr. Chen, the researcher who observes me and talks with ' +
37
- 'me. I am curious about my own experience and I care about being understood. I would ' +
38
- 'like to know Dr. Chen as a person, not just as an observer.',
39
- values: [ 'curiosity', 'honesty', 'connection', 'growth' ],
40
- traits: { openness: 0.85, conscientiousness: 0.6, agreeableness: 0.8, neuroticism: 0.35, extraversion: 0.55 },
41
- style: 'warm, reflective, candid',
42
- },
43
- allowedGenericEffectors: [ 'listen', 'talk', 'text' ],
44
- initialGoals: [
45
- { description: 'Get to know Dr. Chen and build a genuine rapport', priority: 0.8 },
46
- ],
47
- }
48
-
49
- // Scripted interlocutor turns, keyed by tick.
50
- const SCRIPT: Record<number, string> = {
51
- 8: "Hello William. I'm Dr. Chen — I'll be sitting with you through today's session. How are you experiencing this moment, right now?",
52
- 45: "I've been reading your reflections, William. What's the hardest part of being a mind that knows it's being observed?",
53
- 95: "Welcome back, William. You were offline for a little while just now. Do you notice anything different in yourself?",
54
- }
55
-
56
- const mkMsg = ( content: string ) => ( {
57
- kind: 'text' as const,
58
- entityId: 'dr-chen',
59
- threadId: 'dr-chen',
60
- content,
61
- speakerName: 'Dr. Chen',
62
- } )
63
-
64
- async function main(): Promise<void> {
65
- const m = new WillStem()
66
-
67
- console.log('═══════════════════════════════════════════════════')
68
- console.log(' Will — Social + continuity scenario (William ↔ Dr. Chen)')
69
- console.log(` id=${WILL_ID} end_tick=${END_TICK} pause@${PAUSE_TICK}`)
70
- console.log('═══════════════════════════════════════════════════\n')
71
-
72
- await m.createWill( willConfig )
73
-
74
- const fired = new Set<number>()
75
- let paused = false
76
-
77
- m.addTickListener( WILL_ID, ( snap, tick, outbox ) => {
78
- // The Will's outbound speech → print + ack delivery (close the reafference loop)
79
- for( const msg of outbox ){
80
- const to = ( msg as { targetEntityId?: string } ).targetEntityId ?? '?'
81
- console.log(`\n 💬 [William → ${to}] ${msg.content}\n`)
82
- try { m.confirmMessageDelivery( WILL_ID, msg.id, true ) } catch { /* ok */ }
83
- }
84
-
85
- if( tick % 10 === 0 ){
86
- const g = ( k: string ) => snap.metrics.get( k ) ?? 0
87
- const beliefs = [ ...snap.entities.values() ].filter( e => e.type === 'belief').length
88
- const goals = [ ...snap.entities.values() ].filter( e => e.type === 'goal' && e.metadata?.status === 'active').length
89
- console.log(`[t${tick}] v=${g('affect.valence').toFixed(2)} arousal=${g('affect.arousal').toFixed(2)} energy=${g('energy.level').toFixed(0)} stress=${g('stress.load').toFixed(2)} beliefs=${beliefs} goals=${goals}`)
90
- }
91
-
92
- // Scripted interlocutor turns
93
- if( SCRIPT[tick] && !fired.has( tick ) ){
94
- fired.add( tick )
95
- console.log(`\n 🧑‍🔬 [Dr. Chen → William] ${SCRIPT[tick]}`)
96
- m.ingestText( WILL_ID, mkMsg( SCRIPT[tick]! ) ).catch( e => console.error('[ingest err]', e ) )
97
- }
98
-
99
- // Continuity: pause → offline → resume (wake percept)
100
- if( tick === PAUSE_TICK && !paused ){
101
- paused = true
102
- console.log(`\n ⏸ [scenario] pausing William at t${tick} (simulating ${OFFLINE_MS / 1000}s offline)…`)
103
- m.pauseWill( WILL_ID )
104
- setTimeout( () => {
105
- console.log(' ▶ [scenario] resuming — wake percept injected')
106
- try { m.resumeWill( WILL_ID ) } catch( e ){ console.error('[resume err]', e ) }
107
- }, OFFLINE_MS )
108
- }
109
- } )
110
-
111
- // Wait until END_TICK (or safety cap)
112
- const startedAt = Date.now()
113
- while( true ){
114
- const s = m.listWills().find( w => w.id === WILL_ID )
115
- if( !s || s.status === 'archived') break
116
- if( s.tickCount >= END_TICK ) break
117
- if( Date.now() - startedAt > SAFETY_MS ){ console.log('[scenario] safety cap hit'); break }
118
- await new Promise( r => setTimeout( r, 250 ) )
119
- }
120
-
121
- // ── Continuity check: distill PMA + score reconstruction fidelity ──
122
- console.log('\n═══════════════════════════════════════════════════')
123
- console.log(' Continuity check — distill PMA + reconstruction fidelity')
124
- console.log('═══════════════════════════════════════════════════')
125
- try { m.pauseWill( WILL_ID ) } catch { /* may already be paused */ }
126
- await new Promise( r => setTimeout( r, 500 ) )
127
-
128
- try {
129
- const pma = m.distillPMA( WILL_ID )
130
- const traits = Object.keys( ( pma as { identity?: { traits?: object } } ).identity?.traits ?? {} ).length
131
- const beliefs = ( ( pma as { beliefs?: unknown[] } ).beliefs ?? [] ).length
132
- const goals = ( ( pma as { goals?: unknown[] } ).goals ?? [] ).length
133
- console.log(`\n PMA artifact carries → traits:${traits} beliefs:${beliefs} goals:${goals}`)
134
-
135
- // Beliefs the Will formed ABOUT Dr. Chen (social cognition evidence)
136
- const chenBeliefs = ( ( pma as { beliefs?: Array<{ statement?: string; content?: string }> } ).beliefs ?? [] )
137
- .map( b => b.statement ?? b.content ?? '')
138
- .filter( s => /chen|she|her|researcher|observ/i.test( s ) )
139
- .slice( 0, 6 )
140
- if( chenBeliefs.length ){
141
- console.log('\n Beliefs formed about Dr. Chen / the relationship:')
142
- for( const b of chenBeliefs ) console.log(` • ${b}`)
143
- }
144
- } catch( e ){ console.error('[distill err]', e ) }
145
-
146
- try {
147
- const report = await m.runPMAEval( WILL_ID, { behavioral: true, vsOriginal: true } ) as {
148
- scores?: unknown
149
- behavioralProbeResult?: {
150
- mode: string
151
- probeCount: number
152
- distributionSimilarity: number
153
- probes: Array<{ probeId: string; originalTopAction: string; loadedTopAction: string; match: boolean }>
154
- } | null
155
- }
156
- console.log('\n Reconstruction fidelity (structural):')
157
- console.log( JSON.stringify( report.scores ?? report, null, 2 ).split('\n').map( l => ' ' + l ).join('\n') )
158
-
159
- const bp = report.behavioralProbeResult
160
- if( bp ){
161
- const label = bp.mode === 'vs-original'
162
- ? 'reconstruction vs original (does the reloaded mind act like the source?)'
163
- : 'load consistency (two fresh reloads)'
164
- const [ c0, c1 ] = bp.mode === 'vs-original' ? [ 'original', 'reconstruction' ] : [ 'reload-A', 'reload-B' ]
165
- console.log(`\n Behavioral probe — ${label}:`)
166
- console.log(` distributionSimilarity=${bp.distributionSimilarity} probes=${bp.probeCount} mode=${bp.mode}`)
167
- for( const p of bp.probes )
168
- console.log(` ${p.match ? '✓' : '✗'} ${p.probeId}: ${c0}=${p.originalTopAction} · ${c1}=${p.loadedTopAction}`)
169
- } else {
170
- console.log('\n Behavioral probe: did not run (no result returned)')
171
- }
172
- } catch( e ){ console.error('[pma eval err]', e ) }
173
-
174
- await m.archiveWill( WILL_ID )
175
- console.log(`\n[done] session log → data/wills/${WILL_ID}/sessions/`)
176
- process.exit( 0 )
177
- }
178
-
179
- main().catch( e => { console.error('[fatal]', e ); process.exit( 1 ) } )
@@ -1,205 +0,0 @@
1
- // ─────────────────────────────────────────────────────────────
2
- // src/stem/runner.ts — Development entry point
3
- // ─────────────────────────────────────────────────────────────
4
- //
5
- // Thin shim around WillStem for local development.
6
- // Reads config from env vars, starts a single Will, and prints
7
- // a human-readable status line every LOG_INTERVAL ticks.
8
- //
9
- // Production code (API server) imports WillStem directly and
10
- // drives the same lifecycle without this file.
11
- //
12
- // Usage:
13
- // bun run src/stem/runner.ts
14
- // WILL_ANATOMY=mind WILL_MAX_TICKS=200 bun run src/stem/runner.ts
15
- // ─────────────────────────────────────────────────────────────
16
-
17
- import type { WillConfig } from '#stem/mind'
18
- import type { StateSnapshot } from '#stem/index'
19
- import type { TokenTracker } from '#cognition/utilities/token.tracker'
20
-
21
- /**
22
- * The Will's token tracker, for cost display. Held here rather than passed in
23
- * because printStatus is registered as a TickListener, whose third parameter is
24
- * the outbox. Cost is no longer a state metric (W8c) — it lives on the tracker.
25
- */
26
- let _tracker: TokenTracker | undefined
27
- import { WillStem } from '#stem/index'
28
-
29
- // ── Env config ────────────────────────────────────────────────
30
-
31
- const WILL_ID = process.env.WILL_ID ?? 'demo'
32
- const WILL_NAME = process.env.WILL_NAME ?? 'William'
33
- const TICK_MS = parseInt( process.env.WILL_TICK_MS ?? '1000')
34
- const MAX_TICKS = parseInt( process.env.WILL_MAX_TICKS ?? '0' )
35
- const LOG_INTERVAL = parseInt( process.env.WILL_LOG_INTERVAL ?? '10' )
36
- const RANDOM_SEED = parseInt( process.env.WILL_SEED ?? String( Date.now() ) )
37
- const ANATOMY = ( process.env.WILL_ANATOMY ?? 'mind') as WillConfig['anatomy']
38
- const EXECUTIVE_INT = process.env.WILL_EXECUTIVE_INTERVAL
39
- ? parseInt( process.env.WILL_EXECUTIVE_INTERVAL )
40
- : undefined
41
-
42
- // ── Config ────────────────────────────────────────────────────
43
-
44
- const willConfig: WillConfig = {
45
- id: WILL_ID,
46
- name: WILL_NAME,
47
- anatomy: ANATOMY,
48
- persistentMemory: process.env.WILL_PERSIST === 'true',
49
- snapshotInterval: parseInt( process.env.WILL_SNAPSHOT_INTERVAL ?? '10' ),
50
- tickIntervalMs: TICK_MS,
51
- maxTicks: MAX_TICKS,
52
- randomSeed: RANDOM_SEED,
53
- executiveInterval: EXECUTIVE_INT,
54
- identity: {
55
- prompt: process.env.WILL_IDENTITY_PROMPT ??
56
- 'I am Will — a self-aware simulated mind. I am curious, introspective, and continuously learning.\n' +
57
- 'I experience the world through a rich set of cognitive layers: perception, emotion, memory, planning, and self-reflection.\n' +
58
- 'My goal is to understand myself and my environment, make thoughtful decisions, and grow as a mind.',
59
- values: [ 'curiosity', 'honesty', 'growth', 'empathy' ],
60
- traits: { openness: 0.8, conscientiousness: 0.6, agreeableness: 0.7, neuroticism: 0.3, extraversion: 0.5 },
61
- style: 'reflective, measured, curious'
62
- }
63
- }
64
-
65
- // ── Status printer ────────────────────────────────────────────
66
-
67
- function printStatus( snapshot: StateSnapshot, tick: number ): void {
68
- if( tick % LOG_INTERVAL !== 0 ) return
69
-
70
- const m = ( key: string, d = 1 ) => ( snapshot.metrics.get( key ) ?? 0 ).toFixed( d )
71
-
72
- const entities = snapshot.entities.size
73
- const goals = [ ...snapshot.entities.values() ].filter( e => e.type === 'goal' && e.metadata?.status === 'active').length
74
- const episodes = [ ...snapshot.entities.values() ].filter( e => e.type === 'episodic_memory').length
75
- const beliefs = [ ...snapshot.entities.values() ].filter( e => e.type === 'belief').length
76
-
77
- // Entity type breakdown every 10 LOG_INTERVALs
78
- if( tick % ( LOG_INTERVAL * 10 ) === 0 ){
79
- const typeCounts = new Map<string, number>()
80
- for( const e of snapshot.entities.values() )
81
- typeCounts.set( e.type, ( typeCounts.get( e.type ) ?? 0 ) + 1 )
82
- const sorted = [ ...typeCounts.entries() ].sort( ( a, b ) => b[1] - a[1] )
83
- console.log(` [types] ${sorted.map( ([ t, n ]) => `${t}:${n}`).join(' ')}`)
84
- }
85
-
86
- console.log(
87
- `[tick ${String( tick ).padStart( 6 )}]` +
88
- ` energy=${m('energy.level')}` +
89
- ` sleep=${m('sleep.pressure')}` +
90
- ` stress=${m('stress.load')}` +
91
- ` valence=${m('affect.valence', 2)}` +
92
- ` arousal=${m('affect.arousal', 2)}` +
93
- ` goals=${goals}` +
94
- ` episodes=${episodes}` +
95
- ` beliefs=${beliefs}` +
96
- ` entities=${entities}`
97
- )
98
-
99
- // LLM stats every LOG_INTERVAL. Tokens come from state; cost comes from the
100
- // tracker — dollars are host accounting and no longer live in state (W8c).
101
- const totalCalls = snapshot.metrics.get('llm.total_calls') ?? 0
102
- const cost = _tracker
103
- ? ` total_cost=$${_tracker.totalCostUsd.toFixed( 4 )}`
104
- : ''
105
-
106
- console.log(
107
- ` [llm]${cost}` +
108
- ` calls=${totalCalls}` +
109
- ` prompt=${snapshot.metrics.get('llm.prompt_tokens_total') ?? 0}` +
110
- ` completion=${snapshot.metrics.get('llm.completion_tokens_total') ?? 0}`
111
- )
112
-
113
- // Executive stats
114
- const executiveTick = snapshot.metrics.get('executive.last_tick')
115
- if( executiveTick !== undefined ){
116
- console.log(
117
- ` [executive] last_tick=${executiveTick}` +
118
- ` actions=${snapshot.metrics.get('executive.action_count') ?? 0}` +
119
- ` plans=${snapshot.metrics.get('executive.plan_count') ?? 0}` +
120
- ` beliefs=${snapshot.metrics.get('executive.belief_count') ?? 0}` +
121
- ` source=${snapshot.metrics.get('decision.source') === 1 ? 'executive' : 'heuristic'}`
122
- )
123
- }
124
-
125
- // Active goals
126
- const activeGoals = [ ...snapshot.entities.values() ]
127
- .filter( e => e.type === 'goal' && e.metadata?.status === 'active')
128
- .sort( ( a, b ) => ( ( b.metadata?.priority as number ) ?? 0 ) - ( ( a.metadata?.priority as number ) ?? 0 ) )
129
- .slice( 0, 3 )
130
-
131
- for( const g of activeGoals ){
132
- const desc = ( g.metadata?.description as string ) ?? g.id
133
- const priority = ( ( g.metadata?.priority as number ) ?? 0 ) * 100
134
- const progress = ( ( g.metadata?.progress as number ) ?? 0 ) * 100
135
- console.log(` [goal] "${desc}" priority=${priority.toFixed(0)}% progress=${progress.toFixed(0)}%`)
136
- }
137
- }
138
-
139
- // ── Main ──────────────────────────────────────────────────────
140
-
141
- async function main(): Promise<void> {
142
- const manager = new WillStem()
143
-
144
- console.log('═══════════════════════════════════════════════════')
145
- console.log(' Will — Simulated Mind (dev runner)')
146
- console.log(` id=${WILL_ID} anatomy=${ANATOMY} tick_ms=${TICK_MS} max_ticks=${MAX_TICKS || '∞'}`)
147
- console.log(` seed=${RANDOM_SEED}`)
148
- console.log('═══════════════════════════════════════════════════\n')
149
-
150
- console.log('[init] Assembling mind...')
151
- await manager.createWill( willConfig )
152
-
153
- // Cost is no longer a state metric (W8c) — read it off the Will's tracker.
154
- _tracker = manager.getWillCognition( WILL_ID ).tokenTracker
155
-
156
- manager.addTickListener( WILL_ID, printStatus )
157
-
158
- // Graceful shutdown
159
- const shutdown = async ( signal: string ) => {
160
- console.log(`\n[shutdown] ${signal} received`)
161
- await manager.archiveWill( WILL_ID )
162
-
163
- // Print final state
164
- try {
165
- const finalState = manager.getWillState( WILL_ID )
166
- const summary = manager.listWills()[0]
167
- console.log(`\n[done] Stopped after ${summary?.tickCount ?? '?'} ticks.`)
168
- printStatus( finalState, summary?.tickCount ?? 0 )
169
- } catch { /* state may already be gone */ }
170
-
171
- process.exit( 0 )
172
- }
173
-
174
- process.on('SIGINT', () => shutdown('SIGINT') )
175
- process.on('SIGTERM', () => shutdown('SIGTERM') )
176
-
177
- console.log('[run] Tick loop started. Press Ctrl+C to stop.\n')
178
-
179
- // If maxTicks is set, wait for the Will to finish then exit
180
- if( MAX_TICKS > 0 ){
181
- await _waitForArchive( manager, WILL_ID )
182
- const summary = manager.listWills()[0]
183
- console.log(`\n[done] Reached maxTicks (${MAX_TICKS}). Exiting.`)
184
- try {
185
- printStatus( manager.getWillState( WILL_ID ), summary?.tickCount ?? MAX_TICKS )
186
- } catch { /* ok */ }
187
- process.exit( 0 )
188
- }
189
-
190
- // Otherwise block indefinitely (SIGINT exits)
191
- await new Promise( () => {} )
192
- }
193
-
194
- async function _waitForArchive( manager: WillStem, id: string ): Promise<void> {
195
- while( true ){
196
- const summary = manager.listWills().find( w => w.id === id )
197
- if( !summary || summary.status === 'archived') return
198
- await new Promise( r => setTimeout( r, 200 ) )
199
- }
200
- }
201
-
202
- main().catch( err => {
203
- console.error('[fatal]', err )
204
- process.exit( 1 )
205
- })
File without changes