@medicine-wheel/narrative-engine 0.2.2

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.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rsis-narrative.d.ts","sourceRoot":"","sources":["../src/rsis-narrative.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EACV,aAAa,EACb,oBAAoB,EAEpB,qBAAqB,EACrB,OAAO,EACR,MAAM,+BAA+B,CAAC;AAGvC;;GAEG;AACH,wBAAgB,2BAA2B,CACzC,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,oBAAoB,EAAE,EAC/B,SAAS,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,EAClC,QAAQ,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,GAChC,MAAM,CAoBR;AAED;;GAEG;AACH,wBAAgB,8BAA8B,CAC5C,YAAY,EAAE,MAAM,EACpB,SAAS,EAAE,MAAM,GAChB,MAAM,CAYR;AAMD;;GAEG;AACH,wBAAgB,4BAA4B,CAC1C,YAAY,EAAE,qBAAqB,EACnC,KAAK,EAAE,MAAM,GACZ,MAAM,CAUR;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,CAAC,EAAE,aAAa,GAAG,MAAM,CAarE;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAEhD"}
@@ -0,0 +1,95 @@
1
+ "use strict";
2
+ /**
3
+ * @medicine-wheel/narrative-engine β€” RSIS Narrative Generators
4
+ *
5
+ * Produces ceremony-phase-aware provenance stories, reciprocity
6
+ * narratives, and directional observations for RSIS tool outputs.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.generateProvenanceNarrative = generateProvenanceNarrative;
10
+ exports.generateReciprocityObservation = generateReciprocityObservation;
11
+ exports.generateDirectionObservation = generateDirectionObservation;
12
+ exports.getCeremonyPhaseFraming = getCeremonyPhaseFraming;
13
+ exports.describeSun = describeSun;
14
+ const ontology_core_1 = require("@medicine-wheel/ontology-core");
15
+ /**
16
+ * Generate a human-readable provenance narrative for a code artifact
17
+ */
18
+ function generateProvenanceNarrative(symbolName, lineage, inquiries, stewards) {
19
+ let narrative = `"${symbolName}" `;
20
+ if (lineage.length > 0) {
21
+ const first = lineage[0];
22
+ narrative += `was born in the ${first.sun || 'Unknown'} Sun during cycle ${first.cycle || 'unknown'}`;
23
+ if (lineage.length > 1) {
24
+ const last = lineage[lineage.length - 1];
25
+ narrative += `, most recently touched under ${last.sun || 'Unknown'} during cycle ${last.cycle || 'unknown'}`;
26
+ }
27
+ narrative += '.';
28
+ }
29
+ else {
30
+ narrative += 'has no recorded ceremonial lineage yet.';
31
+ }
32
+ if (inquiries.length > 0) {
33
+ narrative += ` It serves ${inquiries.length} ${inquiries.length === 1 ? 'inquiry' : 'inquiries'}: ${inquiries.map(i => i.name).join(', ')}.`;
34
+ }
35
+ if (stewards.length > 0) {
36
+ narrative += ` Stewarded by: ${stewards.map(s => s.name).join(', ')}.`;
37
+ }
38
+ return narrative;
39
+ }
40
+ /**
41
+ * Generate a reciprocity observation β€” always invitational, never evaluative
42
+ */
43
+ function generateReciprocityObservation(stewardCount, flowCount) {
44
+ const parts = [];
45
+ if (flowCount === 0 && stewardCount === 0) {
46
+ return 'No reciprocity data has been populated yet. Consider running rsis-gitnexus analyze with RSIS mode enabled.';
47
+ }
48
+ if (stewardCount > 0) {
49
+ parts.push(`${stewardCount} steward(s) identified. This area invites reflection on how stewardship is distributed.`);
50
+ }
51
+ if (flowCount > 0) {
52
+ parts.push(`${flowCount} reciprocity flow(s) identified. This area invites reflection on how contributions move.`);
53
+ }
54
+ return parts.join(' ');
55
+ }
56
+ const DIRECTION_EMOJI = {
57
+ east: '🌸', south: '🧠', west: '⚑', north: 'πŸ•ΈοΈ',
58
+ };
59
+ /**
60
+ * Generate a natural language observation about directional balance
61
+ */
62
+ function generateDirectionObservation(distribution, total) {
63
+ if (total === 0)
64
+ return 'No recent changes to analyze.';
65
+ const entries = Object.entries(distribution);
66
+ const sorted = entries.sort((a, b) => b[1] - a[1]);
67
+ const dominant = sorted[0][0];
68
+ const weakest = sorted[sorted.length - 1][0];
69
+ return `Recent work is concentrated in ${dominant} ${DIRECTION_EMOJI[dominant]} (${distribution[dominant]}%). ` +
70
+ `The ecosystem may benefit from a ${weakest} ${DIRECTION_EMOJI[weakest]} ceremony.`;
71
+ }
72
+ /**
73
+ * Get ceremony-phase-aware framing for tool output
74
+ */
75
+ function getCeremonyPhaseFraming(phase) {
76
+ switch (phase) {
77
+ case 'opening':
78
+ return 'Opening Phase β€” What wants to emerge? Focus on intention and vision.';
79
+ case 'council':
80
+ return 'Council Phase β€” Cross-Sun perspectives on code relationships.';
81
+ case 'integration':
82
+ return 'Integration Phase β€” Weaving insights into synthesis artifacts.';
83
+ case 'closure':
84
+ return 'Closure Phase β€” Reciprocity summaries and seeding observations.';
85
+ default:
86
+ return '';
87
+ }
88
+ }
89
+ /**
90
+ * Describe a Thematic Sun
91
+ */
92
+ function describeSun(sun) {
93
+ return ontology_core_1.SUN_DESCRIPTIONS[sun] || sun;
94
+ }
95
+ //# sourceMappingURL=rsis-narrative.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rsis-narrative.js","sourceRoot":"","sources":["../src/rsis-narrative.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Beat Sequencer β€” orders and validates narrative beats
3
+ * across the four-direction, four-act structure.
4
+ */
5
+ import type { NarrativeBeat, DirectionName } from '@medicine-wheel/ontology-core';
6
+ import type { BeatPosition, BeatInsertResult, SequencerOptions } from './types.js';
7
+ /** Map beats to their position metadata */
8
+ export declare function sequenceBeats(beats: NarrativeBeat[]): BeatPosition[];
9
+ /** Insert a beat into an existing sequence */
10
+ export declare function insertBeat(beats: NarrativeBeat[], newBeat: NarrativeBeat, opts?: SequencerOptions): BeatInsertResult;
11
+ /** Get beats grouped by direction */
12
+ export declare function beatsByDirection(beats: NarrativeBeat[]): Record<DirectionName, NarrativeBeat[]>;
13
+ /** Get the next expected direction in a cycle */
14
+ export declare function nextDirection(beats: NarrativeBeat[]): DirectionName | null;
15
+ /** Get the current act based on the latest beat */
16
+ export declare function currentAct(beats: NarrativeBeat[]): number;
17
+ /** Suggest the next beat's direction and act */
18
+ export declare function suggestNextBeat(beats: NarrativeBeat[]): {
19
+ direction: DirectionName;
20
+ act: number;
21
+ };
22
+ /** Reorder beats by direction spiral (east→south→west→north within each act) */
23
+ export declare function spiralOrder(beats: NarrativeBeat[]): NarrativeBeat[];
24
+ /**
25
+ * Analyse whether later beats show genuine epistemic deepening vs repetition.
26
+ *
27
+ * Deepening is detected when:
28
+ * - Learnings accumulate and diversify across beats
29
+ * - Later beats reference or build upon earlier learnings
30
+ * - New directions are visited in subsequent cycles
31
+ *
32
+ * Stagnation is flagged when:
33
+ * - Learnings stop growing
34
+ * - The same directions repeat without new content
35
+ */
36
+ export declare function detectEpistemicDeepening(beats: NarrativeBeat[]): {
37
+ circleCount: number;
38
+ deepeningIndicators: string[];
39
+ stagnationRisk: boolean;
40
+ };
41
+ /**
42
+ * Identify beats where understanding visibly shifted.
43
+ *
44
+ * A transformation point is a beat where:
45
+ * - New learnings appear that were absent in all prior beats
46
+ * - A direction transition occurs (ceremony boundary)
47
+ * - The beat carries ceremonies (indicating intentional shift)
48
+ */
49
+ export declare function findTransformationPoints(beats: NarrativeBeat[]): Array<{
50
+ beatId: string;
51
+ beforeUnderstanding: string;
52
+ afterUnderstanding: string;
53
+ catalyst: string;
54
+ }>;
55
+ //# sourceMappingURL=sequencer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sequencer.d.ts","sourceRoot":"","sources":["../src/sequencer.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAElF,OAAO,KAAK,EAAE,YAAY,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAUnF,2CAA2C;AAC3C,wBAAgB,aAAa,CAAC,KAAK,EAAE,aAAa,EAAE,GAAG,YAAY,EAAE,CAapE;AAED,8CAA8C;AAC9C,wBAAgB,UAAU,CACxB,KAAK,EAAE,aAAa,EAAE,EACtB,OAAO,EAAE,aAAa,EACtB,IAAI,GAAE,gBAAqB,GAC1B,gBAAgB,CA0ClB;AAED,qCAAqC;AACrC,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,aAAa,EAAE,GAAG,MAAM,CAAC,aAAa,EAAE,aAAa,EAAE,CAAC,CAQ/F;AAED,iDAAiD;AACjD,wBAAgB,aAAa,CAAC,KAAK,EAAE,aAAa,EAAE,GAAG,aAAa,GAAG,IAAI,CAQ1E;AAED,mDAAmD;AACnD,wBAAgB,UAAU,CAAC,KAAK,EAAE,aAAa,EAAE,GAAG,MAAM,CAGzD;AAED,gDAAgD;AAChD,wBAAgB,eAAe,CAAC,KAAK,EAAE,aAAa,EAAE,GAAG;IAAE,SAAS,EAAE,aAAa,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAOjG;AAED,gFAAgF;AAChF,wBAAgB,WAAW,CAAC,KAAK,EAAE,aAAa,EAAE,GAAG,aAAa,EAAE,CAQnE;AAID;;;;;;;;;;;GAWG;AACH,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,aAAa,EAAE,GAAG;IAChE,WAAW,EAAE,MAAM,CAAC;IACpB,mBAAmB,EAAE,MAAM,EAAE,CAAC;IAC9B,cAAc,EAAE,OAAO,CAAC;CACzB,CAyDA;AAED;;;;;;;GAOG;AACH,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,aAAa,EAAE,GAAG,KAAK,CAAC;IACtE,MAAM,EAAE,MAAM,CAAC;IACf,mBAAmB,EAAE,MAAM,CAAC;IAC5B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC,CAwCD"}
@@ -0,0 +1,223 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.sequenceBeats = sequenceBeats;
4
+ exports.insertBeat = insertBeat;
5
+ exports.beatsByDirection = beatsByDirection;
6
+ exports.nextDirection = nextDirection;
7
+ exports.currentAct = currentAct;
8
+ exports.suggestNextBeat = suggestNextBeat;
9
+ exports.spiralOrder = spiralOrder;
10
+ exports.detectEpistemicDeepening = detectEpistemicDeepening;
11
+ exports.findTransformationPoints = findTransformationPoints;
12
+ const ontology_core_1 = require("@medicine-wheel/ontology-core");
13
+ const DIRECTION_ORDER = ['east', 'south', 'west', 'north'];
14
+ const DEFAULT_OPTIONS = {
15
+ enforceDirectionOrder: false,
16
+ allowMultiplePerAct: true,
17
+ maxBeatsPerDirection: 12,
18
+ };
19
+ /** Map beats to their position metadata */
20
+ function sequenceBeats(beats) {
21
+ const sorted = [...beats].sort((a, b) => {
22
+ const actDiff = a.act - b.act;
23
+ if (actDiff !== 0)
24
+ return actDiff;
25
+ return a.timestamp.localeCompare(b.timestamp);
26
+ });
27
+ return sorted.map((beat, index) => ({
28
+ beat,
29
+ index,
30
+ direction: beat.direction,
31
+ act: beat.act,
32
+ }));
33
+ }
34
+ /** Insert a beat into an existing sequence */
35
+ function insertBeat(beats, newBeat, opts = {}) {
36
+ const options = { ...DEFAULT_OPTIONS, ...opts };
37
+ const warnings = [];
38
+ // Check max beats per direction
39
+ const directionCount = beats.filter(b => b.direction === newBeat.direction).length;
40
+ if (directionCount >= options.maxBeatsPerDirection) {
41
+ return {
42
+ success: false,
43
+ positions: sequenceBeats(beats),
44
+ warnings: [`Direction '${newBeat.direction}' already has ${directionCount} beats (max: ${options.maxBeatsPerDirection})`],
45
+ };
46
+ }
47
+ // Check multiple per act
48
+ if (!options.allowMultiplePerAct) {
49
+ const existingInAct = beats.find(b => b.act === newBeat.act && b.direction === newBeat.direction);
50
+ if (existingInAct) {
51
+ return {
52
+ success: false,
53
+ positions: sequenceBeats(beats),
54
+ warnings: [`Act ${newBeat.act} in direction '${newBeat.direction}' already has a beat`],
55
+ };
56
+ }
57
+ }
58
+ // Check direction order enforcement
59
+ if (options.enforceDirectionOrder && beats.length > 0) {
60
+ const lastBeat = beats[beats.length - 1];
61
+ const lastIdx = DIRECTION_ORDER.indexOf(lastBeat.direction);
62
+ const newIdx = DIRECTION_ORDER.indexOf(newBeat.direction);
63
+ if (newIdx < lastIdx) {
64
+ warnings.push(`Beat in '${newBeat.direction}' precedes the latest '${lastBeat.direction}' β€” direction order not enforced`);
65
+ }
66
+ }
67
+ const updated = [...beats, newBeat];
68
+ return {
69
+ success: true,
70
+ positions: sequenceBeats(updated),
71
+ warnings,
72
+ };
73
+ }
74
+ /** Get beats grouped by direction */
75
+ function beatsByDirection(beats) {
76
+ const result = {
77
+ east: [], south: [], west: [], north: [],
78
+ };
79
+ for (const beat of beats) {
80
+ result[beat.direction].push(beat);
81
+ }
82
+ return result;
83
+ }
84
+ /** Get the next expected direction in a cycle */
85
+ function nextDirection(beats) {
86
+ if (beats.length === 0)
87
+ return 'east';
88
+ const visited = new Set(beats.map(b => b.direction));
89
+ for (const dir of DIRECTION_ORDER) {
90
+ if (!visited.has(dir))
91
+ return dir;
92
+ }
93
+ return null; // all directions visited
94
+ }
95
+ /** Get the current act based on the latest beat */
96
+ function currentAct(beats) {
97
+ if (beats.length === 0)
98
+ return 1;
99
+ return Math.max(...beats.map(b => b.act));
100
+ }
101
+ /** Suggest the next beat's direction and act */
102
+ function suggestNextBeat(beats) {
103
+ const next = nextDirection(beats);
104
+ if (next) {
105
+ return { direction: next, act: ontology_core_1.DIRECTION_ACTS[next] };
106
+ }
107
+ // All directions visited β€” advance to next cycle by restarting at east
108
+ return { direction: 'east', act: 1 };
109
+ }
110
+ /** Reorder beats by direction spiral (east→south→west→north within each act) */
111
+ function spiralOrder(beats) {
112
+ return [...beats].sort((a, b) => {
113
+ const actDiff = a.act - b.act;
114
+ if (actDiff !== 0)
115
+ return actDiff;
116
+ const dirDiff = DIRECTION_ORDER.indexOf(a.direction) - DIRECTION_ORDER.indexOf(b.direction);
117
+ if (dirDiff !== 0)
118
+ return dirDiff;
119
+ return a.timestamp.localeCompare(b.timestamp);
120
+ });
121
+ }
122
+ // ─── Epistemic Deepening ──────────────────────────────────────
123
+ /**
124
+ * Analyse whether later beats show genuine epistemic deepening vs repetition.
125
+ *
126
+ * Deepening is detected when:
127
+ * - Learnings accumulate and diversify across beats
128
+ * - Later beats reference or build upon earlier learnings
129
+ * - New directions are visited in subsequent cycles
130
+ *
131
+ * Stagnation is flagged when:
132
+ * - Learnings stop growing
133
+ * - The same directions repeat without new content
134
+ */
135
+ function detectEpistemicDeepening(beats) {
136
+ if (beats.length === 0) {
137
+ return { circleCount: 0, deepeningIndicators: [], stagnationRisk: false };
138
+ }
139
+ const sorted = [...beats].sort((a, b) => a.timestamp.localeCompare(b.timestamp));
140
+ const indicators = [];
141
+ // Count full cycles through all four directions
142
+ let cycleDirections = new Set();
143
+ let circleCount = 0;
144
+ for (const beat of sorted) {
145
+ cycleDirections.add(beat.direction);
146
+ if (cycleDirections.size === DIRECTION_ORDER.length) {
147
+ circleCount++;
148
+ cycleDirections = new Set();
149
+ }
150
+ }
151
+ // Track learning accumulation
152
+ const cumulativeLearnings = [];
153
+ let learningsGrowing = false;
154
+ const midpoint = Math.floor(sorted.length / 2);
155
+ const firstHalfLearnings = sorted.slice(0, midpoint).flatMap(b => b.learnings);
156
+ const secondHalfLearnings = sorted.slice(midpoint).flatMap(b => b.learnings);
157
+ if (secondHalfLearnings.length > firstHalfLearnings.length) {
158
+ learningsGrowing = true;
159
+ indicators.push('Learnings are accumulating β€” later beats carry more insight');
160
+ }
161
+ // Check learning diversity
162
+ const allLearnings = sorted.flatMap(b => b.learnings);
163
+ const uniqueLearnings = new Set(allLearnings);
164
+ if (uniqueLearnings.size > allLearnings.length * 0.7) {
165
+ indicators.push('High learning diversity β€” minimal repetition of insights');
166
+ }
167
+ // Check direction coverage expansion
168
+ const firstHalfDirs = new Set(sorted.slice(0, midpoint).map(b => b.direction));
169
+ const secondHalfDirs = new Set(sorted.slice(midpoint).map(b => b.direction));
170
+ if (secondHalfDirs.size >= firstHalfDirs.size) {
171
+ indicators.push('Direction coverage maintained or expanded in later beats');
172
+ }
173
+ if (circleCount > 0) {
174
+ indicators.push(`${circleCount} full circle(s) completed through all four directions`);
175
+ }
176
+ // Stagnation: no learning growth and high repetition
177
+ const stagnationRisk = !learningsGrowing &&
178
+ beats.length > 4 &&
179
+ uniqueLearnings.size < allLearnings.length * 0.5;
180
+ return { circleCount, deepeningIndicators: indicators, stagnationRisk };
181
+ }
182
+ /**
183
+ * Identify beats where understanding visibly shifted.
184
+ *
185
+ * A transformation point is a beat where:
186
+ * - New learnings appear that were absent in all prior beats
187
+ * - A direction transition occurs (ceremony boundary)
188
+ * - The beat carries ceremonies (indicating intentional shift)
189
+ */
190
+ function findTransformationPoints(beats) {
191
+ if (beats.length < 2)
192
+ return [];
193
+ const sorted = [...beats].sort((a, b) => a.timestamp.localeCompare(b.timestamp));
194
+ const transformations = [];
195
+ const priorLearnings = new Set();
196
+ for (let i = 1; i < sorted.length; i++) {
197
+ const beat = sorted[i];
198
+ const prev = sorted[i - 1];
199
+ const newLearnings = beat.learnings.filter((l) => !priorLearnings.has(l));
200
+ const isDirectionShift = beat.direction !== prev.direction;
201
+ const hasCeremony = beat.ceremonies.length > 0;
202
+ const hasNewLearnings = newLearnings.length > 0;
203
+ if (hasNewLearnings || (isDirectionShift && hasCeremony)) {
204
+ const catalystParts = [];
205
+ if (isDirectionShift)
206
+ catalystParts.push(`direction shift (${prev.direction} β†’ ${beat.direction})`);
207
+ if (hasCeremony)
208
+ catalystParts.push('ceremony conducted');
209
+ if (hasNewLearnings)
210
+ catalystParts.push(`${newLearnings.length} new learning(s)`);
211
+ transformations.push({
212
+ beatId: beat.id,
213
+ beforeUnderstanding: prev.learnings.join('; ') || prev.title,
214
+ afterUnderstanding: beat.learnings.join('; ') || beat.title,
215
+ catalyst: catalystParts.join(', '),
216
+ });
217
+ }
218
+ for (const l of beat.learnings)
219
+ priorLearnings.add(l);
220
+ }
221
+ return transformations;
222
+ }
223
+ //# sourceMappingURL=sequencer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sequencer.js","sourceRoot":"","sources":["../src/sequencer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Timeline Builder β€” generates timeline data for visualization
3
+ * of narrative beats along chronological, directional, or ceremonial axes.
4
+ */
5
+ import type { NarrativeBeat, DirectionName } from '@medicine-wheel/ontology-core';
6
+ import type { TimelineData, TimelineOptions } from './types.js';
7
+ /** Build timeline data from narrative beats */
8
+ export declare function buildTimeline(beats: NarrativeBeat[], options?: TimelineOptions): TimelineData;
9
+ /** Get beats grouped into acts for a timeline strip view */
10
+ export declare function actStrip(beats: NarrativeBeat[]): Array<{
11
+ act: number;
12
+ direction: DirectionName;
13
+ beats: NarrativeBeat[];
14
+ hasCeremony: boolean;
15
+ }>;
16
+ //# sourceMappingURL=timeline.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"timeline.d.ts","sourceRoot":"","sources":["../src/timeline.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAElF,OAAO,KAAK,EAGV,YAAY,EAEZ,eAAe,EAChB,MAAM,YAAY,CAAC;AASpB,+CAA+C;AAC/C,wBAAgB,aAAa,CAC3B,KAAK,EAAE,aAAa,EAAE,EACtB,OAAO,GAAE,eAAoB,GAC5B,YAAY,CAyCd;AA6ED,4DAA4D;AAC5D,wBAAgB,QAAQ,CAAC,KAAK,EAAE,aAAa,EAAE,GAAG,KAAK,CAAC;IACtD,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,aAAa,CAAC;IACzB,KAAK,EAAE,aAAa,EAAE,CAAC;IACvB,WAAW,EAAE,OAAO,CAAC;CACtB,CAAC,CAWD"}
@@ -0,0 +1,131 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildTimeline = buildTimeline;
4
+ exports.actStrip = actStrip;
5
+ const ontology_core_1 = require("@medicine-wheel/ontology-core");
6
+ const DEFAULT_OPTIONS = {
7
+ axis: 'chronological',
8
+ filterDirection: undefined,
9
+ filterAct: undefined,
10
+ sortBy: 'timestamp',
11
+ };
12
+ /** Build timeline data from narrative beats */
13
+ function buildTimeline(beats, options = {}) {
14
+ const opts = { ...DEFAULT_OPTIONS, ...options };
15
+ // Filter
16
+ let filtered = [...beats];
17
+ if (opts.filterDirection) {
18
+ filtered = filtered.filter(b => b.direction === opts.filterDirection);
19
+ }
20
+ if (opts.filterAct) {
21
+ filtered = filtered.filter(b => b.act === opts.filterAct);
22
+ }
23
+ // Sort
24
+ filtered.sort((a, b) => {
25
+ switch (opts.sortBy) {
26
+ case 'act':
27
+ return a.act - b.act || a.timestamp.localeCompare(b.timestamp);
28
+ case 'direction': {
29
+ const dirOrder = ['east', 'south', 'west', 'north'];
30
+ return dirOrder.indexOf(a.direction) - dirOrder.indexOf(b.direction) || a.timestamp.localeCompare(b.timestamp);
31
+ }
32
+ default:
33
+ return a.timestamp.localeCompare(b.timestamp);
34
+ }
35
+ });
36
+ // Build entries
37
+ const span = computeSpan(filtered);
38
+ const entries = filtered.map((beat, i) => ({
39
+ beat,
40
+ position: filtered.length <= 1 ? 0.5 : i / (filtered.length - 1),
41
+ direction: beat.direction,
42
+ act: beat.act,
43
+ hasCeremony: beat.ceremonies.length > 0,
44
+ group: groupKey(beat, opts.axis),
45
+ }));
46
+ // Build groups
47
+ const groups = buildGroups(entries, opts.axis);
48
+ return { axis: opts.axis, entries, groups, span };
49
+ }
50
+ /** Compute the time span of beats */
51
+ function computeSpan(beats) {
52
+ if (beats.length === 0) {
53
+ const now = new Date().toISOString();
54
+ return { start: now, end: now };
55
+ }
56
+ const timestamps = beats.map(b => b.timestamp).sort();
57
+ return { start: timestamps[0], end: timestamps[timestamps.length - 1] };
58
+ }
59
+ /** Determine the group key for a beat */
60
+ function groupKey(beat, axis) {
61
+ switch (axis) {
62
+ case 'directional':
63
+ return beat.direction;
64
+ case 'ceremonial':
65
+ return beat.ceremonies.length > 0 ? 'with-ceremony' : 'without-ceremony';
66
+ default:
67
+ return `act-${beat.act}`;
68
+ }
69
+ }
70
+ /** Build group metadata */
71
+ function buildGroups(entries, axis) {
72
+ const groupMap = new Map();
73
+ for (const entry of entries) {
74
+ const existing = groupMap.get(entry.group) ?? [];
75
+ existing.push(entry);
76
+ groupMap.set(entry.group, existing);
77
+ }
78
+ const groups = [];
79
+ for (const [key, groupEntries] of groupMap) {
80
+ groups.push({
81
+ key,
82
+ label: groupLabel(key, axis),
83
+ color: groupColor(key, axis),
84
+ entries: groupEntries,
85
+ });
86
+ }
87
+ return groups;
88
+ }
89
+ /** Human-readable group label */
90
+ function groupLabel(key, axis) {
91
+ switch (axis) {
92
+ case 'directional':
93
+ return key.charAt(0).toUpperCase() + key.slice(1);
94
+ case 'ceremonial':
95
+ return key === 'with-ceremony' ? 'With Ceremony' : 'Without Ceremony';
96
+ default:
97
+ return `Act ${key.replace('act-', '')}`;
98
+ }
99
+ }
100
+ /** Group color */
101
+ function groupColor(key, axis) {
102
+ switch (axis) {
103
+ case 'directional':
104
+ return ontology_core_1.DIRECTION_COLORS[key] ?? '#888';
105
+ case 'ceremonial':
106
+ return key === 'with-ceremony' ? '#DC143C' : '#666';
107
+ default: {
108
+ const actColors = {
109
+ 'act-1': ontology_core_1.DIRECTION_COLORS.east,
110
+ 'act-2': ontology_core_1.DIRECTION_COLORS.south,
111
+ 'act-3': ontology_core_1.DIRECTION_COLORS.west,
112
+ 'act-4': ontology_core_1.DIRECTION_COLORS.north,
113
+ };
114
+ return actColors[key] ?? '#888';
115
+ }
116
+ }
117
+ }
118
+ /** Get beats grouped into acts for a timeline strip view */
119
+ function actStrip(beats) {
120
+ const dirOrder = ['east', 'south', 'west', 'north'];
121
+ return dirOrder.map((dir, i) => {
122
+ const actBeats = beats.filter(b => b.direction === dir);
123
+ return {
124
+ act: i + 1,
125
+ direction: dir,
126
+ beats: actBeats.sort((a, b) => a.timestamp.localeCompare(b.timestamp)),
127
+ hasCeremony: actBeats.some(b => b.ceremonies.length > 0),
128
+ };
129
+ });
130
+ }
131
+ //# sourceMappingURL=timeline.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"timeline.js","sourceRoot":"","sources":["../src/timeline.ts"],"names":[],"mappings":"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"}