@haaaiawd/second-nature 0.2.2 → 0.2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/openclaw.plugin.json +1 -1
  2. package/package.json +1 -1
  3. package/runtime/cli/ops/heartbeat-surface.d.ts +20 -0
  4. package/runtime/cli/ops/heartbeat-surface.js +72 -1
  5. package/runtime/cli/ops/ops-router.js +115 -31
  6. package/runtime/connectors/base/contract.d.ts +10 -0
  7. package/runtime/connectors/base/policy-bound-write-dispatch.d.ts +29 -0
  8. package/runtime/connectors/base/policy-bound-write-dispatch.js +127 -0
  9. package/runtime/core/second-nature/control-plane/heartbeat-orchestrator.js +336 -25
  10. package/runtime/core/second-nature/control-plane/real-runtime-spine.d.ts +33 -0
  11. package/runtime/core/second-nature/control-plane/real-runtime-spine.js +41 -0
  12. package/runtime/core/second-nature/guidance/impulse-context-reader.d.ts +44 -0
  13. package/runtime/core/second-nature/guidance/impulse-context-reader.js +84 -0
  14. package/runtime/core/second-nature/guidance/impulse-context-writer.d.ts +39 -0
  15. package/runtime/core/second-nature/guidance/impulse-context-writer.js +70 -0
  16. package/runtime/core/second-nature/perception/judgment-engine.d.ts +2 -0
  17. package/runtime/core/second-nature/perception/judgment-engine.js +11 -1
  18. package/runtime/core/second-nature/perception/perception-builder.d.ts +6 -2
  19. package/runtime/core/second-nature/perception/perception-builder.js +18 -7
  20. package/runtime/core/second-nature/quiet-dream/daily-rhythm-scheduler.d.ts +43 -0
  21. package/runtime/core/second-nature/quiet-dream/daily-rhythm-scheduler.js +157 -0
  22. package/runtime/core/second-nature/quiet-dream/memory-projection-lifecycle.js +17 -16
  23. package/runtime/core/second-nature/quiet-dream/quiet-daily-review-builder.d.ts +3 -0
  24. package/runtime/core/second-nature/quiet-dream/quiet-daily-review-builder.js +4 -0
  25. package/runtime/observability/living-loop-health-gate.d.ts +45 -0
  26. package/runtime/observability/living-loop-health-gate.js +94 -0
  27. package/runtime/observability/loop-status.d.ts +11 -0
  28. package/runtime/observability/loop-status.js +49 -3
  29. package/runtime/observability/services/heartbeat-digest-assembler.d.ts +12 -0
  30. package/runtime/observability/services/heartbeat-digest-assembler.js +9 -0
  31. package/runtime/shared/types/v8-contracts.d.ts +2 -2
  32. package/runtime/storage/db/index.js +34 -0
  33. package/runtime/storage/db/migrations/index.js +4 -0
  34. package/runtime/storage/db/migrations/v8-001-living-perception-loop.js +119 -119
  35. package/runtime/storage/db/migrations/v8-002-perception-contract-alignment.d.ts +12 -0
  36. package/runtime/storage/db/migrations/v8-002-perception-contract-alignment.js +14 -0
  37. package/runtime/storage/db/migrations/v8-003-quiet-closure-refs.d.ts +10 -0
  38. package/runtime/storage/db/migrations/v8-003-quiet-closure-refs.js +12 -0
  39. package/runtime/storage/db/schema/v8-entities.d.ts +586 -0
  40. package/runtime/storage/db/schema/v8-entities.js +39 -0
  41. package/runtime/storage/v8-state-stores.d.ts +32 -2
  42. package/runtime/storage/v8-state-stores.js +121 -2
@@ -22,7 +22,7 @@
22
22
  * Test coverage: tests/unit/storage/v8-state-stores.test.ts
23
23
  */
24
24
  import type { StateDatabase } from "./db/index.js";
25
- import { type EvidenceItemRecord, type NewEvidenceItemRecord, type PerceptionCardRecord, type NewPerceptionCardRecord, type JudgmentVerdictRecord, type NewJudgmentVerdictRecord, type ActionClosureRecordSelect, type ActionClosureRecordInsert, type QuietDailyReviewRecord, type NewQuietDailyReviewRecord, type DreamConsolidationRunRecord, type NewDreamConsolidationRunRecord, type LongTermMemoryProjectionRecord, type NewLongTermMemoryProjectionRecord, type HeartbeatCycleTraceRecord, type NewHeartbeatCycleTraceRecord, type LoopStageEventRecord, type NewLoopStageEventRecord } from "./db/schema/v8-entities.js";
25
+ import { type EvidenceItemRecord, type NewEvidenceItemRecord, type PerceptionCardRecord, type NewPerceptionCardRecord, type JudgmentVerdictRecord, type NewJudgmentVerdictRecord, type ActionClosureRecordSelect, type ActionClosureRecordInsert, type QuietDailyReviewRecord, type NewQuietDailyReviewRecord, type DreamConsolidationRunRecord, type NewDreamConsolidationRunRecord, type LongTermMemoryProjectionRecord, type NewLongTermMemoryProjectionRecord, type HeartbeatCycleTraceRecord, type NewHeartbeatCycleTraceRecord, type LoopStageEventRecord, type NewLoopStageEventRecord, type ImpulseContextArtifactRecord, type NewImpulseContextArtifactRecord, type DailyRhythmStateRecord, type NewDailyRhythmStateRecord } from "./db/schema/v8-entities.js";
26
26
  import type { SourceRef, DegradedOperationResult } from "../shared/types/v8-contracts.js";
27
27
  export interface WriteValidationError {
28
28
  ok: false;
@@ -81,8 +81,9 @@ export declare function readActionClosuresByDay(db: StateDatabase, day: string):
81
81
  rows: ActionClosureRecordSelect[];
82
82
  degraded?: DegradedOperationResult;
83
83
  }>;
84
- export declare function writeQuietDailyReview(db: StateDatabase, row: Omit<NewQuietDailyReviewRecord, "sourceRefsJson"> & {
84
+ export declare function writeQuietDailyReview(db: StateDatabase, row: Omit<NewQuietDailyReviewRecord, "sourceRefsJson" | "closureRefsJson"> & {
85
85
  sourceRefs: SourceRef[];
86
+ closureRefs?: SourceRef[];
86
87
  }): Promise<{
87
88
  id: string;
88
89
  } | DegradedOperationResult>;
@@ -112,6 +113,13 @@ export declare function writeLongTermMemoryProjection(db: StateDatabase, row: Om
112
113
  }): Promise<{
113
114
  id: string;
114
115
  } | DegradedOperationResult>;
116
+ /**
117
+ * Update an existing projection's status — required for supersession lifecycle.
118
+ * Uses UPDATE instead of INSERT to avoid primary-key conflict.
119
+ */
120
+ export declare function updateLongTermMemoryProjectionStatus(db: StateDatabase, id: string, status: LongTermMemoryProjectionRecord["status"], payloadJson?: string): Promise<{
121
+ id: string;
122
+ } | DegradedOperationResult>;
115
123
  export declare function readMemoryProjectionsByStatus(db: StateDatabase, status: LongTermMemoryProjectionRecord["status"]): Promise<{
116
124
  rows: LongTermMemoryProjectionRecord[];
117
125
  degraded?: DegradedOperationResult;
@@ -120,6 +128,10 @@ export declare function readMemoryProjectionsByTopic(db: StateDatabase, topicKey
120
128
  rows: LongTermMemoryProjectionRecord[];
121
129
  degraded?: DegradedOperationResult;
122
130
  }>;
131
+ export declare function readLongTermMemoryProjectionById(db: StateDatabase, id: string): Promise<{
132
+ row?: LongTermMemoryProjectionRecord;
133
+ degraded?: DegradedOperationResult;
134
+ }>;
123
135
  export declare function writeHeartbeatCycleTrace(db: StateDatabase, row: Omit<NewHeartbeatCycleTraceRecord, "sourceRefsJson"> & {
124
136
  sourceRefs?: SourceRef[];
125
137
  }): Promise<{
@@ -142,6 +154,24 @@ export declare function readLoopStageEventsByStage(db: StateDatabase, stage: Loo
142
154
  rows: LoopStageEventRecord[];
143
155
  degraded?: DegradedOperationResult;
144
156
  }>;
157
+ export declare function writeImpulseContextArtifact(db: StateDatabase, row: Omit<NewImpulseContextArtifactRecord, "sourceRefsJson"> & {
158
+ sourceRefs: SourceRef[];
159
+ }): Promise<{
160
+ id: string;
161
+ } | DegradedOperationResult>;
162
+ export declare function readImpulseContextArtifact(db: StateDatabase, sceneType: string, capabilityIntent?: string, platformId?: string): Promise<{
163
+ row?: ImpulseContextArtifactRecord;
164
+ degraded?: DegradedOperationResult;
165
+ }>;
166
+ export declare function writeDailyRhythmState(db: StateDatabase, row: Omit<NewDailyRhythmStateRecord, "sourceRefsJson"> & {
167
+ sourceRefs: SourceRef[];
168
+ }): Promise<{
169
+ id: string;
170
+ } | DegradedOperationResult>;
171
+ export declare function readDailyRhythmStateByDay(db: StateDatabase, day: string): Promise<{
172
+ row?: DailyRhythmStateRecord;
173
+ degraded?: DegradedOperationResult;
174
+ }>;
145
175
  export declare function extractSourceRefs(row: {
146
176
  sourceRefsJson: string | null;
147
177
  }): SourceRef[];
@@ -21,8 +21,8 @@
21
21
  *
22
22
  * Test coverage: tests/unit/storage/v8-state-stores.test.ts
23
23
  */
24
- import { eq, desc, like } from "drizzle-orm";
25
- import { evidenceItem, perceptionCard, judgmentVerdict, actionClosureRecord, quietDailyReview, dreamConsolidationRun, longTermMemoryProjection, heartbeatCycleTrace, loopStageEvent, } from "./db/schema/v8-entities.js";
24
+ import { eq, and, desc, like, isNull } from "drizzle-orm";
25
+ import { evidenceItem, perceptionCard, judgmentVerdict, actionClosureRecord, quietDailyReview, dreamConsolidationRun, longTermMemoryProjection, heartbeatCycleTrace, loopStageEvent, impulseContextArtifact, dailyRhythmState, } from "./db/schema/v8-entities.js";
26
26
  // ───────────────────────────────────────────────────────────────
27
27
  // Shared helpers
28
28
  // ───────────────────────────────────────────────────────────────
@@ -258,6 +258,7 @@ export async function writeQuietDailyReview(db, row) {
258
258
  const record = {
259
259
  ...row,
260
260
  sourceRefsJson: serializeSourceRefs(validated.record),
261
+ closureRefsJson: row.closureRefs ? serializeSourceRefs(row.closureRefs) : null,
261
262
  };
262
263
  await db.db.insert(quietDailyReview).values(record);
263
264
  return { id: row.id };
@@ -366,6 +367,23 @@ export async function writeLongTermMemoryProjection(db, row) {
366
367
  return makeDegraded("state_unreadable", "projection", "Retry projection write after DB recovery", validated.record);
367
368
  }
368
369
  }
370
+ /**
371
+ * Update an existing projection's status — required for supersession lifecycle.
372
+ * Uses UPDATE instead of INSERT to avoid primary-key conflict.
373
+ */
374
+ export async function updateLongTermMemoryProjectionStatus(db, id, status, payloadJson) {
375
+ try {
376
+ const updateData = { status, lifecycleStatus: status };
377
+ if (payloadJson !== undefined) {
378
+ updateData.payloadJson = payloadJson;
379
+ }
380
+ await db.db.update(longTermMemoryProjection).set(updateData).where(eq(longTermMemoryProjection.id, id));
381
+ return { id };
382
+ }
383
+ catch {
384
+ return makeDegraded("state_unreadable", "projection", `Retry projection status update for ${id} after DB recovery`);
385
+ }
386
+ }
369
387
  export async function readMemoryProjectionsByStatus(db, status) {
370
388
  try {
371
389
  const rows = await db.db
@@ -398,6 +416,21 @@ export async function readMemoryProjectionsByTopic(db, topicKey) {
398
416
  };
399
417
  }
400
418
  }
419
+ export async function readLongTermMemoryProjectionById(db, id) {
420
+ try {
421
+ const rows = await db.db
422
+ .select()
423
+ .from(longTermMemoryProjection)
424
+ .where(eq(longTermMemoryProjection.id, id))
425
+ .limit(1);
426
+ return { row: rows[0] };
427
+ }
428
+ catch {
429
+ return {
430
+ degraded: makeDegraded("state_unreadable", "projection", `Check state database connectivity for projection ${id}`),
431
+ };
432
+ }
433
+ }
401
434
  // ───────────────────────────────────────────────────────────────
402
435
  // HeartbeatCycleTrace store
403
436
  // ───────────────────────────────────────────────────────────────
@@ -484,6 +517,92 @@ export async function readLoopStageEventsByStage(db, stage, limit = 100) {
484
517
  }
485
518
  }
486
519
  // ───────────────────────────────────────────────────────────────
520
+ // ImpulseContextArtifact store
521
+ // ───────────────────────────────────────────────────────────────
522
+ export async function writeImpulseContextArtifact(db, row) {
523
+ const validated = validateSourceRefs(row.sourceRefs, "projection");
524
+ if (!validated.ok)
525
+ return validated.degraded;
526
+ try {
527
+ const record = {
528
+ ...row,
529
+ sourceRefsJson: serializeSourceRefs(validated.record),
530
+ };
531
+ // Upsert: delete existing then insert (SQLite primary-key conflict)
532
+ await db.db.delete(impulseContextArtifact).where(eq(impulseContextArtifact.id, row.id));
533
+ await db.db.insert(impulseContextArtifact).values(record);
534
+ return { id: row.id };
535
+ }
536
+ catch {
537
+ return makeDegraded("state_unreadable", "projection", "Retry impulse context write after DB recovery", validated.record);
538
+ }
539
+ }
540
+ export async function readImpulseContextArtifact(db, sceneType, capabilityIntent, platformId) {
541
+ try {
542
+ const conditions = [eq(impulseContextArtifact.sceneType, sceneType)];
543
+ if (capabilityIntent) {
544
+ conditions.push(eq(impulseContextArtifact.capabilityIntent, capabilityIntent));
545
+ }
546
+ else {
547
+ conditions.push(isNull(impulseContextArtifact.capabilityIntent));
548
+ }
549
+ if (platformId) {
550
+ conditions.push(eq(impulseContextArtifact.platformId, platformId));
551
+ }
552
+ else {
553
+ conditions.push(isNull(impulseContextArtifact.platformId));
554
+ }
555
+ const rows = await db.db
556
+ .select()
557
+ .from(impulseContextArtifact)
558
+ .where(and(...conditions))
559
+ .orderBy(desc(impulseContextArtifact.updatedAt))
560
+ .limit(1);
561
+ return { row: rows[0] };
562
+ }
563
+ catch {
564
+ return {
565
+ degraded: makeDegraded("state_unreadable", "projection", "Check state database connectivity"),
566
+ };
567
+ }
568
+ }
569
+ // ───────────────────────────────────────────────────────────────
570
+ // DailyRhythmState store
571
+ // ───────────────────────────────────────────────────────────────
572
+ export async function writeDailyRhythmState(db, row) {
573
+ const validated = validateSourceRefs(row.sourceRefs, "dream");
574
+ if (!validated.ok)
575
+ return validated.degraded;
576
+ try {
577
+ const record = {
578
+ ...row,
579
+ sourceRefsJson: serializeSourceRefs(validated.record),
580
+ };
581
+ await db.db.delete(dailyRhythmState).where(eq(dailyRhythmState.id, row.id));
582
+ await db.db.insert(dailyRhythmState).values(record);
583
+ return { id: row.id };
584
+ }
585
+ catch {
586
+ return makeDegraded("state_unreadable", "dream", "Retry daily rhythm state write after DB recovery", validated.record);
587
+ }
588
+ }
589
+ export async function readDailyRhythmStateByDay(db, day) {
590
+ try {
591
+ const rows = await db.db
592
+ .select()
593
+ .from(dailyRhythmState)
594
+ .where(eq(dailyRhythmState.day, day))
595
+ .orderBy(desc(dailyRhythmState.updatedAt))
596
+ .limit(1);
597
+ return { row: rows[0] };
598
+ }
599
+ catch {
600
+ return {
601
+ degraded: makeDegraded("state_unreadable", "dream", `Check state database connectivity for day=${day}`),
602
+ };
603
+ }
604
+ }
605
+ // ───────────────────────────────────────────────────────────────
487
606
  // SourceRef round-trip helper (for tests and consumers)
488
607
  // ───────────────────────────────────────────────────────────────
489
608
  export function extractSourceRefs(row) {