@mindot/will 0.5.0 → 0.6.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 (132) hide show
  1. package/dist/channels/discord.d.ts +1 -1
  2. package/dist/channels/discord.js.map +1 -1
  3. package/dist/channels/whatsapp.d.ts +1 -1
  4. package/dist/channels/whatsapp.js.map +1 -1
  5. package/dist/cli.js +567 -51
  6. package/dist/cli.js.map +1 -1
  7. package/dist/index.d.ts +2 -2
  8. package/dist/index.js +567 -51
  9. package/dist/index.js.map +1 -1
  10. package/dist/mcp/effectors.d.ts +1 -1
  11. package/dist/mcp/effectors.js.map +1 -1
  12. package/dist/{will-BDq-TMQr.d.ts → will-Bikuk4s2.d.ts} +48 -6
  13. package/package.json +1 -1
  14. package/src/channels/discord.ts +11 -11
  15. package/src/channels/roster.ts +1 -1
  16. package/src/channels/types.ts +1 -1
  17. package/src/channels/whatsapp.ts +25 -25
  18. package/src/cli.ts +20 -20
  19. package/src/cognition/acp.ts +28 -0
  20. package/src/cognition/agency/consequence.ts +174 -0
  21. package/src/cognition/agency/engines/action.selector.ts +301 -48
  22. package/src/cognition/agency/engines/affordance.synthesizer.ts +26 -16
  23. package/src/cognition/agency/engines/deliberation.engine.ts +28 -14
  24. package/src/cognition/agency/engines/motor.schema.executor.ts +86 -14
  25. package/src/cognition/agency/engines/reafference.engine.ts +122 -18
  26. package/src/cognition/agency/execution.primitives.ts +13 -13
  27. package/src/cognition/agency/proactive.communicator.ts +1 -1
  28. package/src/cognition/agency/reconcile.learning.ts +1 -1
  29. package/src/cognition/agency/revocation.ts +79 -0
  30. package/src/cognition/agency/schemas/repertoire.ts +2 -2
  31. package/src/cognition/agency/selection.scoring.ts +25 -9
  32. package/src/cognition/bus.ts +2 -2
  33. package/src/cognition/completion.inbox.ts +1 -1
  34. package/src/cognition/config.mirror.entities.ts +5 -5
  35. package/src/cognition/event.log.ts +2 -2
  36. package/src/cognition/event.schemas.ts +67 -67
  37. package/src/cognition/faculties/aesthetic.evaluator.ts +6 -6
  38. package/src/cognition/faculties/affective.blender.ts +36 -4
  39. package/src/cognition/faculties/attachment.evaluator.ts +6 -6
  40. package/src/cognition/faculties/attention.allocator.ts +63 -8
  41. package/src/cognition/faculties/autobiographical.narrator.ts +3 -3
  42. package/src/cognition/faculties/bias.detector.ts +7 -7
  43. package/src/cognition/faculties/circadian.oscillator.ts +3 -3
  44. package/src/cognition/faculties/confidence.calibrator.ts +7 -7
  45. package/src/cognition/faculties/dream.simulator.ts +5 -5
  46. package/src/cognition/faculties/empathy.simulator.ts +7 -7
  47. package/src/cognition/faculties/energy.regulator.ts +4 -4
  48. package/src/cognition/faculties/episodic.consolidator.ts +6 -6
  49. package/src/cognition/faculties/executive.engine/commands.ts +6 -6
  50. package/src/cognition/faculties/executive.engine/context.ts +42 -42
  51. package/src/cognition/faculties/executive.engine/deferred.effects.ts +2 -2
  52. package/src/cognition/faculties/executive.engine/engine.ts +25 -25
  53. package/src/cognition/faculties/executive.engine/facet.supervisor.ts +12 -12
  54. package/src/cognition/faculties/executive.engine/facet.ts +18 -18
  55. package/src/cognition/faculties/executive.engine/gating.ts +2 -2
  56. package/src/cognition/faculties/executive.engine/messages.ts +3 -3
  57. package/src/cognition/faculties/executive.engine/parser.ts +11 -11
  58. package/src/cognition/faculties/executive.engine/prompt.factory.ts +55 -55
  59. package/src/cognition/faculties/exteroception.ts +99 -5
  60. package/src/cognition/faculties/forgetting.curve.ts +3 -3
  61. package/src/cognition/faculties/frustration.evaluator.ts +6 -6
  62. package/src/cognition/faculties/goal.manager.ts +15 -15
  63. package/src/cognition/faculties/inhibition.controller.ts +3 -3
  64. package/src/cognition/faculties/interoception.ts +3 -3
  65. package/src/cognition/faculties/introspection.engine.ts +3 -3
  66. package/src/cognition/faculties/known.entity.tracker.ts +15 -15
  67. package/src/cognition/faculties/loss.evaluator.ts +2 -2
  68. package/src/cognition/faculties/moral.evaluator.ts +4 -4
  69. package/src/cognition/faculties/novelty.detector.ts +4 -4
  70. package/src/cognition/faculties/persona.consolidator.ts +12 -12
  71. package/src/cognition/faculties/planning.engine/engine.ts +47 -47
  72. package/src/cognition/faculties/planning.engine/plan.frontier.ts +5 -5
  73. package/src/cognition/faculties/planning.engine/plan.store.ts +1 -1
  74. package/src/cognition/faculties/planning.engine/plan.supervision.ts +20 -20
  75. package/src/cognition/faculties/reputation.tracker.ts +6 -6
  76. package/src/cognition/faculties/reward.evaluator.ts +4 -4
  77. package/src/cognition/faculties/self.model.updater.ts +8 -8
  78. package/src/cognition/faculties/semantic.engine/integrator.ts +15 -15
  79. package/src/cognition/faculties/sleep.pressure.regulator.ts +4 -4
  80. package/src/cognition/faculties/social.perception.ts +3 -3
  81. package/src/cognition/faculties/spaced.repetition.ts +2 -2
  82. package/src/cognition/faculties/stress.regulator.ts +27 -4
  83. package/src/cognition/faculties/task.switcher.ts +11 -6
  84. package/src/cognition/faculties/theory.of.mind.ts +6 -6
  85. package/src/cognition/faculties/threat.evaluator.ts +3 -3
  86. package/src/cognition/faculties/working.memory.ts +8 -8
  87. package/src/cognition/generative.model.ts +2 -2
  88. package/src/cognition/memory/vector.adapter.ts +5 -5
  89. package/src/cognition/memory/vector.content.ts +4 -4
  90. package/src/cognition/memory/vector.embedder.ts +9 -9
  91. package/src/cognition/persona.prior.ts +1 -1
  92. package/src/cognition/schema.registry.ts +2 -2
  93. package/src/cognition/senses/audition.engine/engine.ts +2 -2
  94. package/src/cognition/senses/base.sense.engine.ts +1 -1
  95. package/src/cognition/utilities/token.tracker.ts +5 -5
  96. package/src/core/abstracts.ts +1 -1
  97. package/src/core/completion.recorder.ts +2 -2
  98. package/src/core/serialization.ts +3 -3
  99. package/src/core/snapshot.manager.ts +1 -1
  100. package/src/core/state.manager.ts +1 -1
  101. package/src/core/utils.ts +1 -1
  102. package/src/host/boot.ts +30 -30
  103. package/src/host/utterances.ts +1 -1
  104. package/src/llm/index.ts +9 -9
  105. package/src/llm/summarizer.ts +4 -4
  106. package/src/llm/wire.contracts.ts +1 -1
  107. package/src/mcp/effectors.ts +10 -10
  108. package/src/mcp/server.ts +11 -11
  109. package/src/pma/eval.ts +1 -1
  110. package/src/pma/index.ts +21 -21
  111. package/src/runners/outreach.runner.ts +3 -3
  112. package/src/runners/social.runner.ts +1 -1
  113. package/src/runners/thin-shim.runner.ts +1 -1
  114. package/src/sdk/will.ts +5 -5
  115. package/src/serve/server.ts +12 -12
  116. package/src/stem/assembly.audit.ts +3 -3
  117. package/src/stem/guards/identity.coherence.ts +10 -10
  118. package/src/stem/guards/identity.guard.ts +22 -22
  119. package/src/stem/index.ts +11 -11
  120. package/src/stem/mind.ts +12 -12
  121. package/src/stem/tracts/biography.writer.ts +3 -3
  122. package/src/stem/tracts/effector.controller.ts +4 -4
  123. package/src/stem/tracts/health.reporter.ts +1 -1
  124. package/src/stem/tracts/outbox.controller.ts +4 -0
  125. package/src/stem/tracts/outbox.writer.ts +4 -4
  126. package/src/stem/tracts/pma.controller.ts +1 -1
  127. package/src/stem/tracts/replay.controller.ts +10 -10
  128. package/src/stem/tracts/sensory.controller.ts +2 -2
  129. package/src/stem/tracts/session.logger.ts +4 -4
  130. package/src/stem/tracts/transport/socketio.transport.ts +7 -7
  131. package/src/stem/tracts/transport/stream.transport.ts +2 -2
  132. package/src/stem/tracts/transport.controller.ts +15 -15
@@ -103,7 +103,7 @@ export async function buildExecutiveContext(
103
103
  }
104
104
 
105
105
  // Filter goal-type episodes — they duplicate the Active Goals section
106
- const recalled = combined.filter( ep => ep.sourceType !== 'goal' ).slice( 0, 8 )
106
+ const recalled = combined.filter( ep => ep.sourceType !== 'goal').slice( 0, 8 )
107
107
  relevantPlanIds = collectPlanIds( recalled )
108
108
  memories = recalled.map( mapEpisodeToMemory )
109
109
  // Recall reinforces retention: marking each surfaced episode as retrieved
@@ -117,7 +117,7 @@ export async function buildExecutiveContext(
117
117
  // the default query order may not be chronological when using PMA replay.
118
118
  const fallbackResults = deps.episodicConsolidator.query({ limit: 20 })
119
119
  const recalled = fallbackResults
120
- .filter( ep => ep.sourceType !== 'goal' )
120
+ .filter( ep => ep.sourceType !== 'goal')
121
121
  .slice()
122
122
  .sort( ( a, b ) => ( ( b.createdAt as unknown as number ) ?? 0 ) - ( ( a.createdAt as unknown as number ) ?? 0 ) )
123
123
  .slice( 0, 8 )
@@ -168,7 +168,7 @@ export async function buildExecutiveContext(
168
168
 
169
169
  // ── Stage 1: Deduplication ────────────────────────────────
170
170
  const _tokenize = ( s: string ): Set<string> =>
171
- new Set( s.toLowerCase().replace( /[^a-z0-9 ]/g, '' ).split( /\s+/ ).filter( Boolean ) )
171
+ new Set( s.toLowerCase().replace( /[^a-z0-9 ]/g, '').split( /\s+/ ).filter( Boolean ) )
172
172
 
173
173
  const _jaccard = ( a: Set<string>, b: Set<string> ): number => {
174
174
  let intersection = 0
@@ -236,7 +236,7 @@ export async function buildExecutiveContext(
236
236
  // impulsivity falls as conscientiousness is demonstrated. So it is no longer static
237
237
  // per session. `readEffectiveParams` only layers a prior onto a key the base already
238
238
  // has, so absent a PMA seed this degrades to base ⇒ undefined disposition.
239
- const execParams = readEffectiveParams( state, 'engine-config-executive' )
239
+ const execParams = readEffectiveParams( state, 'engine-config-executive')
240
240
  const behavioralDisposition = (
241
241
  execParams.riskTolerance !== undefined ||
242
242
  execParams.explorationRate !== undefined ||
@@ -257,7 +257,7 @@ export async function buildExecutiveContext(
257
257
  }> = []
258
258
 
259
259
  for( const entity of state.entities.values() ){
260
- if( entity.type !== 'decision.record' ) continue
260
+ if( entity.type !== 'decision.record') continue
261
261
  const actionStatus = entity.metadata?.actionStatus as string | undefined
262
262
  if( !actionStatus ) continue
263
263
  if( !( [ 'completed', 'failed', 'awaiting_host', 'timed_out' ] as string[] ).includes( actionStatus ) ) continue
@@ -266,7 +266,7 @@ export async function buildExecutiveContext(
266
266
  type: ( entity.metadata?.actionType as string ) ?? 'unknown',
267
267
  status: actionStatus as 'completed' | 'failed' | 'awaiting_host' | 'timed_out',
268
268
  tick: ( entity.metadata?.executionTick as number ) ?? ( entity.metadata?.dispatchedAt as number ) ?? 0,
269
- outcome: String( entity.metadata?.outcome ?? '' ).slice( 0, 120 ),
269
+ outcome: String( entity.metadata?.outcome ?? '').slice( 0, 120 ),
270
270
  planId: entity.metadata?.planId as string | undefined,
271
271
  })
272
272
  }
@@ -280,7 +280,7 @@ export async function buildExecutiveContext(
280
280
  // progress, enabling it to target a specific plan by id when managing several. (P4)
281
281
  const plans: ExecutiveContext['plans'] = []
282
282
  for( const entity of state.entities.values() ){
283
- if( entity.type !== 'plan' ) continue
283
+ if( entity.type !== 'plan') continue
284
284
  const m = entity.metadata ?? {}
285
285
  const steps = ( m['steps'] as Array<{ status?: string }> | undefined ) ?? []
286
286
  plans.push({
@@ -289,7 +289,7 @@ export async function buildExecutiveContext(
289
289
  status: ( m['status'] as string ) ?? 'unknown',
290
290
  executionTier: ( m['executionTier'] as string ) ?? 'automatic',
291
291
  totalSteps: steps.length,
292
- completedSteps: steps.filter( s => s.status === 'completed' || s.status === 'skipped' ).length,
292
+ completedSteps: steps.filter( s => s.status === 'completed' || s.status === 'skipped').length,
293
293
  expectedOutcome: ( m['expectedOutcome'] as string ) ?? '',
294
294
  requestingEntityId: m['requestingEntityId'] as string | undefined,
295
295
  })
@@ -346,7 +346,7 @@ const MAX_SURFACED_ABILITIES = 8
346
346
  export function extractAbilities( state: ReadonlySimulationState ): ExecutiveContext['abilities'] {
347
347
  const out: NonNullable<ExecutiveContext['abilities']> = []
348
348
  for( const e of state.entities.values() ){
349
- if( e.type !== 'affordance' ) continue
349
+ if( e.type !== 'affordance') continue
350
350
  const m = e.metadata as Record<string, unknown> | undefined
351
351
  if( m?.['source'] !== 'external' || m?.['available'] === false ) continue
352
352
  const name = typeof m?.['schema'] === 'string' ? m['schema'] as string : undefined
@@ -372,13 +372,13 @@ export function extractCurrentFocus(
372
372
  state: ReadonlySimulationState,
373
373
  goals: ExecutiveContext['goals']
374
374
  ): ExecutiveContext['currentFocus'] {
375
- const m = state.entities.get( 'task-switch-focus' )?.metadata as Record<string, unknown> | undefined
375
+ const m = state.entities.get('task-switch-focus')?.metadata as Record<string, unknown> | undefined
376
376
  if( !m?.goalId ) return undefined
377
377
  return {
378
378
  goalId: m.goalId as string,
379
379
  goalDescription: goals.find( g => g.id === m.goalId )?.description,
380
380
  focusTicks: ( m.focusTicks as number ) ?? 0,
381
- switchCost: state.metrics.get( 'task_switch.switch_cost' ) ?? 0,
381
+ switchCost: state.metrics.get('task_switch.switch_cost') ?? 0,
382
382
  }
383
383
  }
384
384
 
@@ -397,7 +397,7 @@ export function extractKnownEntities( state: ReadonlySimulationState ): Executiv
397
397
  // triple / dossier / beliefs under the old keid all aggregate under the one someone.
398
398
  const alias = new Map<string, string>()
399
399
  for( const e of state.entities.values() )
400
- if( e.type === 'known-entity-alias' ){
400
+ if( e.type === 'known-entity-alias'){
401
401
  const a = e.metadata?.aliasKeid as string | undefined
402
402
  const c = e.metadata?.canonicalKeid as string | undefined
403
403
  if( a && c ) alias.set( a, c )
@@ -421,7 +421,7 @@ export function extractKnownEntities( state: ReadonlySimulationState ): Executiv
421
421
  }
422
422
  else if( e.type === 'reputation' && m.keid ){
423
423
  const a = get( m.keid as string )
424
- if( typeof m.name === 'string' ) a.name = m.name
424
+ if( typeof m.name === 'string') a.name = m.name
425
425
  a.trust = m.trustworthiness as number
426
426
  a.cooperativeness = m.cooperativeness as number
427
427
  a.reliability ??= m.reliability as number // sentient social reliability — the dossier's wins if present
@@ -433,13 +433,13 @@ export function extractKnownEntities( state: ReadonlySimulationState ): Executiv
433
433
  // sentient social one). (familiarity is intentionally NOT surfaced — it decays each
434
434
  // tick and would churn the cached prompt; it stays internal to the tracker.)
435
435
  const a = get( m.keid as string )
436
- if( typeof m.name === 'string' ) a.name = m.name
437
- if( m.kind === 'thing' || m.kind === 'sentient' ) a.kind = m.kind as 'thing' | 'sentient'
438
- if( typeof m.reliability === 'number' ) a.reliability = m.reliability as number
436
+ if( typeof m.name === 'string') a.name = m.name
437
+ if( m.kind === 'thing' || m.kind === 'sentient') a.kind = m.kind as 'thing' | 'sentient'
438
+ if( typeof m.reliability === 'number') a.reliability = m.reliability as number
439
439
  a._recency = Math.max( a._recency, ( m.lastSeenTick as number ) ?? 0 )
440
440
  }
441
- else if( e.type === 'attachment.bond' ){
442
- const keid = ( m.keid as string ) ?? e.id.replace( /^bond-/, '' )
441
+ else if( e.type === 'attachment.bond'){
442
+ const keid = ( m.keid as string ) ?? e.id.replace( /^bond-/, '')
443
443
  get( keid ).closeness = m.attachmentStrength as number
444
444
  }
445
445
  }
@@ -465,33 +465,33 @@ function buildSemanticQuery(
465
465
  // Active goals (highest priority first)
466
466
  const goals = goalManager?.getActiveGoals().slice( 0, 3 ) ?? []
467
467
  if( goals.length > 0 ){
468
- parts.push( `Current goals: ${goals.map( g => g.description ).join( '; ' )}` )
468
+ parts.push(`Current goals: ${goals.map( g => g.description ).join('; ')}`)
469
469
  }
470
470
 
471
471
  // Dominant emotion if intense
472
472
  const valence = state.metrics.get('affect.valence') ?? 0
473
473
  const dominantEmotion = valence > 0.3 ? 'positive' : valence < -0.3 ? 'negative' : 'neutral'
474
- if( dominantEmotion !== 'neutral' ) parts.push( `Feeling ${dominantEmotion}` )
474
+ if( dominantEmotion !== 'neutral') parts.push(`Feeling ${dominantEmotion}`)
475
475
 
476
476
  // Active conversation entities — pulls memories about current interlocutors
477
477
  const senderNames = new Set<string>()
478
478
  for( const entity of state.entities.values() ){
479
- if( entity.type !== 'communication' ) continue
479
+ if( entity.type !== 'communication') continue
480
480
  const msgTick = ( entity.metadata?.tick as number ) ?? 0
481
481
  if( state.tick - msgTick > 30 ) continue
482
482
  if( entity.metadata?.processedByExecutive ) continue
483
483
  const name = entity.metadata?.agentName as string | undefined
484
- if( name && name !== 'unknown' ) senderNames.add( name )
484
+ if( name && name !== 'unknown') senderNames.add( name )
485
485
  }
486
- if( senderNames.size > 0 ) parts.push( `Talking with: ${[ ...senderNames ].join( ', ' )}` )
486
+ if( senderNames.size > 0 ) parts.push(`Talking with: ${[ ...senderNames ].join(', ')}`)
487
487
 
488
488
  // Recent percepts (top 3 by salience)
489
489
  const percepts = extractPercepts( state ).slice( 0, 3 )
490
490
  if( percepts.length > 0 ){
491
- parts.push( `Recently observed: ${percepts.map( p => p.summary ).join( '; ' )}` )
491
+ parts.push(`Recently observed: ${percepts.map( p => p.summary ).join('; ')}`)
492
492
  }
493
493
 
494
- return parts.length > 0 ? parts.join( '. ' ) : 'Current situation'
494
+ return parts.length > 0 ? parts.join('. ') : 'Current situation'
495
495
  }
496
496
 
497
497
  /** Pull planIds from recalled plan-descriptor episodes (their content carries planId). */
@@ -500,26 +500,26 @@ function collectPlanIds( episodes: Array<{ content: unknown }> ): string[] {
500
500
  for( const ep of episodes ){
501
501
  const c = ep.content as Record<string, any> | null | undefined
502
502
  const pid = c?.[ 'planId' ] ?? c?.[ 'content' ]?.[ 'planId' ]
503
- if( typeof pid === 'string' ) ids.push( pid )
503
+ if( typeof pid === 'string') ids.push( pid )
504
504
  }
505
505
  return [ ...new Set( ids ) ]
506
506
  }
507
507
 
508
508
  function _extractEpisodeContent( raw: unknown ): string {
509
- if( typeof raw === 'string' ) return raw
509
+ if( typeof raw === 'string') return raw
510
510
  if( typeof raw !== 'object' || raw === null ) return String( raw )
511
511
  const c = raw as Record<string, unknown>
512
512
 
513
513
  // WMItem wrapper: { wmType, content: { description | summary | ... } }
514
514
  // Check wmType first so we correctly unwrap structured WM items.
515
- if( typeof c['wmType'] === 'string' ){
515
+ if( typeof c['wmType'] === 'string'){
516
516
  const inner = c['content']
517
- if( typeof inner === 'string' ) return inner
517
+ if( typeof inner === 'string') return inner
518
518
  if( typeof inner === 'object' && inner !== null ){
519
519
  const ic = inner as Record<string, unknown>
520
- if( typeof ic['description'] === 'string' ) return ic['description']
521
- if( typeof ic['summary'] === 'string' ) return ic['summary']
522
- if( typeof ic['userMessage'] === 'string' ){
520
+ if( typeof ic['description'] === 'string') return ic['description']
521
+ if( typeof ic['summary'] === 'string') return ic['summary']
522
+ if( typeof ic['userMessage'] === 'string'){
523
523
  const reply = typeof ic['willReply'] === 'string' ? ` → "${ic['willReply']}"` : ''
524
524
  return `"${ic['userMessage']}"${reply}`
525
525
  }
@@ -527,23 +527,23 @@ function _extractEpisodeContent( raw: unknown ): string {
527
527
  }
528
528
 
529
529
  // Plain percept WMItem: { summary } or nested { content: { summary } }
530
- if( typeof c['summary'] === 'string' ) return c['summary']
530
+ if( typeof c['summary'] === 'string') return c['summary']
531
531
  const inner = c['content']
532
- if( typeof inner === 'string' ) return inner
532
+ if( typeof inner === 'string') return inner
533
533
  if( typeof inner === 'object' && inner !== null ){
534
534
  const ic = inner as Record<string, unknown>
535
- if( typeof ic['summary'] === 'string' ) return ic['summary']
536
- if( typeof ic['description'] === 'string' ) return ic['description']
535
+ if( typeof ic['summary'] === 'string') return ic['summary']
536
+ if( typeof ic['description'] === 'string') return ic['description']
537
537
  }
538
538
  // Belief: { statement }
539
- if( typeof c['statement'] === 'string' ) return c['statement']
539
+ if( typeof c['statement'] === 'string') return c['statement']
540
540
  // Conversation turn: { userMessage, willReply }
541
- if( typeof c['userMessage'] === 'string' ){
541
+ if( typeof c['userMessage'] === 'string'){
542
542
  const reply = typeof c['willReply'] === 'string' ? ` → "${c['willReply']}"` : ''
543
543
  return `"${c['userMessage']}"${reply}`
544
544
  }
545
545
  // Goal: { description }
546
- if( typeof c['description'] === 'string' ) return c['description']
546
+ if( typeof c['description'] === 'string') return c['description']
547
547
  return JSON.stringify( raw ).slice( 0, 200 )
548
548
  }
549
549
 
@@ -570,10 +570,10 @@ function mapEpisodeToMemory( ep: {
570
570
  }
571
571
 
572
572
  function extractSummary( content: unknown ): string {
573
- if( typeof content === 'string' )
573
+ if( typeof content === 'string')
574
574
  return content.slice( 0, 120 )
575
575
 
576
- if( content && typeof content === 'object' ){
576
+ if( content && typeof content === 'object'){
577
577
  const obj = content as Record<string, unknown>
578
578
 
579
579
  return (obj.summary as string)
@@ -581,7 +581,7 @@ function extractSummary( content: unknown ): string {
581
581
  ?? JSON.stringify( content ).slice( 0, 120 )
582
582
  }
583
583
 
584
- return String( content ?? '' ).slice( 0, 120 )
584
+ return String( content ?? '').slice( 0, 120 )
585
585
  }
586
586
 
587
587
  function extractPercepts( state: ReadonlySimulationState ): Array<{ category: string; summary: string; salience: number }> {
@@ -72,7 +72,7 @@ export class DeferredEffectQueue {
72
72
  flush( state: ReadonlySimulationState, currentTick: number ): void {
73
73
  if( this._entries.length === 0 ) return
74
74
 
75
- const committedTick = state.metrics.get( 'executive.last_tick' )
75
+ const committedTick = state.metrics.get('executive.last_tick')
76
76
  const keep: DeferredEntry[] = []
77
77
 
78
78
  for( const entry of this._entries ){
@@ -87,7 +87,7 @@ export class DeferredEffectQueue {
87
87
  for( const effect of entry.effects ){
88
88
  try { effect() }
89
89
  catch( err ){
90
- logger.error( `[executive] deferred effect failed (tick ${entry.observedTick}):`, err )
90
+ logger.error(`[executive] deferred effect failed (tick ${entry.observedTick}):`, err )
91
91
  }
92
92
  }
93
93
  }
@@ -102,7 +102,7 @@ export interface ExecutiveEngineConfig {
102
102
  */
103
103
  export function effortTargetForActions( actionTypes: Iterable<string> ): number | null {
104
104
  const types = new Set( actionTypes )
105
- if( types.has( 'focus' ) ) return 1.0
105
+ if( types.has('focus') ) return 1.0
106
106
  if( [ 'rest', 'sleep', 'wait', 'meditate' ].some( t => types.has( t ) ) ) return 0.4
107
107
  return null
108
108
  }
@@ -308,10 +308,10 @@ export class ExecutiveEngine extends AsyncEngine implements CognitiveEngine {
308
308
  d = new LLMDirector( {
309
309
  willId: this._willId!,
310
310
  model,
311
- maxOutputTokens: this._llm?.maxOutputTokens ?? parseInt( process.env.WILL_MAX_OUTPUT_TOKENS ?? '8096' ),
311
+ maxOutputTokens: this._llm?.maxOutputTokens ?? parseInt( process.env.WILL_MAX_OUTPUT_TOKENS ?? '8096'),
312
312
  // Provider-agnostic key; falls back to ANTHROPIC_API_KEY for back-compat.
313
313
  apiKey: this._llm?.apiKey ?? process.env.WILL_LLM_API_KEY ?? process.env.ANTHROPIC_API_KEY ?? '',
314
- provider: ( this._llm?.provider ?? process.env.WILL_LLM_PROVIDER ?? 'anthropic' ) as LLMProvider,
314
+ provider: ( this._llm?.provider ?? process.env.WILL_LLM_PROVIDER ?? 'anthropic') as LLMProvider,
315
315
  // Optional base-URL override (e.g. Ollama / Azure / self-hosted). Unset →
316
316
  // the director uses the provider's official endpoint.
317
317
  baseUrl: this._llm?.baseUrl ?? process.env.WILL_LLM_BASE_URL ?? process.env.OPENAI_BASE_URL,
@@ -327,7 +327,7 @@ export class ExecutiveEngine extends AsyncEngine implements CognitiveEngine {
327
327
  return d
328
328
  }
329
329
 
330
- spawnFacet( role?: 'deliberation' | 'conversation' | 'outreach' | 'supervision' ): { attention: 'available' | 'full', handle?: ExecutiveFacetHandle } {
330
+ spawnFacet( role?: 'deliberation' | 'conversation' | 'outreach' | 'supervision'): { attention: 'available' | 'full', handle?: ExecutiveFacetHandle } {
331
331
  // Delegate to FacetSupervisor (R5-g-3), passing the current engine
332
332
  // attachments. The supervisor owns the registry + attention budget and
333
333
  // performs the throw-checks on bus / director / state ref.
@@ -376,7 +376,7 @@ export class ExecutiveEngine extends AsyncEngine implements CognitiveEngine {
376
376
 
377
377
  // Set attention state for bandwidth allowance
378
378
  // One facet per ~0.3 free capacity units, floor at 1
379
- if( event.type === 'attention.state.changed' ){
379
+ if( event.type === 'attention.state.changed'){
380
380
  const p = event.payload as { freeFraction: number }
381
381
  this._facetSupervisor.setAttentionState( p.freeFraction )
382
382
  return
@@ -437,7 +437,7 @@ export class ExecutiveEngine extends AsyncEngine implements CognitiveEngine {
437
437
  // per distinct role model; roles that share a model share the instance.
438
438
  if( !this._llmDirector && this._willId ){
439
439
  const execModel = this._models.executive ?? process.env.WILL_LLM_MODEL
440
- ?? defaultModelFor( ( this._llm?.provider ?? process.env.WILL_LLM_PROVIDER ?? 'anthropic' ) as LLMProvider )
440
+ ?? defaultModelFor( ( this._llm?.provider ?? process.env.WILL_LLM_PROVIDER ?? 'anthropic') as LLMProvider )
441
441
  this._llmDirector = this._directorFor( execModel )
442
442
  // The summarizer runs its role's model (falls back to executive) with the
443
443
  // same provider, session logging and token tracking.
@@ -457,7 +457,7 @@ export class ExecutiveEngine extends AsyncEngine implements CognitiveEngine {
457
457
  updateGatingState( this._gatingState, state, tick, result.shouldActivate, result.cleanedBuffer )
458
458
 
459
459
  if( result.shouldActivate )
460
- logger.info( `[executive] activating — reason: ${result.reason} (tick=${tick})` )
460
+ logger.info(`[executive] activating — reason: ${result.reason} (tick=${tick})`)
461
461
 
462
462
  return result.shouldActivate
463
463
  }
@@ -507,7 +507,7 @@ export class ExecutiveEngine extends AsyncEngine implements CognitiveEngine {
507
507
  semanticIntegrator: this._semanticIntegrator
508
508
  }, state )
509
509
 
510
- stream.report( 'context_assembled', {
510
+ stream.report('context_assembled', {
511
511
  workingMemoryItems: execContext.workingMemory.length,
512
512
  activeGoals: execContext.goals.length,
513
513
  totalEpisodes: this._episodicConsolidator?.getAllEpisodes().length ?? 0,
@@ -516,7 +516,7 @@ export class ExecutiveEngine extends AsyncEngine implements CognitiveEngine {
516
516
 
517
517
  // Compute modulation and uncertainty using PromptFactory
518
518
  const qualityModulation = PromptFactory.computeQualityModulation( state )
519
- stream.report( 'modulation', { qualityModulation } )
519
+ stream.report('modulation', { qualityModulation } )
520
520
 
521
521
  const epistemicUncertainty = PromptFactory.computeEpistemicUncertainty( execContext, state )
522
522
  this._lastEpistemicUncertainty = epistemicUncertainty
@@ -526,15 +526,15 @@ export class ExecutiveEngine extends AsyncEngine implements CognitiveEngine {
526
526
  // computed this tick, so the choice is free and deterministic (R2). The threshold is
527
527
  // the *effective* one (base ⊕ persona-prior): an analytical Will develops a lower
528
528
  // threshold and deliberates more readily — effort allocation as a developing trait.
529
- const deliberateThreshold = readEffectiveParams( state, 'engine-config-executive' ).deliberateThreshold ?? DELIBERATE_THRESHOLD
529
+ const deliberateThreshold = readEffectiveParams( state, 'engine-config-executive').deliberateThreshold ?? DELIBERATE_THRESHOLD
530
530
  const processSelection = selectProcess( {
531
531
  epistemicUncertainty,
532
532
  priorConfidence: this._lastExecutiveOutput?.confidence ?? 0.5,
533
- novelty: state.metrics.get( 'perception.novelty' ) ?? 0,
534
- stressLoad: state.metrics.get( 'stress.load' ) ?? 0,
533
+ novelty: state.metrics.get('perception.novelty') ?? 0,
534
+ stressLoad: state.metrics.get('stress.load') ?? 0,
535
535
  hasPendingMessage: this._messageQueue.pendingMessages.length > 0,
536
536
  }, deliberateThreshold )
537
- stream.report( 'process_selected', {
537
+ stream.report('process_selected', {
538
538
  process: processSelection.process,
539
539
  effortScore: processSelection.effortScore,
540
540
  reason: processSelection.reason,
@@ -600,7 +600,7 @@ export class ExecutiveEngine extends AsyncEngine implements CognitiveEngine {
600
600
  `candidates=${ideationCandidates?.length ?? 0} temp=${proposeTemperature.toFixed( 2 )} latency=${wallClock() - ideationStart}ms`
601
601
  )
602
602
  }
603
- stream.report( 'ideation_complete', {
603
+ stream.report('ideation_complete', {
604
604
  process: processSelection.process,
605
605
  candidateCount: ideationCandidates?.length ?? 0,
606
606
  } )
@@ -639,7 +639,7 @@ export class ExecutiveEngine extends AsyncEngine implements CognitiveEngine {
639
639
 
640
640
  // Call LLM
641
641
  if( !this._llmDirector )
642
- throw new Error( 'LLM director not initialized — willId must be set before first tick' )
642
+ throw new Error('LLM director not initialized — willId must be set before first tick')
643
643
 
644
644
  const llmStart = wallClock() // perf timing only — latency is telemetry, never replay state
645
645
  let executiveOutput: ExecutiveOutputFull
@@ -668,7 +668,7 @@ export class ExecutiveEngine extends AsyncEngine implements CognitiveEngine {
668
668
  )
669
669
 
670
670
  const responsePath = this._willId
671
- ? `./data/wills/${this._willId}/debug/response-tick-${String( state.tick ).padStart( 6, '0' )}.txt`
671
+ ? `./data/wills/${this._willId}/debug/response-tick-${String( state.tick ).padStart( 6, '0')}.txt`
672
672
  : ''
673
673
  this._sessionLogger?.write( {
674
674
  type: 'executive.response',
@@ -692,7 +692,7 @@ export class ExecutiveEngine extends AsyncEngine implements CognitiveEngine {
692
692
  }
693
693
  catch( err: unknown ){
694
694
  const msg = err instanceof Error ? err.message : String( err )
695
- logger.error( `[executive] LLM call failed: ${msg.slice( 0, 200 )}` )
695
+ logger.error(`[executive] LLM call failed: ${msg.slice( 0, 200 )}`)
696
696
 
697
697
  this._sessionLogger?.write( {
698
698
  type: 'executive.response',
@@ -725,7 +725,7 @@ export class ExecutiveEngine extends AsyncEngine implements CognitiveEngine {
725
725
  hasNarrative: !!executiveOutput.narrative
726
726
  } )
727
727
 
728
- stream.report( 'executive_complete', {
728
+ stream.report('executive_complete', {
729
729
  actionCount: executiveOutput.actions.length,
730
730
  planCount: executiveOutput.plans?.length ?? 0,
731
731
  newBeliefCount: executiveOutput.newBeliefs?.length ?? 0,
@@ -744,7 +744,7 @@ export class ExecutiveEngine extends AsyncEngine implements CognitiveEngine {
744
744
  ): StateCommands | null {
745
745
  const data = result as Record<string, unknown>
746
746
 
747
- if( step === 'context_assembled' )
747
+ if( step === 'context_assembled')
748
748
  return {
749
749
  metrics: [
750
750
  [ 'executive.phase', 0 ],
@@ -752,7 +752,7 @@ export class ExecutiveEngine extends AsyncEngine implements CognitiveEngine {
752
752
  ]
753
753
  }
754
754
 
755
- if( step === 'modulation' )
755
+ if( step === 'modulation')
756
756
  return {
757
757
  metrics: [
758
758
  [ 'executive.phase', 1 ],
@@ -760,7 +760,7 @@ export class ExecutiveEngine extends AsyncEngine implements CognitiveEngine {
760
760
  ]
761
761
  }
762
762
 
763
- if( step === 'process_selected' )
763
+ if( step === 'process_selected')
764
764
  return {
765
765
  metrics: [
766
766
  [ 'executive.process', ( data.process as string ) === 'deliberate' ? 1 : 0 ],
@@ -768,14 +768,14 @@ export class ExecutiveEngine extends AsyncEngine implements CognitiveEngine {
768
768
  ]
769
769
  }
770
770
 
771
- if( step === 'ideation_complete' )
771
+ if( step === 'ideation_complete')
772
772
  return {
773
773
  metrics: [
774
774
  [ 'executive.deliberate_candidates', ( data.candidateCount as number ) ?? 0 ]
775
775
  ]
776
776
  }
777
777
 
778
- if( step === 'executive_complete' )
778
+ if( step === 'executive_complete')
779
779
  return {
780
780
  metrics: [
781
781
  [ 'executive.phase', 2 ],
@@ -1044,7 +1044,7 @@ export class ExecutiveEngine extends AsyncEngine implements CognitiveEngine {
1044
1044
  private _restoreSummarizer( state: ReadonlySimulationState ): void {
1045
1045
  if( !this._summarizer ) return
1046
1046
 
1047
- const entity = state.entities.get( 'executive-rolling-summary' )
1047
+ const entity = state.entities.get('executive-rolling-summary')
1048
1048
  if( !entity ) return
1049
1049
 
1050
1050
  const m = entity.metadata ?? {}
@@ -1054,6 +1054,6 @@ export class ExecutiveEngine extends AsyncEngine implements CognitiveEngine {
1054
1054
 
1055
1055
  this._summarizer.restore( summary, buffer, callCount )
1056
1056
  if( summary )
1057
- logger.info( `[executive] summarizer restored (${summary.length} chars, ${callCount} prior calls)` )
1057
+ logger.info(`[executive] summarizer restored (${summary.length} chars, ${callCount} prior calls)`)
1058
1058
  }
1059
1059
  }
@@ -140,12 +140,12 @@ export class FacetSupervisor {
140
140
  // vanish silently. The TTL measures *quiet* facets only.
141
141
  if( facet.busy ) continue
142
142
  if( tick - facet.lastActiveTick > this._idleTtlTicks )
143
- this._reap( id, 'idle' )
143
+ this._reap( id, 'idle')
144
144
  }
145
145
  }
146
146
 
147
147
  /** Destroy + deregister a facet and notify its owner. Shared by the reaper + LRU eviction. */
148
- private _reap( facetId: string, reason: 'idle' | 'lru' ): void {
148
+ private _reap( facetId: string, reason: 'idle' | 'lru'): void {
149
149
  const facet = this._facets.get( facetId )
150
150
  if( !facet ) return
151
151
 
@@ -154,7 +154,7 @@ export class FacetSupervisor {
154
154
  const onReaped = this._onReaped.get( facetId )
155
155
  this._onReaped.delete( facetId )
156
156
 
157
- logger.info( `[executive] facet ${facetId} reaped (${reason}); remaining: ${this._facets.size}` )
157
+ logger.info(`[executive] facet ${facetId} reaped (${reason}); remaining: ${this._facets.size}`)
158
158
  this._sessionLogger?.write({
159
159
  type: 'executive.facet.destroy',
160
160
  tick: this._lastStateRef?.tick as unknown as number ?? 0,
@@ -165,7 +165,7 @@ export class FacetSupervisor {
165
165
 
166
166
  // Notify the owner (e.g. AuditionEngine) so it drops its handle + session state.
167
167
  try { onReaped?.() }
168
- catch( err ){ logger.error( `[executive] facet ${facetId} onReaped error:`, err ) }
168
+ catch( err ){ logger.error(`[executive] facet ${facetId} onReaped error:`, err ) }
169
169
  }
170
170
 
171
171
  private _leastRecentlyActive(): string | null {
@@ -198,13 +198,13 @@ export class FacetSupervisor {
198
198
  */
199
199
  spawn( deps: FacetSpawnDeps ): SpawnResult {
200
200
  if( !deps.bus )
201
- throw new Error( 'Cannot spawn facet — CognitiveBus not attached. Was addEngine() called?' )
201
+ throw new Error('Cannot spawn facet — CognitiveBus not attached. Was addEngine() called?')
202
202
 
203
203
  if( !deps.llmDirector )
204
- throw new Error( 'Cannot spawn facet — LLM director not initialized. Set willId first.' )
204
+ throw new Error('Cannot spawn facet — LLM director not initialized. Set willId first.')
205
205
 
206
206
  if( !deps.stateRef )
207
- throw new Error( 'Cannot spawn facet — no state snapshot available. Wait for first tick.' )
207
+ throw new Error('Cannot spawn facet — no state snapshot available. Wait for first tick.')
208
208
 
209
209
  // Authoritative current state ref from the engine — keep it so a later
210
210
  // destroy() logs the same tick the engine would.
@@ -214,15 +214,15 @@ export class FacetSupervisor {
214
214
  const maxFacets = Math.max( 1, Math.floor( this._attentionFreeCapacity / 0.3 ) )
215
215
  if( this._facets.size >= maxFacets ){
216
216
  if( !this._evictLruOnPressure ){
217
- logger.info( `[executive] attention full (${this._facets.size}/${maxFacets} facets) ` )
217
+ logger.info(`[executive] attention full (${this._facets.size}/${maxFacets} facets) `)
218
218
  return { attention: 'full' }
219
219
  }
220
220
  // Budget full but a new conversation arrived — evict the least-recently-active
221
221
  // facet so a fresh, live conversation preempts a stale one (no silent drop).
222
222
  const lru = this._leastRecentlyActive()
223
223
  if( !lru ) return { attention: 'full' } // nothing evictable (shouldn't happen)
224
- logger.info( `[executive] attention full (${this._facets.size}/${maxFacets}) — evicting LRU facet ${lru}` )
225
- this._reap( lru, 'lru' )
224
+ logger.info(`[executive] attention full (${this._facets.size}/${maxFacets}) — evicting LRU facet ${lru}`)
225
+ this._reap( lru, 'lru')
226
226
  }
227
227
 
228
228
  this._facetCounter++
@@ -248,7 +248,7 @@ export class FacetSupervisor {
248
248
 
249
249
  this._facets.set( facetId, facet )
250
250
 
251
- logger.info( `[executive] spawned facet → ${facetId} (total facets: ${this._facets.size})` )
251
+ logger.info(`[executive] spawned facet → ${facetId} (total facets: ${this._facets.size})`)
252
252
 
253
253
  this._sessionLogger?.write({
254
254
  type: 'executive.facet.spawn',
@@ -271,7 +271,7 @@ export class FacetSupervisor {
271
271
  facet.destroy()
272
272
  this._facets.delete( facetId )
273
273
  this._onReaped.delete( facetId ) // explicit close — owner already knows; don't fire onReaped
274
- logger.info( `[executive] facet ${facetId} destroyed (remaining: ${this._facets.size})` )
274
+ logger.info(`[executive] facet ${facetId} destroyed (remaining: ${this._facets.size})`)
275
275
  this._sessionLogger?.write({
276
276
  type: 'executive.facet.destroy',
277
277
  tick: this._lastStateRef?.tick as unknown as number ?? 0,