@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.
- package/README.md +15 -11
- package/dist/index.d.ts +188 -141
- package/dist/index.js +6985 -3337
- package/dist/index.js.map +1 -1
- package/dist/surface/channels/discord.d.ts +177 -0
- package/dist/surface/channels/discord.js +394 -0
- package/dist/surface/channels/discord.js.map +1 -0
- package/dist/{channels → surface/channels}/whatsapp.d.ts +2 -2
- package/dist/{channels → surface/channels}/whatsapp.js +11 -5
- package/dist/surface/channels/whatsapp.js.map +1 -0
- package/dist/{cli.js → surface/cli.js} +5382 -1573
- package/dist/surface/cli.js.map +1 -0
- package/dist/{mcp → surface/mcp}/effectors.d.ts +1 -1
- package/dist/{mcp → surface/mcp}/effectors.js +10 -4
- package/dist/surface/mcp/effectors.js.map +1 -0
- package/dist/{will-cS6k4uiJ.d.ts → will-evj9_vrd.d.ts} +6658 -5078
- package/package.json +11 -12
- package/src/cognition/agency/consequence.ts +356 -1
- package/src/cognition/agency/conversation.aim.ts +292 -0
- package/src/cognition/agency/engines/action.selector.ts +142 -5
- package/src/cognition/agency/engines/affordance.synthesizer.ts +200 -7
- package/src/cognition/agency/engines/deliberation.engine.ts +76 -3
- package/src/cognition/agency/engines/motor.schema.executor.ts +509 -32
- package/src/cognition/agency/engines/reafference.engine.ts +160 -4
- package/src/cognition/agency/execution.primitives.ts +17 -4
- package/src/cognition/agency/proactive.communicator.ts +19 -3
- package/src/cognition/agency/reconcile.learning.ts +5 -4
- package/src/cognition/agency/restart.ts +66 -0
- package/src/cognition/agency/schemas/innate.ts +96 -1
- package/src/cognition/agency/schemas/repertoire.ts +19 -1
- package/src/cognition/agency/selection.scoring.ts +49 -0
- package/src/cognition/agency/settlement.ts +203 -0
- package/src/cognition/agency/types.ts +73 -1
- package/src/cognition/cache/composition.ts +232 -0
- package/src/cognition/cache/deliberation.cache.ts +219 -0
- package/src/cognition/cache/fingerprint.ts +120 -0
- package/src/cognition/cache/types.ts +105 -0
- package/src/cognition/config.mirror.entities.ts +108 -1
- package/src/cognition/event.schemas.ts +22 -8
- package/src/cognition/faculties/affective.blender.ts +21 -4
- package/src/cognition/faculties/autobiographical.narrator.ts +5 -10
- package/src/cognition/faculties/circadian.oscillator.ts +36 -7
- package/src/cognition/faculties/episodic.consolidator.ts +59 -3
- package/src/cognition/faculties/executive.engine/action.record.ts +129 -0
- package/src/cognition/faculties/executive.engine/commands.ts +189 -14
- package/src/cognition/faculties/executive.engine/context.ts +106 -46
- package/src/cognition/faculties/executive.engine/deliberate.reasoning.ts +1 -1
- package/src/cognition/faculties/executive.engine/engine.ts +714 -136
- package/src/cognition/faculties/executive.engine/escalation.buffer.ts +230 -45
- package/src/cognition/faculties/executive.engine/facet.supervisor.ts +320 -65
- package/src/cognition/faculties/executive.engine/facet.ts +81 -26
- package/src/cognition/faculties/executive.engine/gating.ts +14 -14
- package/src/cognition/faculties/executive.engine/parser.ts +120 -38
- package/src/cognition/faculties/executive.engine/prompt.factory.ts +331 -38
- package/src/cognition/faculties/executive.engine/types.ts +84 -12
- package/src/cognition/faculties/exteroception.ts +99 -98
- package/src/cognition/faculties/goal.manager.ts +144 -16
- package/src/cognition/faculties/known.entity.tracker.ts +287 -29
- package/src/cognition/faculties/moral.evaluator.ts +8 -3
- package/src/cognition/faculties/persona.consolidator.ts +141 -0
- package/src/cognition/faculties/planning.engine/engine.ts +4 -4
- package/src/cognition/faculties/planning.engine/plan.frontier.ts +1 -1
- package/src/cognition/faculties/reputation.tracker.ts +66 -2
- package/src/cognition/faculties/self.model.updater.ts +19 -12
- package/src/cognition/faculties/semantic.engine/integrator.ts +1 -1
- package/src/cognition/faculties/social.perception.ts +47 -3
- package/src/cognition/faculties/threat.evaluator.ts +7 -0
- package/src/cognition/faculties/working.memory.ts +16 -21
- package/src/cognition/identity.entity.ts +205 -0
- package/src/cognition/index.ts +7 -0
- package/src/cognition/instruction.handler.ts +1 -1
- package/src/cognition/memory/vector.adapter.ts +12 -3
- package/src/cognition/memory/vector.embedder.ts +45 -4
- package/src/cognition/percept.entity.ts +122 -0
- package/src/cognition/persona.prior.ts +6 -0
- package/src/cognition/sense.boundary.ts +176 -0
- package/src/cognition/senses/audition.engine/engine.ts +492 -53
- package/src/cognition/senses/base.sense.engine.ts +105 -7
- package/src/cognition/senses/index.ts +83 -13
- package/src/cognition/senses/provenance.ts +128 -0
- package/src/cognition/senses/somatosensation.engine.ts +117 -9
- package/src/cognition/social.identity.ts +296 -0
- package/src/cognition/utilities/token.tracker.ts +94 -10
- package/src/core/orchestrator.ts +51 -0
- package/src/index.ts +39 -5
- package/src/llm/gate.ts +48 -0
- package/src/llm/index.ts +127 -33
- package/src/llm/routing.ts +6 -0
- package/src/llm/summarizer.ts +1 -1
- package/src/llm/wire.contracts.ts +57 -0
- package/src/pma/index.ts +68 -54
- package/src/stem/assembly.audit.ts +1 -0
- package/src/stem/guards/identity.coherence.ts +1 -1
- package/src/stem/index.ts +171 -23
- package/src/stem/mind.ts +198 -57
- package/src/stem/policy/arbiter.ts +10 -0
- package/src/stem/profiles/built-in.ts +7 -0
- package/src/{profiles → stem/profiles}/companion.ts +1 -1
- package/src/{profiles → stem/profiles}/company-brain.ts +1 -1
- package/src/{profiles → stem/profiles}/customer-service.ts +1 -1
- package/src/{profiles → stem/profiles}/game-npc.ts +1 -1
- package/src/{profiles → stem/profiles}/index.ts +1 -1
- package/src/{profiles → stem/profiles}/smart-home.ts +1 -1
- package/src/stem/tracts/effector/escalation.lifecycle.ts +239 -0
- package/src/stem/tracts/effector/policy.enforcement.ts +261 -0
- package/src/stem/tracts/effector/types.ts +110 -0
- package/src/stem/tracts/effector.controller.ts +112 -401
- package/src/stem/tracts/outbox.controller.ts +30 -17
- package/src/stem/tracts/outbox.writer.ts +40 -2
- package/src/stem/tracts/sensory.controller.ts +6 -6
- package/src/stem/tracts/session.logger.ts +6 -1
- package/src/stem/tracts/transport/types.ts +20 -1
- package/src/stem/tracts/transport.controller.ts +33 -9
- package/src/surface/channels/discord.ts +609 -0
- package/src/{channels → surface/channels}/roster.ts +1 -1
- package/src/surface/channels/types.ts +136 -0
- package/src/{channels → surface/channels}/whatsapp.ts +22 -10
- package/src/{cli.ts → surface/cli.ts} +14 -9
- package/src/{host → surface/host}/boot.ts +3 -3
- package/src/{host → surface/host}/utterances.ts +2 -2
- package/src/{mcp → surface/mcp}/effectors.ts +19 -6
- package/src/{mcp → surface/mcp}/server.ts +19 -5
- package/src/{sdk → surface/sdk}/will.ts +194 -33
- package/src/{serve → surface/serve}/server.ts +11 -4
- package/src/types.ts +24 -3
- package/dist/channels/discord.d.ts +0 -69
- package/dist/channels/discord.js +0 -193
- package/dist/channels/discord.js.map +0 -1
- package/dist/channels/whatsapp.js.map +0 -1
- package/dist/cli.js.map +0 -1
- package/dist/mcp/effectors.js.map +0 -1
- package/src/channels/discord.ts +0 -214
- package/src/channels/types.ts +0 -46
- package/src/cognition/faculties/executive.engine/messages.ts +0 -102
- package/src/extensions/livestream.ext.ts +0 -570
- package/src/extensions/time.ext.ts +0 -339
- package/src/profiles/built-in.ts +0 -7
- package/src/runners/coherence.runner.ts +0 -49
- package/src/runners/outreach.runner.ts +0 -155
- package/src/runners/social.runner.ts +0 -179
- package/src/runners/thin-shim.runner.ts +0 -205
- /package/dist/{cli.d.ts → surface/cli.d.ts} +0 -0
|
@@ -59,6 +59,18 @@ export interface ExecutiveOutputFull {
|
|
|
59
59
|
name?: string
|
|
60
60
|
learned?: string[]
|
|
61
61
|
feeling?: number
|
|
62
|
+
/**
|
|
63
|
+
* "This is the same someone as that" — another keid I now believe is this
|
|
64
|
+
* same referent, fusing two of my records into one.
|
|
65
|
+
*
|
|
66
|
+
* The mind's own verdict on an identity, and it may do what the recognition
|
|
67
|
+
* heuristic will not: absorb an ESTABLISHED relationship. The heuristic is
|
|
68
|
+
* right to refuse — fusing two real people who share a name would take one of
|
|
69
|
+
* them's whole history — but the mind has evidence a name-match does not,
|
|
70
|
+
* usually because somebody just told it. Without this, the same human
|
|
71
|
+
* well-established on two channels stayed two people permanently.
|
|
72
|
+
*/
|
|
73
|
+
sameAs?: string
|
|
62
74
|
}>
|
|
63
75
|
newGoals?: Array<{
|
|
64
76
|
description: string
|
|
@@ -70,6 +82,8 @@ export interface ExecutiveOutputFull {
|
|
|
70
82
|
goalsToAbandon?: Array<{ goalId: string; reason: string }>
|
|
71
83
|
goalsToReprioritize?: Array<{ goalId: string; newPriority: number; reason: string }>
|
|
72
84
|
selfObservations?: string[]
|
|
85
|
+
/** Compound actions the mind is naming as single skills (see ProposedSkill). */
|
|
86
|
+
newSkills?: ProposedSkill[]
|
|
73
87
|
/**
|
|
74
88
|
* Plain-text reply from a conversation facet — populated by parseResponse()
|
|
75
89
|
* from the [REPLY_TEXT]...[/REPLY_TEXT] block.
|
|
@@ -78,14 +92,10 @@ export interface ExecutiveOutputFull {
|
|
|
78
92
|
*/
|
|
79
93
|
replyText?: string
|
|
80
94
|
/**
|
|
81
|
-
*
|
|
82
|
-
*
|
|
95
|
+
* Set when the facet declared it is NOT speaking this cycle, carrying why.
|
|
96
|
+
* Present ⇒ nothing is sent, whatever else the response contains.
|
|
83
97
|
*/
|
|
84
|
-
|
|
85
|
-
targetEntityId: string
|
|
86
|
-
targetEntityName: string
|
|
87
|
-
messages: string[]
|
|
88
|
-
}>
|
|
98
|
+
noMessage?: string
|
|
89
99
|
/**
|
|
90
100
|
* System 2 only — the distinct approaches the master generated and weighed before
|
|
91
101
|
* committing, retained for explainability/auditability (and a future regret /
|
|
@@ -235,8 +245,11 @@ export interface ExecutiveContext {
|
|
|
235
245
|
relevantPlanIds: string[]
|
|
236
246
|
percepts: Array<{
|
|
237
247
|
category: string
|
|
248
|
+
/** The engine's label for the signal. */
|
|
238
249
|
summary: string
|
|
239
250
|
salience: number
|
|
251
|
+
/** What the host actually sent, whole — the evidence under the label. */
|
|
252
|
+
data?: unknown
|
|
240
253
|
}>
|
|
241
254
|
/**
|
|
242
255
|
* Host-declared abilities afforded to the Will *right now* — what it can do in
|
|
@@ -253,8 +266,11 @@ export interface ExecutiveContext {
|
|
|
253
266
|
}>
|
|
254
267
|
workingMemory: Array<{
|
|
255
268
|
type: string
|
|
269
|
+
/** The engine's label for the item. */
|
|
256
270
|
summary: string
|
|
257
271
|
activation: number
|
|
272
|
+
/** What a host sent, whole — carried through memory, not only into it. */
|
|
273
|
+
data?: unknown
|
|
258
274
|
}>
|
|
259
275
|
memories: Array<{
|
|
260
276
|
content: string
|
|
@@ -271,15 +287,21 @@ export interface ExecutiveContext {
|
|
|
271
287
|
/** How many beliefs exist but were not included due to the relevance cap. */
|
|
272
288
|
beliefsOmitted: number
|
|
273
289
|
/**
|
|
274
|
-
*
|
|
275
|
-
*
|
|
276
|
-
*
|
|
290
|
+
* What became of what it did — the Act→Confirm→Perceive loop, surfaced.
|
|
291
|
+
*
|
|
292
|
+
* Built from `action.record` entities the executive writes from the
|
|
293
|
+
* `action.outcome` / `action.withheld` events it already receives. It used to
|
|
294
|
+
* be built from `decision.record` entities carrying an `actionStatus`, a field
|
|
295
|
+
* read in one place and written in none — so this was empty in every prompt a
|
|
296
|
+
* live mind ever received, and it could see what it had SAID but never what it
|
|
297
|
+
* had DONE. See `action.record.ts`.
|
|
277
298
|
*/
|
|
278
299
|
recentActions: Array<{
|
|
279
300
|
/** Effector name that was invoked */
|
|
280
301
|
type: string
|
|
281
|
-
/**
|
|
282
|
-
|
|
302
|
+
/** How it resolved. `withheld` is distinct from `failed` on purpose: the
|
|
303
|
+
* mind formed the act and chose not to complete it. */
|
|
304
|
+
status: 'completed' | 'failed' | 'withheld'
|
|
283
305
|
/** Tick the action was executed or dispatched */
|
|
284
306
|
tick: number
|
|
285
307
|
/** Short outcome description — truncated to 120 chars */
|
|
@@ -287,6 +309,33 @@ export interface ExecutiveContext {
|
|
|
287
309
|
/** planId if this action came from a plan step */
|
|
288
310
|
planId?: string
|
|
289
311
|
}>
|
|
312
|
+
/**
|
|
313
|
+
* What the mind has said to people lately, and who has answered.
|
|
314
|
+
*
|
|
315
|
+
* The one thing it could never see about itself. `conversation.sent` has been in
|
|
316
|
+
* state since the beginning — 57 records on the Will this was found on — and
|
|
317
|
+
* reached no prompt at all, so the sole evidence of having spoken was a `✓
|
|
318
|
+
* reach-out` line under What Became Of What I Did: no words, no person, and a tick
|
|
319
|
+
* mark asserting it had worked. That is why the same question went out eleven
|
|
320
|
+
* times in two and a half minutes; from the inside each one was the first.
|
|
321
|
+
*
|
|
322
|
+
* Newest first. Answered turns are kept alongside open ones deliberately — "I
|
|
323
|
+
* asked and they replied" and "I asked and heard nothing" only mean anything
|
|
324
|
+
* against each other.
|
|
325
|
+
*/
|
|
326
|
+
spokenTurns: Array<{
|
|
327
|
+
/** Who it was said to, by name where the mind knows one. */
|
|
328
|
+
target: string
|
|
329
|
+
/** The opening words — enough to recognise a thing already said. */
|
|
330
|
+
preview: string
|
|
331
|
+
/** Ticks since it was said. */
|
|
332
|
+
age: number
|
|
333
|
+
/** Unset while still in the air; the mind is told which. */
|
|
334
|
+
answered: boolean
|
|
335
|
+
/** What they said back, when they did. The fact of an answer without its
|
|
336
|
+
* content is worse than silence — it invites acting as though it is known. */
|
|
337
|
+
answeredWith?: string
|
|
338
|
+
}>
|
|
290
339
|
/** Behavioral disposition loaded from PMA at session start — stable per session. */
|
|
291
340
|
behavioralDisposition?: {
|
|
292
341
|
riskTolerance: number
|
|
@@ -309,6 +358,10 @@ export interface ExecutiveContext {
|
|
|
309
358
|
* Omitted when the Will knows no one.
|
|
310
359
|
*/
|
|
311
360
|
knownEntities?: Array<{
|
|
361
|
+
/** Where this referent is reachable, and how each place has gone. */
|
|
362
|
+
handles?: Array<{ keid: string; kind: string; answeredAgo?: number }>
|
|
363
|
+
/** Names of referents this one may be the same as — an unsettled identity. */
|
|
364
|
+
mayBeSameAs?: string[]
|
|
312
365
|
keid: string
|
|
313
366
|
kind: 'sentient' | 'thing'
|
|
314
367
|
name?: string
|
|
@@ -336,6 +389,25 @@ export interface ExecutiveContext {
|
|
|
336
389
|
|
|
337
390
|
// ── Pending message ──────────────────────────────────────────
|
|
338
391
|
|
|
392
|
+
/**
|
|
393
|
+
* A compound action the mind names as one thing it does — "when I do A then B,
|
|
394
|
+
* that is <name>". Registered into the SchemaRepertoire as a composite, after
|
|
395
|
+
* which it competes as a single affordance and can proceduralize into a habit.
|
|
396
|
+
*
|
|
397
|
+
* This is the creation seam for the instrumental→habitual gradient. Before it,
|
|
398
|
+
* `agency.composite.proposed` was subscribed by ReafferenceEngine — whose handler
|
|
399
|
+
* is the only caller of `registerComposite()` anywhere — and published by nothing,
|
|
400
|
+
* so no Will could ever hold a skill beyond the innate floor (#114).
|
|
401
|
+
*/
|
|
402
|
+
export interface ProposedSkill {
|
|
403
|
+
/** What the mind calls it. Becomes the schema id. */
|
|
404
|
+
id: string
|
|
405
|
+
/** The sub-schemas it is made of, in order. Two or more, or it is not compound. */
|
|
406
|
+
composedOf: string[]
|
|
407
|
+
tags?: string[]
|
|
408
|
+
cost?: number
|
|
409
|
+
}
|
|
410
|
+
|
|
339
411
|
export interface PendingMessage {
|
|
340
412
|
id: string
|
|
341
413
|
content: string
|
|
@@ -24,18 +24,18 @@ import type {
|
|
|
24
24
|
SimulationContext,
|
|
25
25
|
ReadonlySimulationState,
|
|
26
26
|
StateCommands,
|
|
27
|
-
SimulationEvent,
|
|
28
27
|
SimulationEntity,
|
|
29
28
|
} from '#core/types'
|
|
30
29
|
import type { SimulationEngine, EngineResult, CognitiveEngine } from '#cognition/types'
|
|
31
30
|
import type { CognitiveEventSchema } from '#cognition/schema.registry'
|
|
32
31
|
import type { CognitiveEvent, CognitiveBus } from '#cognition/bus'
|
|
32
|
+
import { perceptEntity, PERCEPT_SUMMARY_CAP } from '#cognition/percept.entity'
|
|
33
33
|
import { GenerativeModel } from '#cognition/generative.model'
|
|
34
34
|
import {
|
|
35
|
-
|
|
35
|
+
ATTENUATION, CORRESPONDENCE_ATTENUATION,
|
|
36
36
|
liveConsequences, matchConsequenceText, matchConsequenceEntity,
|
|
37
37
|
} from '#agency/consequence'
|
|
38
|
-
import {
|
|
38
|
+
import { MIND_OWN_ENTITY_TYPES } from '#cognition/sense.boundary'
|
|
39
39
|
|
|
40
40
|
export interface ExteroceptionConfig {
|
|
41
41
|
/** Maximum percepts to produce per tick */
|
|
@@ -43,9 +43,18 @@ export interface ExteroceptionConfig {
|
|
|
43
43
|
/** Default salience for unmarked percepts */
|
|
44
44
|
defaultSalience?: number
|
|
45
45
|
/** Whether to emit percept events */
|
|
46
|
-
emitPerceptEvents?: boolean
|
|
47
46
|
/** Entity types to always treat as high-salience */
|
|
48
47
|
highPriorityTypes?: string[]
|
|
48
|
+
/**
|
|
49
|
+
* Where this mind ends — the entity types its own engines write about its own
|
|
50
|
+
* operation, which it therefore cannot encounter as world events. Live, so a
|
|
51
|
+
* host adding a cognitive engine after assembly is accounted for.
|
|
52
|
+
*
|
|
53
|
+
* Unwired (a bare harness, a unit test) it falls back to the shipped anatomy,
|
|
54
|
+
* which is right for every assembly that adds no cognitive engine of its own.
|
|
55
|
+
* See `#cognition/sense.boundary`.
|
|
56
|
+
*/
|
|
57
|
+
endogenous?: () => ReadonlySet<string>
|
|
49
58
|
bus?: CognitiveBus
|
|
50
59
|
}
|
|
51
60
|
|
|
@@ -63,51 +72,60 @@ interface RawPercept {
|
|
|
63
72
|
valenceSource?: 'entity' | 'ambient'
|
|
64
73
|
}
|
|
65
74
|
|
|
66
|
-
// Skip internal entities — they're not external percepts.
|
|
67
|
-
// Percepts about percepts create a feedback loop that floods
|
|
68
|
-
// working memory and episodic storage with noise.
|
|
69
|
-
const internalTypes = new Set([
|
|
70
|
-
'percept', 'percept.social', 'working_memory.item',
|
|
71
|
-
'interoception', 'attention.focus', 'decision.record',
|
|
72
|
-
'task.focus', 'self_observation',
|
|
73
|
-
'goal', 'belief', 'plan', 'narrative_chapter',
|
|
74
|
-
'introspection', 'self_narrative', 'cognitive_bias',
|
|
75
|
-
'effector.created', 'empathic_state', 'attachment.bond',
|
|
76
|
-
'theory_of_mind', 'reputation', 'episodic_memory',
|
|
77
|
-
// Internal state entities written by our own engines — not external events
|
|
78
|
-
'affect.blends', 'executive.summary',
|
|
79
|
-
// The agency's own forward-model records (EXAFFERENCE P1/P2): perceiving our
|
|
80
|
-
// expected-consequence descriptors would be a self-noise loop.
|
|
81
|
-
CONSEQUENCE_TYPE,
|
|
82
|
-
// The agency's own revocation tombstones (EXAFFERENCE P4) — internal bookkeeping.
|
|
83
|
-
REVOCATION_TYPE,
|
|
84
|
-
])
|
|
85
|
-
|
|
86
75
|
export class Exteroception implements SimulationEngine, CognitiveEngine {
|
|
87
76
|
readonly name = 'exteroception'
|
|
88
77
|
|
|
89
78
|
private _maxPerceptsPerTick: number
|
|
90
79
|
private _defaultSalience: number
|
|
91
|
-
private _emitPerceptEvents: boolean
|
|
92
80
|
private _highPriorityTypes: Set<string>
|
|
93
|
-
|
|
81
|
+
/**
|
|
82
|
+
* entityId → what was last seen of it. The TYPE is remembered alongside the
|
|
83
|
+
* version because a removal has to answer the same question an appearance
|
|
84
|
+
* does — "was this mine?" — and by then the entity is gone. It used to be
|
|
85
|
+
* answered by a second, separately-drifting list of id prefixes.
|
|
86
|
+
*/
|
|
87
|
+
private _previousEntityVersions = new Map<string, { at: Timestamp; type: string }>()
|
|
94
88
|
|
|
95
89
|
private _bus: CognitiveBus | null = null
|
|
96
90
|
|
|
97
91
|
private readonly _model = new GenerativeModel()
|
|
98
92
|
|
|
93
|
+
/** Live sense boundary + a memo, so a 50-engine union isn't rebuilt per tick. */
|
|
94
|
+
private _boundary: ( () => ReadonlySet<string> ) | null
|
|
95
|
+
private _endogenousMemo: ReadonlySet<string> = MIND_OWN_ENTITY_TYPES
|
|
96
|
+
|
|
99
97
|
|
|
100
98
|
constructor( config: ExteroceptionConfig = {} ){
|
|
101
99
|
this._bus = config.bus ?? null
|
|
100
|
+
this._boundary = config.endogenous ?? null
|
|
102
101
|
this._maxPerceptsPerTick = config.maxPerceptsPerTick ?? 50
|
|
103
102
|
this._defaultSalience = config.defaultSalience ?? 0.3
|
|
104
|
-
this._emitPerceptEvents = config.emitPerceptEvents ?? true
|
|
105
103
|
this._highPriorityTypes = new Set( config.highPriorityTypes ?? [
|
|
106
104
|
'message', 'notification', 'alert', 'threat', 'goal',
|
|
107
105
|
])
|
|
108
106
|
}
|
|
109
107
|
attachBus( bus: CognitiveBus ): void { this._bus = bus }
|
|
110
108
|
|
|
109
|
+
/**
|
|
110
|
+
* Wire the live sense boundary. Separate from construction because the
|
|
111
|
+
* boundary is derived from the assembled engine list, and this sense is
|
|
112
|
+
* constructed before that list exists (same reason `attachBus` exists).
|
|
113
|
+
*/
|
|
114
|
+
attachBoundary( resolve: () => ReadonlySet<string> ): void { this._boundary = resolve }
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* The types that are THIS mind rather than its world.
|
|
118
|
+
*
|
|
119
|
+
* Re-read each tick so a host engine registered after assembly still lands
|
|
120
|
+
* inside the boundary; the memo makes that a set-identity check in the common
|
|
121
|
+
* case, since `endogenousTypes` returns the shipped set unchanged when nothing
|
|
122
|
+
* extra is declared.
|
|
123
|
+
*/
|
|
124
|
+
private _endogenous(): ReadonlySet<string> {
|
|
125
|
+
if( this._boundary ) this._endogenousMemo = this._boundary()
|
|
126
|
+
return this._endogenousMemo
|
|
127
|
+
}
|
|
128
|
+
|
|
111
129
|
// ── Engine interface ─────────────────────────────────────
|
|
112
130
|
|
|
113
131
|
subscribes(): string[] { return ['executive.prediction.formed'] }
|
|
@@ -132,9 +150,7 @@ export class Exteroception implements SimulationEngine, CognitiveEngine {
|
|
|
132
150
|
state: ReadonlySimulationState,
|
|
133
151
|
context: SimulationContext
|
|
134
152
|
): Promise<EngineResult> {
|
|
135
|
-
const
|
|
136
|
-
events: Array<Omit<SimulationEvent, 'id' | 'timestamp' | 'tick'>> = [],
|
|
137
|
-
commands: StateCommands = { set: [], delete: [], metrics: [] }
|
|
153
|
+
const commands: StateCommands = { set: [], delete: [], metrics: [] }
|
|
138
154
|
|
|
139
155
|
const rawPercepts = this._scanWorld( state )
|
|
140
156
|
|
|
@@ -168,37 +184,27 @@ export class Exteroception implements SimulationEngine, CognitiveEngine {
|
|
|
168
184
|
: entityHit ? rp.salience * CORRESPONDENCE_ATTENUATION
|
|
169
185
|
: rp.salience
|
|
170
186
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
events.push({
|
|
193
|
-
type: `percept.${rp.changeType}.${rp.category}`,
|
|
194
|
-
source: this.name,
|
|
195
|
-
payload: {
|
|
196
|
-
entityId: rp.entityId,
|
|
197
|
-
salience,
|
|
198
|
-
category: rp.category,
|
|
199
|
-
summary: rp.summary,
|
|
200
|
-
},
|
|
201
|
-
})
|
|
187
|
+
// Through the shared constructor (SIGNAL_BOUNDARY P0) rather than a
|
|
188
|
+
// hand-rolled literal. A no-op here — this writer already set every core
|
|
189
|
+
// field — which is exactly why it is the one that proves the shape: four
|
|
190
|
+
// other writers reach it having each forgotten a different one.
|
|
191
|
+
//
|
|
192
|
+
// `provenance` is INFERRED here, legitimately: a match against our own
|
|
193
|
+
// live consequence descriptors is the efference copy doing its job. The
|
|
194
|
+
// sense door asserts instead, because it has nothing to match against.
|
|
195
|
+
commands.set!.push( perceptEntity( {
|
|
196
|
+
id: `percept-${tick}-${i}`,
|
|
197
|
+
tick,
|
|
198
|
+
salience,
|
|
199
|
+
category: rp.category,
|
|
200
|
+
summary: rp.summary,
|
|
201
|
+
provenance: hit ? 'reafferent' : 'exafferent',
|
|
202
|
+
entityId: rp.entityId,
|
|
203
|
+
changeType: rp.changeType,
|
|
204
|
+
...( hit ? { sourceIntentId: hit.intentId } : {} ),
|
|
205
|
+
// affect→percept seam (registry #5): what this percept FEELS like
|
|
206
|
+
...( rp.valence !== undefined ? { valence: rp.valence, valenceSource: rp.valenceSource } : {} ),
|
|
207
|
+
} ) )
|
|
202
208
|
}
|
|
203
209
|
|
|
204
210
|
// Clean up old percepts from previous ticks (keep last 2 ticks of percepts)
|
|
@@ -211,13 +217,12 @@ export class Exteroception implements SimulationEngine, CognitiveEngine {
|
|
|
211
217
|
)
|
|
212
218
|
|
|
213
219
|
|
|
214
|
-
//
|
|
220
|
+
// The percept RATE is still learned — `percept.rate` carries a precision set
|
|
221
|
+
// from `executive.prediction.formed`, and the observation is what keeps that
|
|
222
|
+
// baseline honest. What is gone is the `percept.batch.ingested` event it used
|
|
223
|
+
// to publish: one publisher, zero subscribers, ever.
|
|
215
224
|
const _bus = this._bus
|
|
216
|
-
if(
|
|
217
|
-
const predErr = this._model.observe('percept.rate', capped.length )
|
|
218
|
-
if( !predErr.gated )
|
|
219
|
-
_bus.publish({ type: 'percept.batch.ingested', version: 1, sourceEngine: this.name, salience: Math.max( 0.2, predErr.salience ), payload: { count: capped.length } })
|
|
220
|
-
}
|
|
225
|
+
if( capped.length > 0 ) this._model.observe('percept.rate', capped.length )
|
|
221
226
|
|
|
222
227
|
// percept.category.updated — one event per distinct category so subscribers
|
|
223
228
|
// (aesthetic.evaluator etc.) get a structured signal without scanning percepts
|
|
@@ -229,7 +234,7 @@ export class Exteroception implements SimulationEngine, CognitiveEngine {
|
|
|
229
234
|
_bus.publish({ type: 'percept.category.updated', version: 1, sourceEngine: this.name, salience: Math.min( 1, count * 0.15 + 0.2 ), payload: { category, count } })
|
|
230
235
|
}
|
|
231
236
|
|
|
232
|
-
return {
|
|
237
|
+
return { commands }
|
|
233
238
|
}
|
|
234
239
|
|
|
235
240
|
// ── Internal ─────────────────────────────────────────────
|
|
@@ -243,18 +248,19 @@ export class Exteroception implements SimulationEngine, CognitiveEngine {
|
|
|
243
248
|
private _scanWorld( state: ReadonlySimulationState ): RawPercept[] {
|
|
244
249
|
const percepts: RawPercept[] = []
|
|
245
250
|
const currentIds = new Set<string>()
|
|
251
|
+
const mine = this._endogenous()
|
|
246
252
|
|
|
247
253
|
for( const [ id, entity ] of state.entities ){
|
|
248
254
|
currentIds.add( id )
|
|
249
255
|
|
|
250
|
-
if(
|
|
251
|
-
// Still track
|
|
252
|
-
//
|
|
253
|
-
this._previousEntityVersions.set( id, entity.updatedAt )
|
|
256
|
+
if( mine.has( entity.type ) ){
|
|
257
|
+
// Still track it, so it never reads as "appeared" if the boundary later
|
|
258
|
+
// widens — but it is machinery, not world, and is not perceived.
|
|
259
|
+
this._previousEntityVersions.set( id, { at: entity.updatedAt, type: entity.type } )
|
|
254
260
|
continue
|
|
255
261
|
}
|
|
256
262
|
|
|
257
|
-
const previousVersion = this._previousEntityVersions.get( id )
|
|
263
|
+
const previousVersion = this._previousEntityVersions.get( id )?.at
|
|
258
264
|
|
|
259
265
|
if( previousVersion === undefined ){
|
|
260
266
|
percepts.push({
|
|
@@ -279,32 +285,27 @@ private _scanWorld( state: ReadonlySimulationState ): RawPercept[] {
|
|
|
279
285
|
})
|
|
280
286
|
}
|
|
281
287
|
|
|
282
|
-
this._previousEntityVersions.set( id, entity.updatedAt )
|
|
288
|
+
this._previousEntityVersions.set( id, { at: entity.updatedAt, type: entity.type } )
|
|
283
289
|
}
|
|
284
290
|
|
|
285
|
-
//
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
summary: `Entity removed: ${id}`,
|
|
304
|
-
})
|
|
305
|
-
}
|
|
306
|
-
this._previousEntityVersions.delete( id )
|
|
307
|
-
}
|
|
291
|
+
// Something that was there is gone. The same question as an appearance —
|
|
292
|
+
// was it mine or the world's? — and answerable now because the remembered
|
|
293
|
+
// type outlives the entity. It used to be guessed from a handful of id
|
|
294
|
+
// prefixes, which is why 17,802 of one quiet run's 36,721 percepts were the
|
|
295
|
+
// mind watching its own affordance field be torn down each tick.
|
|
296
|
+
for( const [ id, seen ] of this._previousEntityVersions ){
|
|
297
|
+
if( currentIds.has( id ) ) continue
|
|
298
|
+
|
|
299
|
+
if( !mine.has( seen.type ) )
|
|
300
|
+
percepts.push({
|
|
301
|
+
entityId: id,
|
|
302
|
+
changeType: 'removed',
|
|
303
|
+
salience: 0.4,
|
|
304
|
+
category: 'removed',
|
|
305
|
+
summary: `Entity removed: ${id}`,
|
|
306
|
+
})
|
|
307
|
+
|
|
308
|
+
this._previousEntityVersions.delete( id )
|
|
308
309
|
}
|
|
309
310
|
|
|
310
311
|
percepts.sort( ( a, b ) => b.salience - a.salience )
|
|
@@ -374,7 +375,7 @@ private _scanWorld( state: ReadonlySimulationState ): RawPercept[] {
|
|
|
374
375
|
? `${name} appears` : `${name} changed`
|
|
375
376
|
}
|
|
376
377
|
if( description ){
|
|
377
|
-
return description.slice( 0,
|
|
378
|
+
return description.slice( 0, PERCEPT_SUMMARY_CAP )
|
|
378
379
|
}
|
|
379
380
|
|
|
380
381
|
return `New ${entity.type}: ${entity.id.slice(0, 30)}`
|