@adam0white/human-framework 2.15.0 → 2.17.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 +36 -0
- package/dist/agenda/agenda.d.ts +2 -0
- package/dist/agenda/agenda.js +11 -1
- package/dist/conversation/conversation.d.ts +13 -4
- package/dist/conversation/conversation.js +24 -2
- package/dist/index.d.ts +4 -3
- package/dist/index.js +4 -3
- package/dist/migrate.js +5 -0
- package/dist/narrate/lexicon.js +23 -0
- package/dist/narrate/narrate.d.ts +7 -1
- package/dist/narrate/narrate.js +17 -1
- package/dist/person.d.ts +6 -1
- package/dist/person.js +13 -8
- package/dist/persona-calendar.d.ts +39 -0
- package/dist/persona-calendar.js +411 -0
- package/dist/persona.d.ts +1 -1
- package/dist/persona.js +5 -2
- package/dist/projects/projects.d.ts +8 -2
- package/dist/projects/projects.js +142 -2
- package/dist/promptings/promptings.d.ts +3 -1
- package/dist/promptings/promptings.js +13 -1
- package/dist/prospection/prospection.js +15 -2
- package/dist/review/review.d.ts +4 -1
- package/dist/review/review.js +12 -1
- package/dist/types.d.ts +35 -1
- package/dist/types.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -410,6 +410,7 @@ Knowledge lives in optional `Person.prospection` and survives snapshot/restore.
|
|
|
410
410
|
`projectPersona(source, mapping)` produces `PersonaProjectionSnapshot` (`hf-persona-state/1`).
|
|
411
411
|
`admitPersona(projection, targetOpening, { mappingVersion, sourceId, targetId })` returns a detached
|
|
412
412
|
`{ person, report }`. `validatePersonaProjection(unknown)` validates portable data without filling defaults.
|
|
413
|
+
Portable v1 accepts the published 2.14.1 source-engine stamp and the current engine; it preserves that source provenance. Unknown source engines remain rejected.
|
|
413
414
|
These functions never enter the actor loop and never mutate the source or the host opening.
|
|
414
415
|
|
|
415
416
|
The host supplies a versioned map of skill ids, selected episode ids and every continuing obligation.
|
|
@@ -440,3 +441,38 @@ commitment history prunes it. It removes only records matched to an existing, cl
|
|
|
440
441
|
recursively frozen, detached `MakeUpReceipt` objects. Persist those receipts in the source replay. Pending,
|
|
441
442
|
broken, released, exempt and missing matches remain unresolved. The normal actor loop never calls retirement;
|
|
442
443
|
existing games and saves keep their previous behavior until a host opts in.
|
|
444
|
+
|
|
445
|
+
|
|
446
|
+
### Calendar passports (2.16.0, opt-in)
|
|
447
|
+
|
|
448
|
+
Use `projectCalendarPersona(source, { version, skills, episodes, calendar })` when declared obligations must
|
|
449
|
+
travel. `calendar` has version `hf-persona-calendar-map/1`, one exact clock offset, explicit injective maps
|
|
450
|
+
for commitment, chain, action, entity and norm references, and the source-backed norm catalog.
|
|
451
|
+
The result is `hf-persona-calendar/1`, wrapping the original approved Person projection and a separate
|
|
452
|
+
calendar. It preserves continuing commitments, every owed record, actual retained receipts, held norm
|
|
453
|
+
understandings and lapse state. A missing scheduled receipt remains unresolved and is disclosed; it never
|
|
454
|
+
becomes a paid duty. `isContinuingCommitment(agenda, commitment)` lets a host construct the required maps
|
|
455
|
+
using the owning agenda's existing recurrence semantics.
|
|
456
|
+
|
|
457
|
+
`validateCalendarPersona` strictly validates portable data. `admitCalendarPersona(payload, opening,
|
|
458
|
+
{ mappingVersion, sourceId, targetId, targetNorms })` checks the offset and exact catalog semantics before
|
|
459
|
+
returning a detached Person. The receiving calendar must be empty; authored role goals may remain. After
|
|
460
|
+
admission, the host uses ordinary agenda APIs and its declared calendar. No duty is waived, no new ruling
|
|
461
|
+
is invented, and no obligation is converted to a score. Activities, projects and incompatible identity or
|
|
462
|
+
health remain unsupported. The original passport format and no-call continuation remain unchanged.
|
|
463
|
+
|
|
464
|
+
### Project protection and narration options
|
|
465
|
+
|
|
466
|
+
Projects can opt into undo protection with `enableProjects(person, { protectProgress: true })`.
|
|
467
|
+
Declare `diminishes: [prospectId]` on an offer or its described successor, or let the person
|
|
468
|
+
learn the exact action context from a perceived drop after its own completed act.
|
|
469
|
+
`adoptProjectTask(person, prospectId, task)` reuses an active project and its net credit
|
|
470
|
+
for a host task; an absent match returns `undefined`.
|
|
471
|
+
|
|
472
|
+
Narration remains unchanged unless requested. Set `person.lexicon.variety`,
|
|
473
|
+
`nounActions` or `materialMeaning` for the corresponding host wording. Use
|
|
474
|
+
`promptingLine(reading, outcome, kind, { voice: 'third' })` for plain third-person lines.
|
|
475
|
+
`converse` adds per-call `loyalWarning`, `confidentMin` and `phrase` options;
|
|
476
|
+
`perceive` adds a third `{ reputationTraits }` argument. See the architecture's
|
|
477
|
+
[narration and social host options](../../docs/framework.md#narration-and-social-host-options-opt-in)
|
|
478
|
+
for cause-aware reviews and actor-addressed recall. These options change no default continuation.
|
package/dist/agenda/agenda.d.ts
CHANGED
|
@@ -56,6 +56,8 @@ export declare function createAgenda(spec: {
|
|
|
56
56
|
export declare function promise(p: Person, c: Omit<Commitment, 'id' | 'status'>): Commitment;
|
|
57
57
|
/** Release a pending commitment (the other party let it go). Released commitments do not recur. */
|
|
58
58
|
export declare function release(p: Person, id: string): boolean;
|
|
59
|
+
/** Whether an instance still owns a pending duty or a recurrence that can produce its next window. Read-only. */
|
|
60
|
+
export declare const isContinuingCommitment: (state: AgendaState, c: Commitment) => boolean;
|
|
59
61
|
/**
|
|
60
62
|
* Whether an activity that would keep `c` is under way at `now`: begun no later than the window's end
|
|
61
63
|
* (`spanMeetsWindow`), not yet ended, not sleep, and serving `c` (listed in `fulfills` or matching its action and
|
package/dist/agenda/agenda.js
CHANGED
|
@@ -49,6 +49,7 @@
|
|
|
49
49
|
import { DEFAULT_NORMS } from '../conscience/catalog.js';
|
|
50
50
|
import { clamp01, dayOf, dpow, hasNumbers, isNum, isObj } from '../core/index.js';
|
|
51
51
|
import { expectedEffect } from '../memory/index.js';
|
|
52
|
+
import { diminishesProject } from '../projects/index.js';
|
|
52
53
|
import { MINUTES_PER_DAY } from '../types.js';
|
|
53
54
|
export const AGENDA_DEFAULTS = {
|
|
54
55
|
/** Minutes before a window opens during which a commitment already pulls (to get there). */
|
|
@@ -246,6 +247,13 @@ const sameShape = (a, b) => a.kind === b.kind &&
|
|
|
246
247
|
const hasSuccessor = (state, c) => state.commitments.some((x) => x !== c && x.from > c.from && sameChain(x, c));
|
|
247
248
|
/** Closed instances that carry their chain on: kept, broken, or released by an exemption (not by the other party). */
|
|
248
249
|
const chainLink = (c) => c.status === 'kept' || c.status === 'broken' || (c.status === 'released' && c.exempt !== undefined);
|
|
250
|
+
/** Whether an instance still owns a pending duty or a recurrence that can produce its next window. Read-only. */
|
|
251
|
+
export const isContinuingCommitment = (state, c) => c.status === 'pending' ||
|
|
252
|
+
(c.recurEvery !== undefined &&
|
|
253
|
+
c.recurEvery > 0 &&
|
|
254
|
+
chainLink(c) &&
|
|
255
|
+
(c.recurUntil === undefined || c.from + c.recurEvery <= c.recurUntil) &&
|
|
256
|
+
!hasSuccessor(state, c));
|
|
249
257
|
const needsSpawn = (state, c, now) => c.recurEvery !== undefined &&
|
|
250
258
|
c.recurEvery > 0 &&
|
|
251
259
|
chainLink(c) &&
|
|
@@ -520,6 +528,8 @@ function goalValue(g, aff, now) {
|
|
|
520
528
|
}
|
|
521
529
|
/** Opt-in completion-time and success estimate, shared by direct and received routes. @internal */
|
|
522
530
|
export function temporalGoalValue(p, g, aff, now, completion) {
|
|
531
|
+
if (g.project && diminishesProject(p, aff, g.project.prospectId))
|
|
532
|
+
return 0;
|
|
523
533
|
const base = goalValue(g, aff, now);
|
|
524
534
|
return g.temporal
|
|
525
535
|
? base *
|
|
@@ -571,7 +581,7 @@ export function agendaTermsWithGoalEstimates(p, aff, now, goalOverrides) {
|
|
|
571
581
|
terms.push({ source: `commitment:${c.id}`, value: d.commitmentScale * c.importance * pressure });
|
|
572
582
|
}
|
|
573
583
|
for (const g of p.agenda.goals) {
|
|
574
|
-
if (g.status !== 'active')
|
|
584
|
+
if (g.status !== 'active' || (g.project && diminishesProject(p, aff, g.project.prospectId)))
|
|
575
585
|
continue;
|
|
576
586
|
const override = goalOverrides?.get(g.id);
|
|
577
587
|
if (override !== undefined || g.temporal) {
|
|
@@ -55,6 +55,12 @@ export interface ConverseContext {
|
|
|
55
55
|
traits?: Record<string, TraitEffect>;
|
|
56
56
|
/** Carry belief origin and opaque lineage into told claims (off by default). */
|
|
57
57
|
provenance?: boolean;
|
|
58
|
+
/** Relay beliefs this far from 0.5 (0..0.5); default 0.2. Invalid values use the default. */
|
|
59
|
+
confidentMin?: number;
|
|
60
|
+
/** Let a fond speaker warn the listener of an unfavourable character claim about them. */
|
|
61
|
+
loyalWarning?: boolean;
|
|
62
|
+
/** Presentation only. Receives a told claim or a withheld reason and its default summary; never changes selection. */
|
|
63
|
+
phrase?: (claim: Readonly<ToldClaim | WithheldClaim>, summary: string) => string;
|
|
58
64
|
}
|
|
59
65
|
/** Host-visible record of one claim. */
|
|
60
66
|
export interface ToldClaim {
|
|
@@ -80,6 +86,12 @@ export interface AdviceGiven {
|
|
|
80
86
|
/** For the listener's next decision; the voice is the speaker. */
|
|
81
87
|
suggestion: Suggestion;
|
|
82
88
|
}
|
|
89
|
+
export interface WithheldClaim {
|
|
90
|
+
prop: string;
|
|
91
|
+
reason: string;
|
|
92
|
+
/** Present only when a host phrasing callback rendered this reason. */
|
|
93
|
+
summary?: string;
|
|
94
|
+
}
|
|
83
95
|
export interface ConversationResult {
|
|
84
96
|
/** Testimony percepts for `perceive(listener, told)`. */
|
|
85
97
|
told: Percept[];
|
|
@@ -87,10 +99,7 @@ export interface ConversationResult {
|
|
|
87
99
|
advice: AdviceGiven[];
|
|
88
100
|
claims: ToldClaim[];
|
|
89
101
|
/** Candidate claims the speaker held back, and why (e.g. 'norm:backbiting', 'norm:lying'). */
|
|
90
|
-
withheld:
|
|
91
|
-
prop: string;
|
|
92
|
-
reason: string;
|
|
93
|
-
}[];
|
|
102
|
+
withheld: WithheldClaim[];
|
|
94
103
|
/** True when any told claim was a lie. */
|
|
95
104
|
deceit: boolean;
|
|
96
105
|
/** The speaker's own deed tags for conscience (e.g. backbiting/lying violated), deduplicated, sorted. */
|
|
@@ -21,6 +21,10 @@
|
|
|
21
21
|
* share of conversation about absent third parties that spreads reputational information (Dunbar 2004), and
|
|
22
22
|
* extraversion as talkativeness (how many claims are offered).
|
|
23
23
|
*
|
|
24
|
+
* SCOPE (host options): `loyalWarning` admits only unfavourable listener claims when affection is at least
|
|
25
|
+
* 0.5 (an engineering threshold). `confidentMin` sets a per-call relay threshold. `phrase` renders selected
|
|
26
|
+
* testimony only; the host owns authored facts, delivery and subsequent disclosure. No hidden relay occurs.
|
|
27
|
+
*
|
|
24
28
|
* It does NOT generate language, model turn-taking, persuasion beyond source trust, what the speaker believes
|
|
25
29
|
* the listener already knows, lies of omission, white lies told to spare feelings, or the speaker's fear of
|
|
26
30
|
* being found out. Coefficients are engineering defaults, not calibrated estimates. Nothing here judges the
|
|
@@ -150,12 +154,25 @@ export function converse(speaker, listener, ctx) {
|
|
|
150
154
|
if (b.prop.startsWith('advice:') || b.prop.includes(':should:'))
|
|
151
155
|
continue;
|
|
152
156
|
const subject = b.prop.split(':')[0];
|
|
153
|
-
if (subject ===
|
|
157
|
+
if (subject === speaker.id)
|
|
154
158
|
continue;
|
|
155
159
|
const cred = expit(b.logOdds);
|
|
156
|
-
|
|
160
|
+
const threshold = Number.isFinite(ctx.confidentMin) &&
|
|
161
|
+
ctx.confidentMin >= 0 &&
|
|
162
|
+
ctx.confidentMin <= 0.5
|
|
163
|
+
? ctx.confidentMin
|
|
164
|
+
: C.confidentMin;
|
|
165
|
+
if (Math.abs(cred - 0.5) < threshold)
|
|
157
166
|
continue;
|
|
158
167
|
const value = cred > 0.5;
|
|
168
|
+
if (subject === listener.id) {
|
|
169
|
+
const trait = parseTraitProp(b.prop, table)?.trait;
|
|
170
|
+
if (!ctx.loyalWarning ||
|
|
171
|
+
relationshipWith(speaker, listener.id).affection < 0.5 ||
|
|
172
|
+
trait === undefined ||
|
|
173
|
+
!isUnfavourableTrait(trait, value, table))
|
|
174
|
+
continue;
|
|
175
|
+
}
|
|
159
176
|
const confidence = value ? cred : 1 - cred;
|
|
160
177
|
const recency = 1 / (1 + Math.max(0, ctx.at - b.updatedAt) / C.recencyScale);
|
|
161
178
|
consider(b.prop, value, confidence, cred, false, R.confidence * (confidence - 0.5) * 2 + R.recency * recency);
|
|
@@ -231,6 +248,8 @@ export function converse(speaker, listener, ctx) {
|
|
|
231
248
|
? `${nameOf(speaker)} says ${c.about} is ${c.value ? '' : 'not '}${c.prop.split(':')[1] ?? ''}`
|
|
232
249
|
: `${nameOf(speaker)} says ${c.prop} is ${c.value ? 'so' : 'not so'}`,
|
|
233
250
|
};
|
|
251
|
+
if (ctx.phrase)
|
|
252
|
+
pc.summary = ctx.phrase(Object.freeze(structuredClone(c)), pc.summary ?? '');
|
|
234
253
|
const claim = pc.claims?.[0];
|
|
235
254
|
if (claim && c.origin !== undefined)
|
|
236
255
|
claim.origin = c.origin;
|
|
@@ -292,6 +311,9 @@ export function converse(speaker, listener, ctx) {
|
|
|
292
311
|
suggestion.appeal = 'benevolence';
|
|
293
312
|
out.advice.push({ action: a.action, percept, suggestion });
|
|
294
313
|
}
|
|
314
|
+
if (ctx.phrase)
|
|
315
|
+
for (const withheld of out.withheld)
|
|
316
|
+
withheld.summary = ctx.phrase(Object.freeze(structuredClone(withheld)), withheld.reason);
|
|
295
317
|
const magnitude = clamp01((ctx.magnitude ?? C.chatMagnitude) + C.chatPerClaim * out.told.length);
|
|
296
318
|
out.socialEvents.speaker.push({ at: ctx.at, kind: 'chat', otherId: listener.id, byMe: true, magnitude });
|
|
297
319
|
out.socialEvents.listener.push({ at: ctx.at, kind: 'chat', otherId: speaker.id, byMe: false, magnitude });
|
package/dist/index.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/** Human Framework public surface. */
|
|
2
|
-
export declare const FRAMEWORK_VERSION = "2.
|
|
2
|
+
export declare const FRAMEWORK_VERSION = "2.17.0";
|
|
3
3
|
export type { CrisisEvent, PracticeKind } from './affect/index.ts';
|
|
4
4
|
export { AFFECT_DEFAULTS, actionTendencies, advanceAffect, appraise, breakAllows, breakBehaviour, breakHazard, CRISIS_DEFAULTS, checkCrisis, createAffect, easeBreak, emotionLevel, enableBreaks, feel, inBreak, readAffect, regulate, release as releaseEmotion, skipCrisis, strain, tendencyEmotions, } from './affect/index.ts';
|
|
5
5
|
export type { GoalTemplate, MakeUpReceipt, PrayerCalendar, PrayerSchedule, PrayerTimes, Retimer, } from './agenda/index.ts';
|
|
6
|
-
export { AGENDA_DEFAULTS, abandonGoal, adoptGoal, advanceAgenda, agendaTerms, applyExemptions, CARE_DEFAULTS, calendarRetimer, careDuty, commitmentPressure, createAgenda, DEFAULT_PRAYER_TIMES, EID_PRAYER_IMPORTANCE, EXEMPTION_DEFAULTS, eidPrayer, eidWindow, fastWindow, iftarWindow, inMakruhTime, isUnderWay, MAKRUH_DEFAULTS, makruhWindows, missedExcuse, onFinished, owedMakeUps, PRAYER_IMPORTANCE, PURPOSE_DEFAULTS, prayerWindows, pressureReachedAt, promise, proposeGoals, RAMADAN_DEFAULTS, ramadanFast, ramadanMeals, release as releaseCommitment, retimeCommitments, retirePaidMakeUps, revisePurposes, scheduleMakeUp, spanMeetsWindow, suhoorWindow, timesFor, violatesAbstention, } from './agenda/index.ts';
|
|
6
|
+
export { AGENDA_DEFAULTS, abandonGoal, adoptGoal, advanceAgenda, agendaTerms, applyExemptions, CARE_DEFAULTS, calendarRetimer, careDuty, commitmentPressure, createAgenda, DEFAULT_PRAYER_TIMES, EID_PRAYER_IMPORTANCE, EXEMPTION_DEFAULTS, eidPrayer, eidWindow, fastWindow, iftarWindow, inMakruhTime, isContinuingCommitment, isUnderWay, MAKRUH_DEFAULTS, makruhWindows, missedExcuse, onFinished, owedMakeUps, PRAYER_IMPORTANCE, PURPOSE_DEFAULTS, prayerWindows, pressureReachedAt, promise, proposeGoals, RAMADAN_DEFAULTS, ramadanFast, ramadanMeals, release as releaseCommitment, retimeCommitments, retirePaidMakeUps, revisePurposes, scheduleMakeUp, spanMeetsWindow, suhoorWindow, timesFor, violatesAbstention, } from './agenda/index.ts';
|
|
7
7
|
export * from './beliefs/index.ts';
|
|
8
8
|
export * from './body/index.ts';
|
|
9
9
|
export * from './character/index.ts';
|
|
@@ -31,7 +31,8 @@ export * from './partnering/index.ts';
|
|
|
31
31
|
export { enablePersistence, PERSISTENCE_DEFAULTS, pursuitOf } from './persistence/index.ts';
|
|
32
32
|
export * from './person.ts';
|
|
33
33
|
export * from './persona.ts';
|
|
34
|
-
export
|
|
34
|
+
export * from './persona-calendar.ts';
|
|
35
|
+
export { adoptProjectTask, considerProjects, enableProjects, PROJECTS_DEFAULTS, projectAppeal, } from './projects/index.ts';
|
|
35
36
|
export * from './promptings/index.ts';
|
|
36
37
|
export type { ConsequenceEvidence, PlanRoute, PlanStep } from './prospection/index.ts';
|
|
37
38
|
export { bodyForecastFor, bodyForecastTerm, consequenceEvidence, enablePlanning, FORECAST_DEFAULTS, forecastLine, forecastThresholds, PROSPECTION_DEFAULTS, seedConsequences, } from './prospection/index.ts';
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/** Human Framework public surface. */
|
|
2
|
-
export const FRAMEWORK_VERSION = '2.
|
|
2
|
+
export const FRAMEWORK_VERSION = '2.17.0';
|
|
3
3
|
export { AFFECT_DEFAULTS, actionTendencies, advanceAffect, appraise, breakAllows, breakBehaviour, breakHazard, CRISIS_DEFAULTS, checkCrisis, createAffect, easeBreak, emotionLevel, enableBreaks, feel, inBreak, readAffect, regulate, release as releaseEmotion, skipCrisis, strain, tendencyEmotions, } from './affect/index.js';
|
|
4
4
|
// `agenda.release` collides with `affect.release`; the agenda one is re-exported under a clearer name.
|
|
5
|
-
export { AGENDA_DEFAULTS, abandonGoal, adoptGoal, advanceAgenda, agendaTerms, applyExemptions, CARE_DEFAULTS, calendarRetimer, careDuty, commitmentPressure, createAgenda, DEFAULT_PRAYER_TIMES, EID_PRAYER_IMPORTANCE, EXEMPTION_DEFAULTS, eidPrayer, eidWindow, fastWindow, iftarWindow, inMakruhTime, isUnderWay, MAKRUH_DEFAULTS, makruhWindows, missedExcuse, onFinished, owedMakeUps, PRAYER_IMPORTANCE, PURPOSE_DEFAULTS, prayerWindows, pressureReachedAt, promise, proposeGoals, RAMADAN_DEFAULTS, ramadanFast, ramadanMeals, release as releaseCommitment, retimeCommitments, retirePaidMakeUps, revisePurposes, scheduleMakeUp, spanMeetsWindow, suhoorWindow, timesFor, violatesAbstention, } from './agenda/index.js';
|
|
5
|
+
export { AGENDA_DEFAULTS, abandonGoal, adoptGoal, advanceAgenda, agendaTerms, applyExemptions, CARE_DEFAULTS, calendarRetimer, careDuty, commitmentPressure, createAgenda, DEFAULT_PRAYER_TIMES, EID_PRAYER_IMPORTANCE, EXEMPTION_DEFAULTS, eidPrayer, eidWindow, fastWindow, iftarWindow, inMakruhTime, isContinuingCommitment, isUnderWay, MAKRUH_DEFAULTS, makruhWindows, missedExcuse, onFinished, owedMakeUps, PRAYER_IMPORTANCE, PURPOSE_DEFAULTS, prayerWindows, pressureReachedAt, promise, proposeGoals, RAMADAN_DEFAULTS, ramadanFast, ramadanMeals, release as releaseCommitment, retimeCommitments, retirePaidMakeUps, revisePurposes, scheduleMakeUp, spanMeetsWindow, suhoorWindow, timesFor, violatesAbstention, } from './agenda/index.js';
|
|
6
6
|
export * from './beliefs/index.js';
|
|
7
7
|
export * from './body/index.js';
|
|
8
8
|
export * from './character/index.js';
|
|
@@ -28,7 +28,8 @@ export * from './partnering/index.js';
|
|
|
28
28
|
export { enablePersistence, PERSISTENCE_DEFAULTS, pursuitOf } from './persistence/index.js';
|
|
29
29
|
export * from './person.js';
|
|
30
30
|
export * from './persona.js';
|
|
31
|
-
export
|
|
31
|
+
export * from './persona-calendar.js';
|
|
32
|
+
export { adoptProjectTask, considerProjects, enableProjects, PROJECTS_DEFAULTS, projectAppeal, } from './projects/index.js';
|
|
32
33
|
export * from './promptings/index.js';
|
|
33
34
|
export { bodyForecastFor, bodyForecastTerm, consequenceEvidence, enablePlanning, FORECAST_DEFAULTS, forecastLine, forecastThresholds, PROSPECTION_DEFAULTS, seedConsequences, } from './prospection/index.js';
|
|
34
35
|
export { fingerprint, restore, snapshot } from './restore.js';
|
package/dist/migrate.js
CHANGED
|
@@ -71,6 +71,11 @@ export const MIGRATIONS = {
|
|
|
71
71
|
note: 'the surroundings field `ambient.now` is renamed `ambient.percept`; per-person retention is optional and starts absent; behaviour unchanged',
|
|
72
72
|
apply: renameAmbient,
|
|
73
73
|
},
|
|
74
|
+
'2.14.1': {
|
|
75
|
+
to: '2.17.0',
|
|
76
|
+
note: 'version stamp only; project protection and narration/social options require explicit opt-in, and existing enabled faculties retain exact behavior',
|
|
77
|
+
apply: stamp,
|
|
78
|
+
},
|
|
74
79
|
'2.14.0': {
|
|
75
80
|
to: '2.14.1',
|
|
76
81
|
note: 'version stamp only; restored projects and persistence retain 2.14.0 behaviour until explicitly re-enabled',
|
package/dist/narrate/lexicon.js
CHANGED
|
@@ -34,6 +34,23 @@ export const EN_LINES = {
|
|
|
34
34
|
// Decision lines by other dominant sources.
|
|
35
35
|
'source:habit': ['Same as always.', 'Out of habit, really.', "It's what I do at this hour."],
|
|
36
36
|
'source:effort': ['The easy thing, for now.', 'Nothing strenuous.'],
|
|
37
|
+
'review.cause': [
|
|
38
|
+
'After {cause}, {missed} remained undone. {next}',
|
|
39
|
+
'I left {missed} unfinished after {cause}. {next}',
|
|
40
|
+
'I was {cause}; {missed} went unfinished. {next}',
|
|
41
|
+
],
|
|
42
|
+
'review.accounting': [
|
|
43
|
+
"I didn't keep {missed}. Next time I'll be ready when it comes.",
|
|
44
|
+
'I left {missed} undone. I will prepare for the next occasion.',
|
|
45
|
+
'Today {missed} went unfinished. Next time I will make room for it.',
|
|
46
|
+
],
|
|
47
|
+
'review.ruminating': [
|
|
48
|
+
'I keep going back over {missed}.',
|
|
49
|
+
'My thoughts keep returning to {missed}.',
|
|
50
|
+
'I cannot stop turning {missed} over in my mind.',
|
|
51
|
+
],
|
|
52
|
+
'source:material.named': ['It brings {material}.', 'We can use the {material}.'],
|
|
53
|
+
'intention.material.named': ['for {material}'],
|
|
37
54
|
'source:material': ['There is money in it.', 'It pays.'],
|
|
38
55
|
'source:expectation': ['It went well last time.', 'I know how this goes.'],
|
|
39
56
|
'source:conscience:repair': ['I owe them that much.', 'I have to make this right.'],
|
|
@@ -363,6 +380,12 @@ function regularGerund(verb) {
|
|
|
363
380
|
export function actionForms(action, lexicon) {
|
|
364
381
|
const given = lexicon?.actions?.[action];
|
|
365
382
|
const base = given?.base ?? action.replace(/[-_]/g, ' ');
|
|
383
|
+
if (lexicon?.nounActions)
|
|
384
|
+
return {
|
|
385
|
+
base: given?.base ?? `do ${base}`,
|
|
386
|
+
past: given?.past ?? `did ${base}`,
|
|
387
|
+
gerund: given?.gerund ?? `doing ${base}`,
|
|
388
|
+
};
|
|
366
389
|
const [verb = base, ...rest] = base.split(' ');
|
|
367
390
|
const tail = rest.length > 0 ? ` ${rest.join(' ')}` : '';
|
|
368
391
|
return {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { DecisionRecord, Lexicon, Person, SuggestionResolution } from '../types.ts';
|
|
1
|
+
import type { DecisionRecord, Episode, Lexicon, Person, SuggestionResolution } from '../types.ts';
|
|
2
2
|
/** Intention string for a decision: 'for Allah', 'to feed myself', 'to keep my promise to X', ... */
|
|
3
3
|
export declare function intentionFor(p: Person, record: DecisionRecord, lexicon?: Lexicon): string;
|
|
4
4
|
/** First-person narration of a decision record. Deterministic by the decision id. */
|
|
@@ -7,3 +7,9 @@ export declare function narrateDecision(p: Person, record: DecisionRecord, lexic
|
|
|
7
7
|
export declare function voiceLine(p: Person, res: SuggestionResolution, key?: string, lexicon?: Lexicon): string;
|
|
8
8
|
/** Short UI summary of a person's state. */
|
|
9
9
|
export declare function describePerson(p: Person, lexicon?: Lexicon): string;
|
|
10
|
+
/**
|
|
11
|
+
* SCOPE: a host-authored addressee form of an episode, selected only for its named actor.
|
|
12
|
+
* Free text cannot safely be inflected. With no authored form, return the original summary.
|
|
13
|
+
* This read-only helper neither recalls an episode nor changes its salience or RNG.
|
|
14
|
+
*/
|
|
15
|
+
export declare function recallLine(episode: Episode, toActor: string): string;
|
package/dist/narrate/narrate.js
CHANGED
|
@@ -93,7 +93,9 @@ export function intentionFor(p, record, lexicon) {
|
|
|
93
93
|
case 'emotion':
|
|
94
94
|
return phraseLine('intention.emotion', {}, lex);
|
|
95
95
|
case 'material':
|
|
96
|
-
return
|
|
96
|
+
return lex?.materialMeaning !== undefined
|
|
97
|
+
? phraseLine('intention.material.named', { material: lex.materialMeaning }, lex)
|
|
98
|
+
: phraseLine('intention.material', {}, lex);
|
|
97
99
|
case 'precommit':
|
|
98
100
|
return phraseLine('intention.precommit', {}, lex);
|
|
99
101
|
case 'expectation':
|
|
@@ -157,6 +159,8 @@ export function narrateDecision(p, record, lexicon) {
|
|
|
157
159
|
? pickLine(`emotion:${tag}`, id, {}, lex)
|
|
158
160
|
: pickLine('emotion:default', id, {}, lex));
|
|
159
161
|
}
|
|
162
|
+
else if (kind === 'material' && lex?.materialMeaning !== undefined)
|
|
163
|
+
parts.push(pickLine('source:material.named', id, { material: lex.materialMeaning }, lex));
|
|
160
164
|
else
|
|
161
165
|
parts.push(linesFor(`source:${source}`, lex).length > 0
|
|
162
166
|
? pickLine(`source:${source}`, id, {}, lex)
|
|
@@ -192,6 +196,8 @@ export function narrateDecision(p, record, lexicon) {
|
|
|
192
196
|
/** The person's spoken reply to a suggestion. */
|
|
193
197
|
export function voiceLine(p, res, key = res.reason, lexicon) {
|
|
194
198
|
const lex = lexicon ?? p.lexicon;
|
|
199
|
+
if (lex?.variety && (res.verdict === 'assented' || res.verdict === 'deferred'))
|
|
200
|
+
key = `${p.id}:${p.now}:${p.traits.extraversion}:${p.traits.honesty}:${key}`;
|
|
195
201
|
const trust = p.will.voices.find((v) => v.voiceId === res.voiceId)?.trust ?? 0.5;
|
|
196
202
|
switch (res.verdict) {
|
|
197
203
|
case 'assented':
|
|
@@ -293,3 +299,13 @@ export function describePerson(p, lexicon) {
|
|
|
293
299
|
const state = bits.length > 0 ? bits.join(', ') : phraseLine('describe.well', {}, lex);
|
|
294
300
|
return phraseLine('describe.line', { name: p.name, act, state }, lex);
|
|
295
301
|
}
|
|
302
|
+
/**
|
|
303
|
+
* SCOPE: a host-authored addressee form of an episode, selected only for its named actor.
|
|
304
|
+
* Free text cannot safely be inflected. With no authored form, return the original summary.
|
|
305
|
+
* This read-only helper neither recalls an episode nor changes its salience or RNG.
|
|
306
|
+
*/
|
|
307
|
+
export function recallLine(episode, toActor) {
|
|
308
|
+
return episode.actorId === toActor && episode.addressedSummary !== undefined
|
|
309
|
+
? episode.addressedSummary
|
|
310
|
+
: episode.summary;
|
|
311
|
+
}
|
package/dist/person.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { type BodyForecastSpan } from './body/index.ts';
|
|
2
2
|
import { type NafsPattern } from './promptings/index.ts';
|
|
3
3
|
import { type SkillTransfer } from './skills/index.ts';
|
|
4
|
+
import { applyReputationBelief } from './social/index.ts';
|
|
4
5
|
import type { Activity, Affordance, BodyLoad, BodyReadout, Command, Commitment, DecisionRecord, LearningDomain, Minute, NeedId, NeedReading, NormDefinition, Outcome, Percept, Person, PersonSpec, Retention, Suggestion, SuggestionResolution, Unit } from './types.ts';
|
|
5
6
|
import { type CommandOutcome } from './will/index.ts';
|
|
6
7
|
export declare const PERSON_DEFAULTS: {
|
|
@@ -85,12 +86,16 @@ export declare function standUp(p: Person): boolean;
|
|
|
85
86
|
* only age (from `life.bornAt`) changes. Hosts that want the interval lived call `tick`.
|
|
86
87
|
*/
|
|
87
88
|
export declare function skip(p: Person, to: Minute): void;
|
|
89
|
+
export interface PerceiveOptions {
|
|
90
|
+
/** Complete host character-trait vocabulary; absent uses HF's default table. */
|
|
91
|
+
reputationTraits?: Parameters<typeof applyReputationBelief>[5];
|
|
92
|
+
}
|
|
88
93
|
/**
|
|
89
94
|
* Attend to percepts (limited capacity), then encode what got through: claims into beliefs, interactions
|
|
90
95
|
* into relationships, others' acts judged by my norms, appraisal into emotions, and an episode each.
|
|
91
96
|
* Returns the percepts that were attended to.
|
|
92
97
|
*/
|
|
93
|
-
export declare function perceive(p: Person, percepts: readonly Percept[]): Percept[];
|
|
98
|
+
export declare function perceive(p: Person, percepts: readonly Percept[], options?: PerceiveOptions): Percept[];
|
|
94
99
|
export interface DecideOptions {
|
|
95
100
|
suggestion?: Suggestion;
|
|
96
101
|
/** Several voices in one decision (N1); merged with `suggestion`, one per voice id. */
|
package/dist/person.js
CHANGED
|
@@ -38,7 +38,7 @@ import { intentionFor, narrateDecision, voiceLine } from './narrate/index.js';
|
|
|
38
38
|
import { advanceNeeds, createNeeds, levelOf, meanSatisfaction, readNeeds, satisfy, urgencyOf, } from './needs/index.js';
|
|
39
39
|
import { widow } from './partnering/index.js';
|
|
40
40
|
import { beginPursuit, enablePersistence, releasePursuit } from './persistence/index.js';
|
|
41
|
-
import { considerProjects, enableProjects, noteProjectStatus, perceiveProspect } from './projects/index.js';
|
|
41
|
+
import { considerProjects, enableProjects, noteProjectAct, noteProjectStatus, perceiveProspect, } from './projects/index.js';
|
|
42
42
|
import { enablePromptings, nafsPatterns, notePromptings } from './promptings/index.js';
|
|
43
43
|
import { bodyForecastFor, consumeConsequences, enablePlanning, forecastLine, forecastThresholds, pruneConsequences, receiveConsequences, } from './prospection/index.js';
|
|
44
44
|
import { enableReview, reviewIfDue } from './review/index.js';
|
|
@@ -585,10 +585,10 @@ function socialKindOf(kind) {
|
|
|
585
585
|
return kind;
|
|
586
586
|
return SOCIAL_ALIASES[kind];
|
|
587
587
|
}
|
|
588
|
-
function perceiveOne(p, pc) {
|
|
588
|
+
function perceiveOne(p, pc, options) {
|
|
589
589
|
receiveConsequences(p, pc);
|
|
590
590
|
if (p.projects && pc.prospect)
|
|
591
|
-
perceiveProspect(p, pc.prospect, pc.at);
|
|
591
|
+
perceiveProspect(p, pc.prospect, pc.at, (pc.channel === 'saw' || pc.channel === 'outcome') && (pc.actorId === undefined || pc.actorId === p.id));
|
|
592
592
|
const at = Math.min(Math.max(pc.at, p.affect.lastUpdated), p.now);
|
|
593
593
|
const actor = pc.actorId;
|
|
594
594
|
const target = pc.targetId;
|
|
@@ -606,7 +606,7 @@ function perceiveOne(p, pc) {
|
|
|
606
606
|
if (claim.origin !== undefined || claim.lineage !== undefined)
|
|
607
607
|
noteProvenance(p, claim, direct ? p.id : (actor ?? 'rumour'), at);
|
|
608
608
|
// Hearsay about someone's character moves my relationship with them (reputation).
|
|
609
|
-
applyReputationBelief(p, claim.prop, before, credence(p, claim.prop), at);
|
|
609
|
+
applyReputationBelief(p, claim.prop, before, credence(p, claim.prop), at, options.reputationTraits);
|
|
610
610
|
}
|
|
611
611
|
// Another source's account, reported by the teller (2.10.0): one source telling two people opposite things.
|
|
612
612
|
if (pc.channel === 'told' && actor !== undefined && Array.isArray(pc.reports)) {
|
|
@@ -724,8 +724,11 @@ function perceiveOne(p, pc) {
|
|
|
724
724
|
summary: pc.summary,
|
|
725
725
|
tags: [pc.kind, pc.channel, ...(isNight(at) ? ['night'] : []), ...(threat ? ['threat'] : [])],
|
|
726
726
|
};
|
|
727
|
-
if (actor !== undefined)
|
|
727
|
+
if (actor !== undefined) {
|
|
728
728
|
episode.actorId = actor;
|
|
729
|
+
if (pc.addressedSummary !== undefined)
|
|
730
|
+
episode.addressedSummary = pc.addressedSummary;
|
|
731
|
+
}
|
|
729
732
|
if (target !== undefined)
|
|
730
733
|
episode.targetId = target;
|
|
731
734
|
if (pc.placeId !== undefined)
|
|
@@ -748,7 +751,7 @@ function judgeDeed(p, actor, pc, at) {
|
|
|
748
751
|
* into relationships, others' acts judged by my norms, appraisal into emotions, and an episode each.
|
|
749
752
|
* Returns the percepts that were attended to.
|
|
750
753
|
*/
|
|
751
|
-
export function perceive(p, percepts) {
|
|
754
|
+
export function perceive(p, percepts, options = {}) {
|
|
752
755
|
if (percepts.length === 0 || !p.body.alive)
|
|
753
756
|
return [];
|
|
754
757
|
const body = readBodyOf(p);
|
|
@@ -758,7 +761,7 @@ export function perceive(p, percepts) {
|
|
|
758
761
|
fear: emotionLevel(p, 'fear'),
|
|
759
762
|
});
|
|
760
763
|
for (const pc of attended) {
|
|
761
|
-
perceiveOne(p, pc);
|
|
764
|
+
perceiveOne(p, pc, options);
|
|
762
765
|
// What I just noticed may bring a memory back (the cemetery road, her name on the phone).
|
|
763
766
|
const at = Math.min(Math.max(pc.at, p.affect.lastUpdated), p.now);
|
|
764
767
|
const cue = { at, action: pc.kind, tags: [pc.kind] };
|
|
@@ -1449,8 +1452,10 @@ export function finish(p, outcome, opts = {}) {
|
|
|
1449
1452
|
...(act.necessity ? { necessity: true } : {}),
|
|
1450
1453
|
...(opts.catalog ? { catalog: opts.catalog } : {}),
|
|
1451
1454
|
});
|
|
1452
|
-
if (p.projects)
|
|
1455
|
+
if (p.projects) {
|
|
1456
|
+
noteProjectAct(p, aff, completed, now);
|
|
1453
1457
|
noteProjectStatus(p, now);
|
|
1458
|
+
}
|
|
1454
1459
|
if (p.pursuit)
|
|
1455
1460
|
releasePursuit(p);
|
|
1456
1461
|
// A completed violating action inside an open abstention's window broke it (the fast, e.g. "no work after the evening prayer").
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { type PersonaAdmission, type PersonaAdmissionResult, type PersonaProjection, type PersonaProjectionSnapshot } from './persona.ts';
|
|
2
|
+
import { type Commitment, type HeldNorm, type NormDefinition, type OwedMakeUp, type Person } from './types.ts';
|
|
3
|
+
export interface PersonaCalendarMap {
|
|
4
|
+
version: 'hf-persona-calendar-map/1';
|
|
5
|
+
/** Exactly target opening minus source departure. All retained calendar timestamps use this offset. */
|
|
6
|
+
offset: number;
|
|
7
|
+
references: {
|
|
8
|
+
commitments: Record<string, string>;
|
|
9
|
+
chains: Record<string, string>;
|
|
10
|
+
actions: Record<string, string>;
|
|
11
|
+
entities: Record<string, string>;
|
|
12
|
+
norms: Record<string, string>;
|
|
13
|
+
};
|
|
14
|
+
sourceNorms: NormDefinition[];
|
|
15
|
+
}
|
|
16
|
+
export interface CalendarPersonaProjection extends Omit<PersonaProjection, 'commitments'> {
|
|
17
|
+
calendar: PersonaCalendarMap;
|
|
18
|
+
}
|
|
19
|
+
export interface CalendarPersonaSnapshot {
|
|
20
|
+
format: 'hf-persona-calendar/1';
|
|
21
|
+
person: PersonaProjectionSnapshot;
|
|
22
|
+
calendar: {
|
|
23
|
+
offset: number;
|
|
24
|
+
commitments: Commitment[];
|
|
25
|
+
owed: OwedMakeUp[];
|
|
26
|
+
lapse: Person['agenda']['lapse'] | null;
|
|
27
|
+
heldNorms: HeldNorm[];
|
|
28
|
+
norms: NormDefinition[];
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
export interface CalendarPersonaAdmission extends PersonaAdmission {
|
|
32
|
+
targetNorms: NormDefinition[];
|
|
33
|
+
}
|
|
34
|
+
/** Validate portable calendar data strictly; no restore defaults or debt settlement. */
|
|
35
|
+
export declare function validateCalendarPersona(input: unknown): CalendarPersonaSnapshot;
|
|
36
|
+
/** Source declares a complete semantic ID map, a clock offset and source-backed norm catalog. */
|
|
37
|
+
export declare function projectCalendarPersona(source: Person, mapping: CalendarPersonaProjection): CalendarPersonaSnapshot;
|
|
38
|
+
/** Receiver declares identical norm meanings and a clean calendar at the exact declared opening clock. */
|
|
39
|
+
export declare function admitCalendarPersona(input: unknown, target: Person, policy: CalendarPersonaAdmission): PersonaAdmissionResult;
|