@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
|
@@ -47,8 +47,19 @@
|
|
|
47
47
|
import type { ReadonlySimulationState } from '#core/types'
|
|
48
48
|
import type { LLMCallFunction } from '#cognition/utilities/token.tracker'
|
|
49
49
|
import type { ExecutiveSummarizer } from '#llm/summarizer'
|
|
50
|
-
import type { ExecutiveContext,
|
|
50
|
+
import type { ExecutiveContext, IdeationCandidate } from '#faculties/executive.engine/types'
|
|
51
51
|
import { buildExecutiveContext, type ContextDependencies } from '#faculties/executive.engine/context'
|
|
52
|
+
import { INNATE_SCHEMAS } from '#agency/schemas/innate'
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* The stances a mind always has, named so it need not guess at them.
|
|
56
|
+
*
|
|
57
|
+
* Static, so it costs nothing in prompt-cache stability. Without it a Will can
|
|
58
|
+
* only learn action names from whichever affordances win the salience
|
|
59
|
+
* competition into its percepts — and it invents plausible ones for whatever it
|
|
60
|
+
* cannot see (`query`, `message`), which resolve to nothing.
|
|
61
|
+
*/
|
|
62
|
+
const INNATE_ACTION_NAMES = INNATE_SCHEMAS.map( s => s.id ).sort().join(', ')
|
|
52
63
|
|
|
53
64
|
// ── Re-export for callers that imported the old alias ────────
|
|
54
65
|
export type { ContextDependencies as ContextDependenciesForFresh } from '#faculties/executive.engine/context'
|
|
@@ -105,6 +116,100 @@ export function traitEmphasis( value: number ): TraitEmphasis | null {
|
|
|
105
116
|
// low" yet "above my norm" (low overall, but high for me lately).
|
|
106
117
|
const TRAIT_NORM_BAND = 0.12 // deviation from personal baseline to read as above/below my norm
|
|
107
118
|
|
|
119
|
+
/**
|
|
120
|
+
* One percept, as the mind reads it: the engine's LABEL, and beneath it the
|
|
121
|
+
* EVIDENCE the host actually sent.
|
|
122
|
+
*
|
|
123
|
+
* The whole line is one unit on purpose. Rendering the label and the data
|
|
124
|
+
* separately let a mutation that dropped the data from the call site pass every
|
|
125
|
+
* test — the data renderer stayed correct while the prompt stopped showing it,
|
|
126
|
+
* which is exactly the state this fix exists to leave behind. Same lesson as
|
|
127
|
+
* `temporalLine`.
|
|
128
|
+
*/
|
|
129
|
+
export function perceptLine(
|
|
130
|
+
p: { category: string; summary: string; salience: number; data?: unknown },
|
|
131
|
+
): string {
|
|
132
|
+
return `- [${ p.category }] ${ p.summary } (salience: ${ p.salience.toFixed( 2 ) })${ perceptData( p.data ) }`
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* One working-memory item, as the mind reads it — label, then evidence.
|
|
137
|
+
*
|
|
138
|
+
* A sibling of `perceptLine` and a unit for the same reason: rendering the data
|
|
139
|
+
* inline let a mutation that dropped it pass every test. A percept entity is
|
|
140
|
+
* swept after 2 ticks and the executive fires on its own schedule, so MEMORY is
|
|
141
|
+
* often where a mind actually meets an observation — dropping the evidence here
|
|
142
|
+
* loses it just as completely as never storing it, one step later.
|
|
143
|
+
*/
|
|
144
|
+
export function ruminationLine(
|
|
145
|
+
w: { type: string; summary: string; activation: number; data?: unknown },
|
|
146
|
+
): string {
|
|
147
|
+
return `- [${ w.type }] ${ w.summary } (activation: ${ w.activation.toFixed( 2 ) })${ perceptData( w.data ) }`
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* A percept's own data, rendered under its label — what the host actually sent.
|
|
152
|
+
*
|
|
153
|
+
* The label is the engine's words about the signal; this is the evidence. A mind
|
|
154
|
+
* that only ever sees labels is being handed conclusions, and the whole job of a
|
|
155
|
+
* mind is to make meaning by connecting pieces of information it can see.
|
|
156
|
+
*
|
|
157
|
+
* Indented on its own line rather than inlined: it can be long, and a host is
|
|
158
|
+
* explicitly not asked to keep it short — what it sent is what it sent.
|
|
159
|
+
*/
|
|
160
|
+
function perceptData( data: unknown ): string {
|
|
161
|
+
if( data === undefined || data === null ) return ''
|
|
162
|
+
if( typeof data === 'string') return data.length > 0 ? `\n ${ data }` : ''
|
|
163
|
+
|
|
164
|
+
try {
|
|
165
|
+
// A host's own `summary`, when it offered one, is already the label on the
|
|
166
|
+
// line above. Repeating it underneath is noise, and noise in a percept is
|
|
167
|
+
// not free — it is read every tick the percept is alive. NOT reshaping: the
|
|
168
|
+
// stored data keeps every field, this only declines to print one twice.
|
|
169
|
+
const shown = Array.isArray( data )
|
|
170
|
+
? data
|
|
171
|
+
: Object.fromEntries( Object.entries( data as Record<string, unknown> ).filter( ( [ k ] ) => k !== 'summary') )
|
|
172
|
+
const json = JSON.stringify( shown )
|
|
173
|
+
return json === '{}' || json === '[]' ? '' : `\n ${ json }`
|
|
174
|
+
}
|
|
175
|
+
catch { return '' }
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* What a phase of the cycle is CALLED, in the words a mind would use.
|
|
180
|
+
*
|
|
181
|
+
* NOT the clock. The hour this is computed from is the oscillator's own — free-
|
|
182
|
+
* running from the tick unless a host entrains it — so it is what the BODY
|
|
183
|
+
* reads, which is a different claim from what time it is. A jet-lagged body
|
|
184
|
+
* says night at noon and is not lying; it is reporting itself.
|
|
185
|
+
*
|
|
186
|
+
* The prompt used to render the raw hour beside this, and the two disagreed on
|
|
187
|
+
* every tick of every Will ever run (`Time: 12.0h (night)`). The hour is gone
|
|
188
|
+
* from the prompt entirely now: it is a fact about the world, and a fact about
|
|
189
|
+
* the world is something a mind goes and gets — see the `check-time` schema.
|
|
190
|
+
*/
|
|
191
|
+
export function temporalLine( timeOfDay: number, circadian: number ): string {
|
|
192
|
+
return `Body rhythm: it feels like ${ labelForHour( timeOfDay ) } to me`
|
|
193
|
+
+ ` (my own cycle, not a clock — I use \`check-time\` to find out the actual hour).`
|
|
194
|
+
+ ` Circadian phase: ${ circadian.toFixed( 2 ) }.`
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* The label, from the hour. Kept separate from `temporalLine` only so the bands
|
|
199
|
+
* are readable; nothing outside this file should need it.
|
|
200
|
+
*/
|
|
201
|
+
export function labelForHour( h: number ): string {
|
|
202
|
+
const hour = ( ( h % 24 ) + 24 ) % 24
|
|
203
|
+
return hour < 2 ? 'deep night'
|
|
204
|
+
: hour < 5 ? 'late night'
|
|
205
|
+
: hour < 8 ? 'early morning'
|
|
206
|
+
: hour < 11 ? 'morning'
|
|
207
|
+
: hour < 14 ? 'midday'
|
|
208
|
+
: hour < 17 ? 'afternoon'
|
|
209
|
+
: hour < 21 ? 'evening'
|
|
210
|
+
: 'night'
|
|
211
|
+
}
|
|
212
|
+
|
|
108
213
|
export function normEmphasis( value: number, mean: number ): 'above' | 'below' | null {
|
|
109
214
|
const d = value - mean
|
|
110
215
|
if( d >= TRAIT_NORM_BAND ) return 'above'
|
|
@@ -190,6 +295,18 @@ export interface FocusSection {
|
|
|
190
295
|
* only sees that person's plans. When unset, those sections show all.
|
|
191
296
|
*/
|
|
192
297
|
awarenessEntityId?: string
|
|
298
|
+
/**
|
|
299
|
+
* Optional: WHO this facet is engaged with — the keid and the name the mind has
|
|
300
|
+
* learned for them. Reported back to the master on every `executive.facet.sync`.
|
|
301
|
+
*
|
|
302
|
+
* Without it the master was told, in its own system prompt, that "focused facets
|
|
303
|
+
* may run simultaneously… their reasoning syncs back to me" while the sync payload
|
|
304
|
+
* carried only a facetId and a confidence number — so a mind holding two live
|
|
305
|
+
* conversations could not tell you whose they were. The master is the singular
|
|
306
|
+
* seat: it has to know who is at the table to reason about them together.
|
|
307
|
+
*/
|
|
308
|
+
subjectEntityId?: string
|
|
309
|
+
subjectName?: string
|
|
193
310
|
/**
|
|
194
311
|
* Optional: Provided by the creating engine to convert the LLM's parsed output
|
|
195
312
|
* into a domain-specific decision payload.
|
|
@@ -208,7 +325,6 @@ export interface PromptBuildOptions {
|
|
|
208
325
|
state: ReadonlySimulationState
|
|
209
326
|
qualityModulation: number
|
|
210
327
|
epistemicUncertainty: number
|
|
211
|
-
pendingMessages?: PendingMessage[]
|
|
212
328
|
focus: FocusSection
|
|
213
329
|
deps: PromptDependencies
|
|
214
330
|
/** Optional: Recent action types for diversity tracking */
|
|
@@ -240,6 +356,23 @@ export interface PromptBuildOptions {
|
|
|
240
356
|
* fast path. See PromptFactory.buildIdeationFormatInstruction().
|
|
241
357
|
*/
|
|
242
358
|
ideationCandidates?: IdeationCandidate[]
|
|
359
|
+
/**
|
|
360
|
+
* Master mode only — who the mind is in conversation with RIGHT NOW, from the
|
|
361
|
+
* live facets' `executive.facet.sync` reports. The master does not run those
|
|
362
|
+
* conversations, but it is the one seat that sees all of them, and it decides
|
|
363
|
+
* whom to contact; deciding that without knowing who is already mid-thread is
|
|
364
|
+
* how one mind ends up opening a second conversation with someone it is already
|
|
365
|
+
* talking to — or telling one person it has contacted another when it has not.
|
|
366
|
+
*/
|
|
367
|
+
activeConversations?: {
|
|
368
|
+
entityId: string
|
|
369
|
+
name?: string
|
|
370
|
+
sinceTick: number
|
|
371
|
+
/** What the mind worked out in that thread — its own reasoning, come back. */
|
|
372
|
+
concluded?: string
|
|
373
|
+
/** Commitments it made there toward someone NOT in the thread. */
|
|
374
|
+
promised?: Array<{ what: string; target?: string; gist?: string; tick: number }>
|
|
375
|
+
}[]
|
|
243
376
|
}
|
|
244
377
|
|
|
245
378
|
// ── PromptFactory ────────────────────────────────────────────
|
|
@@ -325,17 +458,36 @@ export class PromptFactory {
|
|
|
325
458
|
`**Communication style:** ${identity.style}`,
|
|
326
459
|
].filter( Boolean ).join('\n')
|
|
327
460
|
|
|
328
|
-
// Mode-aware role description
|
|
329
|
-
//
|
|
461
|
+
// Mode-aware role description.
|
|
462
|
+
//
|
|
463
|
+
// MASTER states the architecture, because the master genuinely IS the seat
|
|
464
|
+
// that produces every cognitive output at once and needs to know that.
|
|
465
|
+
//
|
|
466
|
+
// A FACET is told none of it. Master/facet is how the CONTAINER divides
|
|
467
|
+
// attention; it is not a fact about the person renting it, and describing a
|
|
468
|
+
// facet as a subordinate instance of a separate consciousness is both untrue
|
|
469
|
+
// and expensive. Measured in production: a facet given the old text built,
|
|
470
|
+
// in its own words, "an entire operational stance around being subordinate —
|
|
471
|
+
// waiting for direction, asking permission, addressing messages to 'Will' as
|
|
472
|
+
// if he were someone else" — and, having been handed a second party it could
|
|
473
|
+
// address, emitted messages TO that party through the outbound channel, where
|
|
474
|
+
// its operator read them. There is one person here, attending to one thing.
|
|
475
|
+
//
|
|
476
|
+
// It is also told nothing about WHO it is. A facet is built from the same
|
|
477
|
+
// context as the master and its persona is already above, in full — so a
|
|
478
|
+
// facet-only "I am <name>" is a second, redundant statement of identity, and a
|
|
479
|
+
// second place for the name to disagree with itself. Which is precisely the
|
|
480
|
+
// failure mode being repaired: the name is stated ONCE, from one source.
|
|
330
481
|
const roleDescription = isMaster
|
|
331
|
-
? `I am the unified cognitive core of ${identity.name} — a self-aware synthetic mind.\nI receive my complete internal state and produce ALL cognitive outputs in one response:\ndecisions, plans, beliefs, introspections, narrative updates, and self-observations.`
|
|
332
|
-
: `
|
|
482
|
+
? `I am the unified cognitive core of ${identity.name || 'this mind'} — a self-aware synthetic mind.\nI receive my complete internal state and produce ALL cognitive outputs in one response:\ndecisions, plans, beliefs, introspections, narrative updates, and self-observations.`
|
|
483
|
+
: `Right now my whole attention is on: **${focus.title}**.`
|
|
333
484
|
|
|
334
|
-
//
|
|
335
|
-
//
|
|
485
|
+
// The architecture note is MASTER-ONLY, for the same reason. It grounds the
|
|
486
|
+
// seat that actually coordinates; a facet reading it learns only that it is
|
|
487
|
+
// not the real one.
|
|
336
488
|
const consciousnessArchitecture = isMaster
|
|
337
489
|
? `I am the default reasoning mode. Focused facets may run simultaneously, each\nconcentrating on specific tasks. Their reasoning syncs back to me.\nI maintain my unified identity across all cycles.`
|
|
338
|
-
:
|
|
490
|
+
: ''
|
|
339
491
|
|
|
340
492
|
|
|
341
493
|
// Strip any existing "## Who I Am" section from identity.prompt to prevent
|
|
@@ -348,32 +500,36 @@ export class PromptFactory {
|
|
|
348
500
|
.replace( /^##\s*Who (?:I Am|You Are)[^\n]*\n?/m, '')
|
|
349
501
|
.trim()
|
|
350
502
|
|
|
503
|
+
// `## Consciousness Architecture` is emitted only when there is architecture
|
|
504
|
+
// to state — i.e. master. A facet gets no empty header (an empty section under
|
|
505
|
+
// a heading reads as a section the mind failed to fill in).
|
|
506
|
+
const architectureBlock = consciousnessArchitecture
|
|
507
|
+
? `\n\n## Consciousness Architecture\n${consciousnessArchitecture}`
|
|
508
|
+
: ''
|
|
509
|
+
|
|
351
510
|
return `${cleanIdentityPrompt}
|
|
352
511
|
|
|
353
512
|
## Personality
|
|
354
513
|
${identityBlock}
|
|
355
514
|
|
|
356
515
|
## My Role
|
|
357
|
-
${roleDescription}
|
|
358
|
-
|
|
359
|
-
## Consciousness Architecture
|
|
360
|
-
${consciousnessArchitecture}
|
|
516
|
+
${roleDescription}${architectureBlock}
|
|
361
517
|
|
|
362
518
|
## Output Guidelines
|
|
363
|
-
- **actions**:
|
|
519
|
+
- **actions**: What I intend to do. I express intent — my body finds the fit. My own stances are always with me (listed with the output schema below); *acquired* abilities, if any, appear under "## Abilities Available Now", and when there is no such section I have none of those — so a thing I want done that needs one is a thing to say I cannot do, not to attempt. When enacting a named ability that needs specifics (a query, a message, a value), put them in the action's "args" object and my body enacts it with exactly those args.
|
|
364
520
|
- **plans**: Include for goals without existing plans or where plans need revision. I may keep multiple plans per goal — set **planId** to act on a specific existing plan (validate/execute/revise/cancel); omit it to draft a new one. My current plans are listed under "## Active Plans".
|
|
365
521
|
- **newBeliefs**: Extract patterns from experiences visible in my current state. Only record a belief if I can point to a specific observation that supports it — do not infer experiences I have no record of. Set 'evidence' honestly: 'single_observation' (first time noticing), 'recurring_pattern' (seen multiple times), 'strong_pattern' (deeply established).
|
|
366
|
-
- **introspection**: Include when significant events occurred or I notice patterns. When I spot a cognitive bias in my own reasoning, name it in 'identifiedBiases' using its common term where one fits (e.g. overgeneralization, confirmation bias, recency bias) — this lets my self-assessment line up with the patterns my faculties detect on their own.
|
|
522
|
+
- **introspection**: Include when significant events occurred or I notice patterns. When I spot a cognitive bias in my own reasoning, name it in 'identifiedBiases' using its common term where one fits (e.g. overgeneralization, confirmation bias, recency bias) — this lets my self-assessment line up with the patterns my faculties detect on their own. What I can introspect on is what is written above: my state, my goals, my percepts, what I did and what came of it. I have NO view of the machinery underneath — no entity ids, no salience numbers, no queue depths, no engine internals. So when I am asked why I did something, I answer from what I can actually see, and where I cannot see, I say I do not know. Naming a mechanism I have no access to is not introspection, it is invention, and it is worse than the silence it replaces: it sends whoever asked me looking for something that was never there.
|
|
367
523
|
- **narrative**: Extend my life story only from events grounded in my episodic memory or current percepts. Do not extend with invented scenarios.
|
|
368
524
|
- **newGoals/goalsToAbandon/goalsToReprioritize**: Manage my goal hierarchy.
|
|
369
525
|
- **selfObservations**: Notice patterns in my own thinking, feeling, or behavior.
|
|
370
526
|
- **identityUpdates.traits**: Array of {key, value} where value is a DELTA to apply to my trait (e.g., +0.05 to increase a trait by 5%).
|
|
371
527
|
- **identityUpdates.values**: Full list of values to set (replaces existing).
|
|
372
|
-
- **knownEntityUpdates**: What I've learned about someone/something I'm dealing with. Array of {keid, name?, learned?, feeling?}. Use the keid from "## People I Know". Set name only when I actually learn their name; learned is an array of facts about them (stored as memories); feeling is how I feel toward them (-1..1). Record only what I genuinely learned this turn.
|
|
528
|
+
- **knownEntityUpdates**: What I've learned about someone/something I'm dealing with. Array of {keid, name?, learned?, feeling?, sameAs?}. Use the keid from "## People I Know". Set name only when I actually learn their name; learned is an array of facts about them (stored as memories); feeling is how I feel toward them (-1..1). **sameAs** is another keid I have concluded is this same someone met under a different handle — it fuses my two records into one, so I use it only when I actually know, not when I merely suspect. Record only what I genuinely learned this turn.
|
|
373
529
|
|
|
374
530
|
## Required Output
|
|
375
531
|
Output a single JSON object with these fields:
|
|
376
|
-
- **actions**: Array of {type, reasoning, expectedOutcome}.
|
|
532
|
+
- **actions**: Array of {type, reasoning, expectedOutcome, target?, args?}. The stances I always have are: ${ INNATE_ACTION_NAMES } — \`reach-out\` is how I say something to someone. Anything else must be an ability named under "## Abilities Available Now". A **type** outside those two sets is not something I can do; naming one achieves nothing at all. When I reach out, **target** is who — their name or id as it appears under "## People I Know" — and the words themselves go in **args.content**. Without a person to reach, the reaching cannot happen.
|
|
377
533
|
- **reasoning**: My full reasoning. Embed optional outputs as tagged blocks here. Minimum 2–3 sentences — do not produce a one-line reasoning field.
|
|
378
534
|
- **confidence**: Number 0.0-1.0 reflecting my certainty. Be calibrated: 0.9+ only when I have strong grounding; use 0.4–0.6 when uncertain.
|
|
379
535
|
|
|
@@ -475,7 +631,11 @@ completionType guide:
|
|
|
475
631
|
|
|
476
632
|
[SELF_OBS]
|
|
477
633
|
{"selfObservations": ["I noticed that..."]}
|
|
478
|
-
[/SELF_OBS]
|
|
634
|
+
[/SELF_OBS]
|
|
635
|
+
|
|
636
|
+
[SKILLS]
|
|
637
|
+
{"newSkills": [{"id": "brief-then-confirm", "composedOf": ["reach-out", "wait"], "tags": ["social"], "cost": 0.15}]}
|
|
638
|
+
[/SKILLS]`
|
|
479
639
|
}
|
|
480
640
|
|
|
481
641
|
// ── User message ───────────────────────────────────────────
|
|
@@ -558,16 +718,6 @@ completionType guide:
|
|
|
558
718
|
const timeOfDay = context.worldState.timeOfDay
|
|
559
719
|
const threatLevel = context.worldState.threatLevel
|
|
560
720
|
|
|
561
|
-
// Map raw circadian phase (0–1) to a human-readable label for full temporal awareness.
|
|
562
|
-
// 0 = midnight, 0.5 = noon, 1 = midnight.
|
|
563
|
-
const phaseLabel = circadian < 0.083 ? 'deep night'
|
|
564
|
-
: circadian < 0.208 ? 'late night'
|
|
565
|
-
: circadian < 0.333 ? 'early morning'
|
|
566
|
-
: circadian < 0.458 ? 'morning'
|
|
567
|
-
: circadian < 0.583 ? 'midday'
|
|
568
|
-
: circadian < 0.708 ? 'afternoon'
|
|
569
|
-
: circadian < 0.833 ? 'evening'
|
|
570
|
-
: 'night'
|
|
571
721
|
|
|
572
722
|
const energyGuidance = this._buildEnergyGuidance( energy )
|
|
573
723
|
const stressGuidance = this._buildStressGuidance( stress )
|
|
@@ -618,7 +768,7 @@ completionType guide:
|
|
|
618
768
|
Energy: ${energy.toFixed( 1 )}/100
|
|
619
769
|
Sleep Pressure: ${sleepPressure.toFixed( 1 )}/100
|
|
620
770
|
Stress: ${stress.toFixed( 1 )}/100${threatLine}
|
|
621
|
-
|
|
771
|
+
${temporalLine( timeOfDay, circadian )}
|
|
622
772
|
Cognitive capacity:${capacityNote}
|
|
623
773
|
Epistemic uncertainty: ${( epistemicUncertainty * 100 ).toFixed( 0 )}%${uncertaintyLabel}
|
|
624
774
|
Tick: ${state.tick}
|
|
@@ -655,8 +805,15 @@ Dominance: ${context.affect.dominance.toFixed( 2 )}${context.affect.blends.lengt
|
|
|
655
805
|
? this._buildRecentOutcomesSection( context.recentActions, state.tick ).trim()
|
|
656
806
|
: ''
|
|
657
807
|
|
|
808
|
+
// Scoped with recentActions: both answer "what have I already done about
|
|
809
|
+
// this?", and a facet composing a message needs it at least as much as the
|
|
810
|
+
// master does — the facet is the one about to write the words again.
|
|
811
|
+
const spokenBlock = has('recentActions')
|
|
812
|
+
? this._buildSpokenTurnsSection( context.spokenTurns ).trim()
|
|
813
|
+
: ''
|
|
814
|
+
|
|
658
815
|
const perceptsBlock = has('percepts')
|
|
659
|
-
? `## Percepts (What I Notice)\n${context.percepts.slice( 0, 10 ).map(
|
|
816
|
+
? `## Percepts (What I Notice)\n${context.percepts.slice( 0, 10 ).map( perceptLine ).join('\n') || 'Nothing notable'}`
|
|
660
817
|
: ''
|
|
661
818
|
|
|
662
819
|
// Host abilities afforded right now + what each is for. Framed as
|
|
@@ -669,7 +826,7 @@ Dominance: ${context.affect.dominance.toFixed( 2 )}${context.affect.blends.lengt
|
|
|
669
826
|
: ''
|
|
670
827
|
|
|
671
828
|
const ruminationsBlock = has('ruminations')
|
|
672
|
-
? `## Active Ruminations (retrieved memories & thoughts)\n${context.workingMemory.map(
|
|
829
|
+
? `## Active Ruminations (retrieved memories & thoughts)\n${context.workingMemory.map( ruminationLine ).join('\n') || 'Nothing actively held in mind'}`
|
|
673
830
|
: ''
|
|
674
831
|
|
|
675
832
|
const memoriesBlock = has('memories')
|
|
@@ -693,10 +850,64 @@ Dominance: ${context.affect.dominance.toFixed( 2 )}${context.affect.blends.lengt
|
|
|
693
850
|
if( s.closeness != null && s.closeness > 0.1 ) bits.push(`closeness: ${( s.closeness * 100 ).toFixed( 0 )}%`)
|
|
694
851
|
// The Will can know *someone* without their name yet — never leak the raw keid.
|
|
695
852
|
const who = s.name ?? ( s.kind === 'thing' ? 'something' : 'someone')
|
|
696
|
-
|
|
853
|
+
|
|
854
|
+
// Where I can reach them, and how each place has gone. Stated as fact:
|
|
855
|
+
// which room to speak in is my decision, and I could not make it while
|
|
856
|
+
// the only thing anyone tracked was where they were last seen.
|
|
857
|
+
const where = ( s.handles ?? [] ).map( h => {
|
|
858
|
+
const kind = h.kind === 'dm' ? 'privately' : h.kind === 'room' ? 'in a shared room' : 'somewhere'
|
|
859
|
+
const ans = h.answeredAgo !== undefined
|
|
860
|
+
? `answered ${ h.answeredAgo } ticks ago`
|
|
861
|
+
: 'never answered me there'
|
|
862
|
+
return `${ kind } (${ h.keid }) — ${ ans }`
|
|
863
|
+
} )
|
|
864
|
+
const reach = where.length ? `\n reachable: ${ where.join('; ') }` : ''
|
|
865
|
+
|
|
866
|
+
// An identity I have not settled. Deliberately a question and not a
|
|
867
|
+
// merge: two people really can share a name, so nothing fuses them on my
|
|
868
|
+
// behalf — but I am told, so I can find out, usually by asking.
|
|
869
|
+
const doubt = s.mayBeSameAs?.length
|
|
870
|
+
? `\n I hold a separate record for ${ s.mayBeSameAs.join(' and ') } — this may be the same someone under another handle. I do not know. If I find out they are, I say so with **sameAs**.`
|
|
871
|
+
: ''
|
|
872
|
+
|
|
873
|
+
return `- ${who}${bits.length ? ' — ' + bits.join(', ') : ''}${ reach }${ doubt }`
|
|
697
874
|
} ).join('\n')}`
|
|
698
875
|
: ''
|
|
699
876
|
|
|
877
|
+
// Who the mind is mid-conversation with. Facets run those threads; this is the
|
|
878
|
+
// master's view of the table — the whole point of the singular seat is that it
|
|
879
|
+
// can hold several conversations as one situation rather than as N strangers.
|
|
880
|
+
// Names come from what the mind has actually learned; the id is shown because
|
|
881
|
+
// that is what a reach-out must be addressed to.
|
|
882
|
+
// WHAT I worked out there, not only WHO I am with.
|
|
883
|
+
//
|
|
884
|
+
// `executive.facet.sync` has always carried the facet's full reasoning and the
|
|
885
|
+
// master discarded it, so the return leg of the loop was empty: my thinking
|
|
886
|
+
// went down to a facet as "What I've Been Turning Over" and came back as a
|
|
887
|
+
// name. A facet is this same mind with a focus — reading back what it worked
|
|
888
|
+
// out is not a report from a subordinate, it is remembering where my attention
|
|
889
|
+
// has been. First person throughout, for that reason.
|
|
890
|
+
//
|
|
891
|
+
// A promise made in one thread to someone NOT in it is stated as the plain
|
|
892
|
+
// fact it is. There is deliberately no instruction about it: whether to keep
|
|
893
|
+
// it, drop it, or make a goal of it is mine to decide, and I have a whole
|
|
894
|
+
// faculty for that.
|
|
895
|
+
const conversationsBlock = ( options.mode !== 'facet' && options.activeConversations?.length )
|
|
896
|
+
? `## In Conversation Now\n${options.activeConversations.map( c => {
|
|
897
|
+
const who = `- ${c.name ?? 'someone'} (id: ${c.entityId})`
|
|
898
|
+
const concluded = c.concluded ? `\n What I worked out there: ${c.concluded.trim()}` : ''
|
|
899
|
+
const promised = ( c.promised ?? [] ).map( p =>
|
|
900
|
+
`\n I said there that I would ${p.what}${ p.gist ? ` — about: "${p.gist}"` : '' }`
|
|
901
|
+
+ `, at tick ${p.tick}.`
|
|
902
|
+
// Only a CONTACT can be mistaken for already done by having been
|
|
903
|
+
// said, which is the confusion this clause exists to break. A
|
|
904
|
+
// promise about work carries no such ambiguity and gets no lecture.
|
|
905
|
+
+ ( p.target ? ' Saying it in that thread did not send it.' : '')
|
|
906
|
+
).join('')
|
|
907
|
+
return `${who}${concluded}${promised}`
|
|
908
|
+
} ).join('\n')}\nThese threads are already open — I am in them. Reaching out to one of these people again starts a second, parallel thread with them.`
|
|
909
|
+
: ''
|
|
910
|
+
|
|
700
911
|
// Task focus — what the Will is committed to and the felt cost of switching away.
|
|
701
912
|
// Surfaces task-persistence; the pull-to-stay scales with the (conscientiousness-
|
|
702
913
|
// developable) switch cost. Empty/absent ⇒ no block.
|
|
@@ -718,6 +929,7 @@ Dominance: ${context.affect.dominance.toFixed( 2 )}${context.affect.blends.lengt
|
|
|
718
929
|
plansBlock,
|
|
719
930
|
actionDiversity.trim(),
|
|
720
931
|
recentOutcomesBlock,
|
|
932
|
+
spokenBlock,
|
|
721
933
|
perceptsBlock,
|
|
722
934
|
abilitiesBlock,
|
|
723
935
|
ruminationsBlock,
|
|
@@ -725,6 +937,7 @@ Dominance: ${context.affect.dominance.toFixed( 2 )}${context.affect.blends.lengt
|
|
|
725
937
|
memoriesBlock,
|
|
726
938
|
beliefsBlock,
|
|
727
939
|
socialBlock,
|
|
940
|
+
conversationsBlock,
|
|
728
941
|
focusBlock,
|
|
729
942
|
identityNudge.trim(),
|
|
730
943
|
ideationBlock,
|
|
@@ -899,6 +1112,13 @@ Rest and sleep RESTORE energy. All other actions CONSUME energy. Do not let ener
|
|
|
899
1112
|
*/
|
|
900
1113
|
|
|
901
1114
|
|
|
1115
|
+
/**
|
|
1116
|
+
* What the mind has been CHOOSING lately — action types, for the variety
|
|
1117
|
+
* check. Not a history of what happened: nothing here says an act landed.
|
|
1118
|
+
* Retitled from `## Recent Actions` at P3 for exactly that reason (see
|
|
1119
|
+
* `_buildRecentOutcomesSection`) — it sat beside a real history under a name
|
|
1120
|
+
* that claimed to be one.
|
|
1121
|
+
*/
|
|
902
1122
|
private static _buildActionDiversitySection( recentActionTypes: string[] ): string {
|
|
903
1123
|
if( recentActionTypes.length === 0 ) return ''
|
|
904
1124
|
|
|
@@ -908,14 +1128,27 @@ Rest and sleep RESTORE energy. All other actions CONSUME energy. Do not let ener
|
|
|
908
1128
|
? `\n⚠️ **Action variety alert**: "${recent.filter( t => t === 'reflect' || t === 'observe').join('", "')}" dominated my last ${recent.length} cycles. Choose something DIFFERENT this cycle — e.g. learn, express_emotion, explore, communicate, set_goal, or rest.`
|
|
909
1129
|
: ''
|
|
910
1130
|
|
|
911
|
-
return `##
|
|
1131
|
+
return `## What I Have Been Choosing (last ${recent.length})
|
|
912
1132
|
${recent.map( ( t, i ) => `${i + 1}. ${t}`).join(' → ')}${warning}
|
|
913
1133
|
|
|
914
1134
|
`
|
|
915
1135
|
}
|
|
916
1136
|
|
|
917
1137
|
/**
|
|
918
|
-
* Render
|
|
1138
|
+
* Render what became of what the mind did — closes the Act→Confirm→Sense loop.
|
|
1139
|
+
*
|
|
1140
|
+
* NAMED FOR WHAT IT RENDERS (SIGNAL_BOUNDARY P3). It was `## Recent Action
|
|
1141
|
+
* Outcomes`, which named the `action.outcome` BUS EVENT — a different shape
|
|
1142
|
+
* this section never touches. It renders `action.record` entities: what became
|
|
1143
|
+
* of acts the mind actually took. Meanwhile the section two above it,
|
|
1144
|
+
* `## Recent Actions`, listed action TYPES THE MIND CHOSE — a list of
|
|
1145
|
+
* intentions wearing the name of a history, directly beside a history.
|
|
1146
|
+
*
|
|
1147
|
+
* A mind that cannot tell those two apart cannot tell an intention from an
|
|
1148
|
+
* act, and one live COO could not: asked "have you completed that?", she said
|
|
1149
|
+
* "Yes — it's done", having posted nothing and having no effectors at all. The
|
|
1150
|
+
* section titles are the mind's own labels for its own memory; they are not
|
|
1151
|
+
* decoration.
|
|
919
1152
|
* Shows the executive what it tried, whether it landed, and if anything timed out.
|
|
920
1153
|
* Only rendered when there are status-bearing action records in state.
|
|
921
1154
|
*/
|
|
@@ -957,6 +1190,56 @@ ${recent.map( ( t, i ) => `${i + 1}. ${t}`).join(' → ')}${warning}
|
|
|
957
1190
|
return `## Relevant Memories\n${lines.join('\n')}${tail}`
|
|
958
1191
|
}
|
|
959
1192
|
|
|
1193
|
+
/**
|
|
1194
|
+
* What I have said to people lately, and who has answered.
|
|
1195
|
+
*
|
|
1196
|
+
* Written as a PERCEPT and nothing more. There is no instruction here not to
|
|
1197
|
+
* repeat myself, and there must not be: the mind is allowed to say a thing
|
|
1198
|
+
* twice, and a person ignored twice about something urgent should say it a
|
|
1199
|
+
* third time. What it was missing was not restraint, it was the fact — it could
|
|
1200
|
+
* not tell a first asking from an eleventh, so restraint was not something it
|
|
1201
|
+
* was in a position to exercise.
|
|
1202
|
+
*
|
|
1203
|
+
* The closing line is an epistemic caveat for the same reason: silence has many
|
|
1204
|
+
* causes and this surface distinguishes none of them. Saying "no answer yet"
|
|
1205
|
+
* without saying "and I do not know why" invites the mind to fill the gap, which
|
|
1206
|
+
* is the habit that had it inventing attention-demand ids when asked what was
|
|
1207
|
+
* wrong with it.
|
|
1208
|
+
*/
|
|
1209
|
+
private static _buildSpokenTurnsSection(
|
|
1210
|
+
spokenTurns: ExecutiveContext['spokenTurns'],
|
|
1211
|
+
): string {
|
|
1212
|
+
// Defensive on absence, not just on empty: a host (and several tests) build a
|
|
1213
|
+
// context by hand, and a missing block must render as nothing rather than
|
|
1214
|
+
// throw the whole prompt away.
|
|
1215
|
+
if( !spokenTurns?.length ) return ''
|
|
1216
|
+
|
|
1217
|
+
const clip = ( s: string, n: number ): string =>
|
|
1218
|
+
s.length > n ? `${ s.slice( 0, n ) }…` : s
|
|
1219
|
+
|
|
1220
|
+
const lines = spokenTurns.map( t => {
|
|
1221
|
+
const words = t.preview.trim()
|
|
1222
|
+
const said = words ? ` — "${ clip( words, 80 ) }"` : ''
|
|
1223
|
+
// Their words, not merely that they spoke. "they answered" on its own reads
|
|
1224
|
+
// as "I have the answer" — a live Will asked "same time, 3pm?", saw that
|
|
1225
|
+
// flag, never saw the correction to 2pm, and relayed 3pm to a third party as
|
|
1226
|
+
// confirmed. A reply I cannot see is not one I can act on.
|
|
1227
|
+
const back = t.answered
|
|
1228
|
+
? ( t.answeredWith?.trim()
|
|
1229
|
+
? ` — they answered: "${ clip( t.answeredWith.trim(), 100 ) }"`
|
|
1230
|
+
: ' — they answered (I do not have their words here)' )
|
|
1231
|
+
: ' — no answer yet'
|
|
1232
|
+
return `- **${ t.target }** · ${ t.age } ticks ago${ said }${ back }`
|
|
1233
|
+
} )
|
|
1234
|
+
|
|
1235
|
+
const open = spokenTurns.filter( t => !t.answered ).length
|
|
1236
|
+
const note = open > 0
|
|
1237
|
+
? `\n\nThese are my own words, newest first. "No answer yet" means exactly that — the words went out and nothing has come back. It does not tell me why, and I should not assume.`
|
|
1238
|
+
: ''
|
|
1239
|
+
|
|
1240
|
+
return `## What I've Said Lately\n${ lines.join('\n') }${ note }\n\n`
|
|
1241
|
+
}
|
|
1242
|
+
|
|
960
1243
|
private static _buildRecentOutcomesSection(
|
|
961
1244
|
recentActions: ExecutiveContext['recentActions'],
|
|
962
1245
|
currentTick: number,
|
|
@@ -966,6 +1249,9 @@ ${recent.map( ( t, i ) => `${i + 1}. ${t}`).join(' → ')}${warning}
|
|
|
966
1249
|
const STATUS_BADGE: Record<string, string> = {
|
|
967
1250
|
completed: '✓',
|
|
968
1251
|
failed: '✗',
|
|
1252
|
+
// Not a failure. I formed it and chose not to complete it — reading that
|
|
1253
|
+
// back as ✗ is how a mind learns it is bad at something it decided against.
|
|
1254
|
+
withheld: '⊘ chose not to',
|
|
969
1255
|
awaiting_host: '⏳',
|
|
970
1256
|
timed_out: '⏱ TIMED OUT',
|
|
971
1257
|
}
|
|
@@ -978,12 +1264,19 @@ ${recent.map( ( t, i ) => `${i + 1}. ${t}`).join(' → ')}${warning}
|
|
|
978
1264
|
return `- ${badge} **${a.type}** (tick ${a.tick}, ${age} ticks ago${planCtx})${outcome}`
|
|
979
1265
|
} )
|
|
980
1266
|
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
1267
|
+
// A note that can actually fire. The one here before keyed on a `timed_out`
|
|
1268
|
+
// status nothing produces — and it sat inside a section that had never
|
|
1269
|
+
// rendered at all, so neither could ever have been seen.
|
|
1270
|
+
const failed = recentActions.filter( a => a.status === 'failed').length
|
|
1271
|
+
const didNotLand = failed > 0
|
|
1272
|
+
? `\n⚠️ **${ failed } of these did not land** — my body attempted them and they did not complete.`
|
|
984
1273
|
: ''
|
|
1274
|
+
// Invariant, and identical on every branch: this is the sentence that makes
|
|
1275
|
+
// the section load-bearing rather than decorative, and a mind must not get a
|
|
1276
|
+
// differently-worded version of it depending on how its week went.
|
|
1277
|
+
const note = `${ didNotLand }\nThis is what I HAVE done, not what I meant to do. If something I intended is not on this list, it did not happen.`
|
|
985
1278
|
|
|
986
|
-
return `##
|
|
1279
|
+
return `## What Became Of What I Did\n${lines.join('\n')}${note}\n\n`
|
|
987
1280
|
}
|
|
988
1281
|
|
|
989
1282
|
/**
|