@mindot/will 0.9.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 (110) hide show
  1. package/README.md +15 -11
  2. package/dist/index.d.ts +188 -141
  3. package/dist/index.js +16660 -15206
  4. package/dist/index.js.map +1 -1
  5. package/dist/{channels → surface/channels}/discord.d.ts +50 -3
  6. package/dist/{channels → surface/channels}/discord.js +102 -7
  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 +7 -4
  10. package/dist/surface/channels/whatsapp.js.map +1 -0
  11. package/dist/{cli.js → surface/cli.js} +4406 -2904
  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-DbDj_TEH.d.ts → will-evj9_vrd.d.ts} +5699 -4854
  17. package/package.json +11 -12
  18. package/src/cognition/agency/consequence.ts +237 -3
  19. package/src/cognition/agency/conversation.aim.ts +32 -0
  20. package/src/cognition/agency/engines/action.selector.ts +59 -3
  21. package/src/cognition/agency/engines/affordance.synthesizer.ts +114 -10
  22. package/src/cognition/agency/engines/deliberation.engine.ts +76 -3
  23. package/src/cognition/agency/engines/motor.schema.executor.ts +362 -27
  24. package/src/cognition/agency/engines/reafference.engine.ts +43 -4
  25. package/src/cognition/agency/execution.primitives.ts +17 -4
  26. package/src/cognition/agency/reconcile.learning.ts +5 -4
  27. package/src/cognition/agency/schemas/innate.ts +96 -1
  28. package/src/cognition/agency/schemas/repertoire.ts +19 -1
  29. package/src/cognition/agency/selection.scoring.ts +16 -0
  30. package/src/cognition/agency/settlement.ts +203 -0
  31. package/src/cognition/agency/types.ts +38 -1
  32. package/src/cognition/config.mirror.entities.ts +0 -1
  33. package/src/cognition/event.schemas.ts +0 -8
  34. package/src/cognition/faculties/affective.blender.ts +21 -4
  35. package/src/cognition/faculties/circadian.oscillator.ts +36 -7
  36. package/src/cognition/faculties/executive.engine/action.record.ts +129 -0
  37. package/src/cognition/faculties/executive.engine/context.ts +41 -35
  38. package/src/cognition/faculties/executive.engine/engine.ts +270 -113
  39. package/src/cognition/faculties/executive.engine/escalation.buffer.ts +126 -59
  40. package/src/cognition/faculties/executive.engine/facet.supervisor.ts +10 -0
  41. package/src/cognition/faculties/executive.engine/parser.ts +100 -38
  42. package/src/cognition/faculties/executive.engine/prompt.factory.ts +168 -23
  43. package/src/cognition/faculties/executive.engine/types.ts +18 -15
  44. package/src/cognition/faculties/exteroception.ts +99 -98
  45. package/src/cognition/faculties/goal.manager.ts +50 -2
  46. package/src/cognition/faculties/known.entity.tracker.ts +22 -3
  47. package/src/cognition/faculties/planning.engine/engine.ts +4 -4
  48. package/src/cognition/faculties/planning.engine/plan.frontier.ts +1 -1
  49. package/src/cognition/faculties/semantic.engine/integrator.ts +1 -1
  50. package/src/cognition/faculties/working.memory.ts +6 -1
  51. package/src/cognition/instruction.handler.ts +1 -1
  52. package/src/cognition/memory/vector.embedder.ts +1 -3
  53. package/src/cognition/percept.entity.ts +122 -0
  54. package/src/cognition/sense.boundary.ts +176 -0
  55. package/src/cognition/senses/audition.engine/engine.ts +97 -16
  56. package/src/cognition/senses/base.sense.engine.ts +104 -6
  57. package/src/cognition/senses/index.ts +71 -13
  58. package/src/cognition/senses/provenance.ts +128 -0
  59. package/src/cognition/senses/somatosensation.engine.ts +117 -9
  60. package/src/cognition/social.identity.ts +23 -0
  61. package/src/cognition/utilities/token.tracker.ts +36 -5
  62. package/src/core/orchestrator.ts +13 -0
  63. package/src/index.ts +39 -5
  64. package/src/llm/gate.ts +48 -0
  65. package/src/llm/index.ts +102 -25
  66. package/src/llm/wire.contracts.ts +38 -0
  67. package/src/pma/index.ts +1 -1
  68. package/src/stem/index.ts +92 -21
  69. package/src/stem/mind.ts +26 -2
  70. package/src/stem/policy/arbiter.ts +10 -0
  71. package/src/stem/profiles/built-in.ts +7 -0
  72. package/src/{profiles → stem/profiles}/companion.ts +1 -1
  73. package/src/{profiles → stem/profiles}/company-brain.ts +1 -1
  74. package/src/{profiles → stem/profiles}/customer-service.ts +1 -1
  75. package/src/{profiles → stem/profiles}/game-npc.ts +1 -1
  76. package/src/{profiles → stem/profiles}/index.ts +1 -1
  77. package/src/{profiles → stem/profiles}/smart-home.ts +1 -1
  78. package/src/stem/tracts/effector/escalation.lifecycle.ts +239 -0
  79. package/src/stem/tracts/effector/policy.enforcement.ts +261 -0
  80. package/src/stem/tracts/effector/types.ts +110 -0
  81. package/src/stem/tracts/effector.controller.ts +112 -401
  82. package/src/stem/tracts/outbox.controller.ts +30 -17
  83. package/src/stem/tracts/sensory.controller.ts +6 -6
  84. package/src/stem/tracts/session.logger.ts +6 -1
  85. package/src/stem/tracts/transport/types.ts +20 -1
  86. package/src/stem/tracts/transport.controller.ts +33 -9
  87. package/src/{channels → surface/channels}/discord.ts +224 -7
  88. package/src/{channels → surface/channels}/roster.ts +1 -1
  89. package/src/{channels → surface/channels}/types.ts +1 -1
  90. package/src/{channels → surface/channels}/whatsapp.ts +9 -6
  91. package/src/{cli.ts → surface/cli.ts} +6 -6
  92. package/src/{host → surface/host}/boot.ts +3 -3
  93. package/src/{host → surface/host}/utterances.ts +2 -2
  94. package/src/{mcp → surface/mcp}/effectors.ts +19 -6
  95. package/src/{mcp → surface/mcp}/server.ts +19 -5
  96. package/src/{sdk → surface/sdk}/will.ts +156 -28
  97. package/src/{serve → surface/serve}/server.ts +11 -4
  98. package/src/types.ts +24 -3
  99. package/dist/channels/discord.js.map +0 -1
  100. package/dist/channels/whatsapp.js.map +0 -1
  101. package/dist/cli.js.map +0 -1
  102. package/dist/mcp/effectors.js.map +0 -1
  103. package/src/extensions/livestream.ext.ts +0 -570
  104. package/src/extensions/time.ext.ts +0 -339
  105. package/src/profiles/built-in.ts +0 -7
  106. package/src/runners/coherence.runner.ts +0 -49
  107. package/src/runners/outreach.runner.ts +0 -155
  108. package/src/runners/social.runner.ts +0 -179
  109. package/src/runners/thin-shim.runner.ts +0 -205
  110. /package/dist/{cli.d.ts → surface/cli.d.ts} +0 -0
@@ -35,9 +35,12 @@ import type { CognitiveEventSchema } from '#cognition/schema.registry'
35
35
  import type { Affordance, AffordanceSource, MotorSchema, LearnedSkill, SchemaPrecondition } from '#agency/types'
36
36
  import type { SchemaRepertoire } from '#agency/schemas/repertoire'
37
37
  import { INNATE_SCHEMAS } from '#agency/schemas/innate'
38
+ import { CURIOUS_RESOLVED } from '#faculties/known.entity.tracker'
38
39
  import { collectGoalTargets } from '#agency/selection.scoring'
39
40
  import { readEffectiveParams } from '#cognition/persona.prior'
40
- import { liveConsequences, enactionFootprint, spokenAtByEntity, CONSEQUENCE_TTL_TICKS, type ConsequenceDescriptor } from '#agency/consequence'
41
+ import { liveConsequences, enactionFootprint, spokenAtByEntity, enactedAtBySchemaTarget, CONSEQUENCE_TTL_TICKS, type ConsequenceDescriptor } from '#agency/consequence'
42
+ import { readAliases, canonicalOf } from '#cognition/social.identity'
43
+ import { liveSettlements, settlementForce, type SettlementDescriptor } from '#agency/settlement'
41
44
 
42
45
  /** Default field width for non-innate affordances when no attention metric exists. */
43
46
  const DEFAULT_ATTENTION_CAP = 5
@@ -68,12 +71,31 @@ export class AffordanceSynthesizer implements CognitiveEngine {
68
71
  * because `_build` runs per candidate and reading them is a full-entity scan.
69
72
  */
70
73
  private _inFlight: readonly ConsequenceDescriptor[] = []
74
+ /** Durable "when did I last do this TO them" — the entity-bound peer of
75
+ * `_spokenAt`, collected once per tick for the same reason `_inFlight` is. */
76
+ private _enactedAt: ReadonlyMap<string, number> = new Map()
71
77
 
72
78
  /** Ticks an act stays satiating (engine-config-action-selector.repeatWindowTicks). */
73
79
  private _satiationWindow: number = CONSEQUENCE_TTL_TICKS
80
+ /** Verdicts System 2 has already reached and that have not yet aged out.
81
+ * Collected once per tick for the same reason `_inFlight` is — `_build` runs
82
+ * per candidate and this is a full-entity scan. */
83
+ private _settled: SettlementDescriptor[] = []
74
84
 
75
85
  /** Tick of the last thing said to each entity — outlives the descriptor sweep. */
76
86
  private _spokenAt: ReadonlyMap<string, number> = new Map()
87
+ private _spokeAnywhereAt: number | undefined = undefined
88
+ /**
89
+ * alias id → anchor id, read once per tick.
90
+ *
91
+ * Every surface below is keyed by WHO an act was aimed at, and the mind meets
92
+ * one person under more than one id: a reply is addressed to the transport id
93
+ * the percept arrived with (`discord:1019…`), a self-initiated message to the
94
+ * anchor the executive resolved (`ke:…`). `readSpokenTurns` resolved that for
95
+ * the PROMPT from the start; nothing resolved it for the WEIGHTS, so having
96
+ * just answered someone did not damp reaching out to them a cycle later.
97
+ */
98
+ private _canon: ( id: string ) => string = id => id
77
99
  private _bus: CognitiveBus | null = null
78
100
  private _defaultCap: number
79
101
  private _lastFieldSize = 0
@@ -131,7 +153,21 @@ export class AffordanceSynthesizer implements CognitiveEngine {
131
153
  // `_build` runs for every candidate and this is a full-entity scan. Each
132
154
  // candidate whose (schema, target) matches one of these carries a decaying
133
155
  // `justEnacted`, so having just done a thing damps doing it again.
134
- this._inFlight = liveConsequences( state.entities, tick )
156
+ // One scan, then every target-keyed surface below shares its id space. They
157
+ // must agree with each other AND with the lookup at the call site: canonical
158
+ // keys read with a raw target damps nothing, and a raw key read with a
159
+ // canonical target breaks the damping that already worked.
160
+ const aliases = readAliases( state.entities )
161
+ this._canon = ( id: string ) => canonicalOf( aliases, id )
162
+
163
+ this._inFlight = liveConsequences( state.entities, tick, this._canon )
164
+ // Durable per-(schema, target) enaction. Descriptors alone expire at the ECHO
165
+ // window, so without this the back half of the satiation window damped
166
+ // nothing for any act with an object that is not speech.
167
+ this._enactedAt = enactedAtBySchemaTarget( state.entities, this._canon )
168
+ // What the mind has already decided. Read here so a verdict reaches the
169
+ // competition as a force in the field rather than a fact about one intent.
170
+ this._settled = liveSettlements( state.entities, tick, this._canon )
135
171
  // How long this mind sits with something it has already done before doing it
136
172
  // again — the tenant's, not the container's. Falls back to the echo TTL only
137
173
  // when unseeded, so a bare harness behaves as before.
@@ -140,7 +176,12 @@ export class AffordanceSynthesizer implements CognitiveEngine {
140
176
  // Durable "when did I last speak to them". Descriptors alone cannot carry
141
177
  // satiation — the executor deletes them at their echo TTL, so any window
142
178
  // longer than that was a no-op.
143
- this._spokenAt = spokenAtByEntity( state.entities )
179
+ this._spokenAt = spokenAtByEntity( state.entities, this._canon )
180
+ // When this mind last spoke to ANYONE — the satiation arm that is not about
181
+ // the listener. Computed once per tick rather than per candidate.
182
+ let last = -Infinity
183
+ for( const t of this._spokenAt.values() ) if( t > last ) last = t
184
+ this._spokeAnywhereAt = last > -Infinity ? last : undefined
144
185
 
145
186
  const set: EntityInput[] = []
146
187
  const del: string[] = []
@@ -191,16 +232,18 @@ export class AffordanceSynthesizer implements CognitiveEngine {
191
232
  const personSchemas = schemas.filter( s => s.binds === 'entity')
192
233
  const objectSchemas = schemas.filter( s => s.binds === 'object')
193
234
 
194
- if( personSchemas.length > 0 || objectSchemas.length > 0 )
195
- for( const [ id, e ] of state.entities ){
235
+ // Not gated on there BEING a target-bound schema: `inspect` is offered from
236
+ // this same loop and belongs to the innate floor, so a mind with no `binds`
237
+ // schemas at all — which is every mind until a host declares one — must still
238
+ // reach it. Gating the loop skipped a room entirely, because the innate floor
239
+ // has no `binds: 'object'` schema for a thing to match.
240
+ for( const [ id, e ] of state.entities ){
196
241
  if( e.type !== 'known-entity') continue
197
242
 
198
243
  const m = e.metadata
199
244
  const kind = str( m?.['kind'] )
200
245
  const applicable = kind === 'sentient' ? personSchemas : kind === 'thing' ? objectSchemas : null
201
246
 
202
- if( !applicable || applicable.length === 0 ) continue
203
-
204
247
  const keid = str( m?.['keid'] ) ?? id
205
248
  const fam = num( m?.['familiarity'], 0 )
206
249
  const val = num( m?.['valence'], 0 )
@@ -208,7 +251,7 @@ export class AffordanceSynthesizer implements CognitiveEngine {
208
251
  const salience = fam * 0.6 + Math.max( 0, val ) * 0.3 + res * 0.1 + ( goalTargets.get( keid ) ?? 0 )
209
252
  const name = str( m?.['name'] ) ?? keid
210
253
 
211
- for( const schema of applicable )
254
+ for( const schema of applicable ?? [] )
212
255
  candidates.push({
213
256
  salience,
214
257
  affordance: this._build( schema, tick, state, valence, energyLow, skills, {
@@ -217,6 +260,38 @@ export class AffordanceSynthesizer implements CognitiveEngine {
217
260
  parameters: { targetEntityName: name },
218
261
  } ),
219
262
  })
263
+
264
+ // ── looking at something I cannot place ──────────────────
265
+ //
266
+ // The wanting and the doing referenced different things. Curiosity is
267
+ // per-REFERENT — `drive.curiosity_resolve` rises with
268
+ // `familiarity × (1 − resolutionConfidence)`, and GoalManager turns it
269
+ // into a real goal that completes when that referent resolves. But the
270
+ // only `inspect` on offer bound to PERCEPTS, so a mind could want to know
271
+ // what a room was, hold a goal about it, and have no act that addressed
272
+ // it. The pull existed with nowhere to go.
273
+ //
274
+ // Offered here at the strength of the not-knowing itself, so the thing it
275
+ // most wants to place is the thing it is most drawn to look at — and the
276
+ // affordance appears BECAUSE something is unresolved rather than standing
277
+ // permanently on offer. A referent it can already place raises no
278
+ // candidate at all: there is nothing to find out.
279
+ //
280
+ // Alongside the percept-bound offering, not instead of it. Examining what
281
+ // is in front of you and looking up what you cannot place are both real,
282
+ // and they are not the same act.
283
+ if( perceptSchema && res < CURIOUS_RESOLVED ){
284
+ const wonder = fam * ( 1 - res )
285
+ if( wonder > 0 )
286
+ candidates.push({
287
+ salience: wonder + ( goalTargets.get( keid ) ?? 0 ),
288
+ affordance: this._build( perceptSchema, tick, state, valence, energyLow, skills, {
289
+ evokedBy: id,
290
+ targetEntityId: keid,
291
+ parameters: { focus: name, targetEntityName: name },
292
+ } ),
293
+ })
294
+ }
220
295
  }
221
296
 
222
297
  // ── ideomotor candidates: the executive's imagined actions, pre-activated ──
@@ -255,7 +330,7 @@ export class AffordanceSynthesizer implements CognitiveEngine {
255
330
  // action its current frontier needs. The PlanningEngine writes one `plan.prior`
256
331
  // per ready frontier step; each enters the field as a HIGH-salience candidate
257
332
  // (the frontier is willed) carrying a `planBias` the scorer weighs and the
258
- // planId/stepId provenance that flows through to action.outcome so the plan
333
+ // planId/stepId link that flows through to action.outcome so the plan
259
334
  // advances when the field actually enacts it. Like ideomotor, it never bypasses
260
335
  // the selector — if a more pressing affordance wins, the plan simply re-projects
261
336
  // next tick. The suggested schema must resolve in the repertoire; if it does not,
@@ -367,12 +442,31 @@ export class AffordanceSynthesizer implements CognitiveEngine {
367
442
  // Satiation only applies to acts aimed at someone the mind SPEAKS to — the
368
443
  // `conversation.sent` half is keyed by person, so it must not damp, say,
369
444
  // inspecting them.
445
+ //
446
+ // For an act with NO OBJECT the footprint is the act itself: there is no
447
+ // target to key on, and "I have just done this" is the whole of the fact.
448
+ // The innate floor is entirely objectless, so without this it could not
449
+ // satiate at all and whichever stance won once won harder each tick after.
370
450
  const speaks = schema.tags?.includes('communication') ?? false
451
+ // The lookup half. Only the QUESTION "have I just done this to them" is asked
452
+ // in canonical form — the affordance keeps the id it was built with, because
453
+ // that is the id the act will be delivered against.
454
+ const asked = ctx.targetEntityId ? this._canon( ctx.targetEntityId ) : undefined
371
455
  const justEnacted = enactionFootprint(
372
- this._inFlight, schema.id, ctx.targetEntityId, tick, this._satiationWindow,
456
+ this._inFlight, schema.id, asked, tick, this._satiationWindow,
373
457
  speaks ? this._spokenAt : undefined,
458
+ skill?.lastEnactedTick,
459
+ speaks ? this._spokeAnywhereAt : undefined,
460
+ // Not gated on `speaks`: this is exactly the arm speech does NOT need
461
+ // (it has `spokenAt`) and every other entity-bound act was missing.
462
+ this._enactedAt,
374
463
  )
375
464
 
465
+ // The mirror of satiation: having thought this through holds the choice for
466
+ // a while, and fades. Keyed exactly as `justEnacted` is, so an objectless
467
+ // verdict cannot leak onto an act that has an object.
468
+ const settled = settlementForce( this._settled, schema.id, asked, tick )
469
+
376
470
  const key = ctx.targetEntityId ?? ctx.evokedBy ?? schema.id
377
471
  const source = ctx.source ?? schema.source
378
472
  // A non-default-source candidate (ideomotor) gets a distinct id so it can coexist
@@ -396,6 +490,7 @@ export class AffordanceSynthesizer implements CognitiveEngine {
396
490
  ...( availability < 1 ? { availability } : {} ),
397
491
  ...( socialPrior !== 0 ? { socialPrior } : {} ),
398
492
  ...( justEnacted > 0 ? { justEnacted } : {} ),
493
+ ...( settled > 0 ? { settled } : {} ),
399
494
  planBias: ctx.planBias,
400
495
  willBias: ctx.willBias,
401
496
  planId: ctx.planId,
@@ -423,6 +518,15 @@ export class AffordanceSynthesizer implements CognitiveEngine {
423
518
  description: a.description,
424
519
  ...( a.availability !== undefined ? { availability: a.availability } : {} ),
425
520
  ...( a.socialPrior !== undefined ? { socialPrior: a.socialPrior } : {} ),
521
+ // The act's own footprint. Omitted when 0 so a mind that has done nothing
522
+ // twice writes a byte-identical field — but WRITTEN when it is not, which
523
+ // it never was: this is the state hop between synthesis and the
524
+ // competition, and `justEnacted` did not cross it.
525
+ ...( a.justEnacted !== undefined ? { justEnacted: a.justEnacted } : {} ),
526
+ // The verdict's standing weight — same hop, same rule. A field the
527
+ // synthesizer computes and the entity does not carry is a field the
528
+ // competition never sees, which is how `justEnacted` stayed dormant.
529
+ ...( a.settled !== undefined ? { settled: a.settled } : {} ),
426
530
  planBias: a.planBias,
427
531
  willBias: a.willBias,
428
532
  planId: a.planId,
@@ -31,6 +31,8 @@ import type { CognitiveBus } from '#cognition/bus'
31
31
  import type { CognitiveEngine, EngineResult } from '#cognition/types'
32
32
  import type { CognitiveEventSchema } from '#cognition/schema.registry'
33
33
  import { revokedIntentIds, revocationId } from '#agency/revocation'
34
+ import { settlementEntity, expiredSettlementIds, SETTLEMENT_TTL_TICKS } from '#agency/settlement'
35
+ import { nameOf, isReferentId } from '#cognition/social.identity'
34
36
 
35
37
  // ── Minimal structural view of the executive's facet machinery ───────────────
36
38
  // Kept structural (not an import of the executive engine) so the agency module
@@ -98,7 +100,10 @@ export class DeliberationEngine implements CognitiveEngine {
98
100
  // to let go of it — and the tombstone with it. We never deliberate a
99
101
  // revoked intent.
100
102
  const revoked = revokedIntentIds( state.entities, tick )
101
- const del: string[] = []
103
+ // Aged-out verdicts go with them. Nothing else owns settlements, and a
104
+ // question whose settlement has expired must be genuinely open again — not
105
+ // merely inert-but-present, which would leave the state growing forever.
106
+ const del: string[] = expiredSettlementIds( state.entities, tick )
102
107
 
103
108
  // One deliberation per tick (the serial bottleneck).
104
109
  let target: { id: string; meta: Record<string, unknown> } | null = null
@@ -136,7 +141,15 @@ export class DeliberationEngine implements CognitiveEngine {
136
141
 
137
142
  return {
138
143
  commands: {
139
- set: [ this._commit( id, meta, chosen, candidates, 'facet') ],
144
+ set: [
145
+ this._commit( id, meta, chosen, candidates, 'facet'),
146
+ // The verdict's trace in the field it was called in to resolve.
147
+ // Written ONLY here, on the path where System 2 actually thought —
148
+ // the no-executive path below confirms the substrate's winner without
149
+ // reaching a conclusion, and a mind should not be held to a verdict it
150
+ // never formed.
151
+ this._settle( chosen, candidates, tick ),
152
+ ],
140
153
  ...( del.length > 0 ? { delete: del } : {} ),
141
154
  metrics: [ [ 'agency.deliberation.count', 1 ] ],
142
155
  },
@@ -186,6 +199,25 @@ export class DeliberationEngine implements CognitiveEngine {
186
199
  }
187
200
  }
188
201
 
202
+ /**
203
+ * Record that this contest was weighed and settled.
204
+ *
205
+ * Keyed on what WON, not on the rival set, so a slightly differently-framed
206
+ * contest still meets a verdict the mind has already reached — the rivals ride
207
+ * along as the introspectable reason rather than as a matching key.
208
+ */
209
+ private _settle( chosen: string, candidates: Candidate[], tick: Tick ): EntityInput {
210
+ const cand = candidates.find( c => c.schema === chosen )
211
+ const over = candidates.filter( c => c.schema !== chosen ).map( c => c.schema )
212
+ return settlementEntity({
213
+ schema: chosen,
214
+ targetEntityId: cand?.targetEntityId,
215
+ ...( over.length > 0 ? { over } : {} ),
216
+ tick,
217
+ expiresAt: tick + SETTLEMENT_TTL_TICKS,
218
+ })
219
+ }
220
+
189
221
  /** Write the deliberating intent back as 'selected' with the chosen action. */
190
222
  private _commit(
191
223
  id: string,
@@ -227,7 +259,35 @@ export class DeliberationEngine implements CognitiveEngine {
227
259
  else
228
260
  lines.push('My automatic action-selection was uncertain. Candidate actions:')
229
261
  candidates.forEach( ( c, i ) => {
230
- const to = c.targetEntityId ? ` toward ${ c.targetEntityId }` : ''
262
+ // What the target IS, never the id it is filed under.
263
+ //
264
+ // This printed `c.targetEntityId` raw, so a mind deliberating was offered
265
+ // "inspect toward agency-intent-30" and "inspect toward
266
+ // affordance-1-orient-orient" — engine bookkeeping ids, and by the time a
267
+ // facet reasons off-tick the affordance entities are already swept. Live,
268
+ // she said so herself: "the content of all three is opaque — I don't know
269
+ // what agency-intent-30 actually is", and chose at 0.3 confidence anyway
270
+ // because the instructions forbid inventing an action outside the list.
271
+ //
272
+ // The prompt factory already holds this line for "## People I Know"
273
+ // ("never leak the raw keid"); the deliberation focus is the one place that
274
+ // did not. Resolved through the same dossier lookup, so a `reach-out toward
275
+ // ke:1sqlkux` now reads as the person's name.
276
+ //
277
+ // Unresolvable ⇒ the clause is DROPPED rather than filled with an id. An
278
+ // option the mind cannot identify should look like what it is — a bare act
279
+ // — instead of borrowing authority from a number it cannot read.
280
+ const to = ( () => {
281
+ const id = c.targetEntityId
282
+ if( !id ) return ''
283
+ const named = nameOf( state.entities as never, id )
284
+ if( named ) return ` toward ${ named }`
285
+ // Unnamed: show it only if it means something to the MIND. A host-supplied
286
+ // target ("ada") does; an opaque anchor or a piece of engine bookkeeping
287
+ // does not, and printing those is what produced "inspect toward
288
+ // agency-intent-30" as a thing to choose.
289
+ return opaqueToTheMind( id ) ? '' : ` toward ${ id }`
290
+ } )()
231
291
  // The ability's meaning, so the facet weighs what each option IS FOR rather
232
292
  // than choosing among bare labels ("give" vs "attack" is a real difference).
233
293
  const what = c.description ? ` — ${ c.description }` : ''
@@ -258,3 +318,16 @@ function extractChosen( decision: unknown, candidates: Candidate[] ): string | u
258
318
  function str( v: unknown ): string | undefined {
259
319
  return typeof v === 'string' ? v : undefined
260
320
  }
321
+
322
+ /**
323
+ * Ids the mind cannot read anything off.
324
+ *
325
+ * A `ke:` anchor is opaque BY DESIGN — 0.9.0 made identity deliberately
326
+ * meaningless as a string — and the rest are the engine's own bookkeeping
327
+ * entities, which exist for one tick and say nothing about the world. Neither
328
+ * belongs in a choice a mind has to make; a host-supplied target does.
329
+ */
330
+ function opaqueToTheMind( id: string ): boolean {
331
+ return isReferentId( id )
332
+ || /^(affordance|agency-intent|agency-outcome|ideomotor|facet|percept)[-:]/.test( id )
333
+ }