@haaaiawd/second-nature 0.2.4 → 0.2.5
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/openclaw.plugin.json +1 -1
- package/package.json +1 -1
- package/runtime/cli/ops/ops-router.js +4 -0
- package/runtime/connectors/base/contract.d.ts +1 -0
- package/runtime/connectors/base/failure-taxonomy.js +45 -26
- package/runtime/connectors/services/connector-cooldown-port.d.ts +22 -0
- package/runtime/connectors/services/connector-cooldown-port.js +123 -0
- package/runtime/connectors/services/connector-executor-adapter.js +10 -4
- package/runtime/connectors/services/credential-route-context.d.ts +3 -2
- package/runtime/connectors/services/credential-route-context.js +19 -3
- package/runtime/core/second-nature/action/action-closure-recorder.d.ts +4 -0
- package/runtime/core/second-nature/action/action-closure-recorder.js +5 -0
- package/runtime/core/second-nature/action/action-proposal-builder.js +1 -0
- package/runtime/core/second-nature/control-plane/heartbeat-orchestrator.d.ts +2 -0
- package/runtime/core/second-nature/control-plane/heartbeat-orchestrator.js +76 -0
- package/runtime/core/second-nature/control-plane/real-runtime-spine.d.ts +2 -0
- package/runtime/core/second-nature/control-plane/real-runtime-spine.js +1 -0
- package/runtime/core/second-nature/quiet-dream/daily-rhythm-scheduler.d.ts +1 -1
- package/runtime/core/second-nature/quiet-dream/daily-rhythm-scheduler.js +10 -5
- package/runtime/core/second-nature/quiet-dream/memory-projection-lifecycle.d.ts +2 -2
- package/runtime/core/second-nature/quiet-dream/memory-projection-lifecycle.js +10 -28
- package/runtime/observability/living-loop-health-gate.d.ts +6 -2
- package/runtime/observability/living-loop-health-gate.js +52 -5
- package/runtime/observability/loop-status.d.ts +19 -0
- package/runtime/observability/loop-status.js +121 -7
- package/runtime/observability/services/heartbeat-digest-assembler.d.ts +9 -0
- package/runtime/observability/services/heartbeat-digest-assembler.js +44 -9
- package/runtime/shared/types/v8-contracts.d.ts +1 -1
- package/runtime/storage/db/index.js +28 -8
- package/runtime/storage/db/schema/v8-entities.d.ts +288 -0
- package/runtime/storage/db/schema/v8-entities.js +23 -1
- package/runtime/storage/v8-state-stores.d.ts +10 -1
- package/runtime/storage/v8-state-stores.js +86 -1
|
@@ -816,6 +816,44 @@ export declare const actionClosureRecord: import("drizzle-orm/sqlite-core").SQLi
|
|
|
816
816
|
}, {}, {
|
|
817
817
|
length: number | undefined;
|
|
818
818
|
}>;
|
|
819
|
+
platformId: import("drizzle-orm/sqlite-core").SQLiteColumn<{
|
|
820
|
+
name: "platform_id";
|
|
821
|
+
tableName: "action_closure_record";
|
|
822
|
+
dataType: "string";
|
|
823
|
+
columnType: "SQLiteText";
|
|
824
|
+
data: string;
|
|
825
|
+
driverParam: string;
|
|
826
|
+
notNull: false;
|
|
827
|
+
hasDefault: false;
|
|
828
|
+
isPrimaryKey: false;
|
|
829
|
+
isAutoincrement: false;
|
|
830
|
+
hasRuntimeDefault: false;
|
|
831
|
+
enumValues: [string, ...string[]];
|
|
832
|
+
baseColumn: never;
|
|
833
|
+
identity: undefined;
|
|
834
|
+
generated: undefined;
|
|
835
|
+
}, {}, {
|
|
836
|
+
length: number | undefined;
|
|
837
|
+
}>;
|
|
838
|
+
capabilityId: import("drizzle-orm/sqlite-core").SQLiteColumn<{
|
|
839
|
+
name: "capability_id";
|
|
840
|
+
tableName: "action_closure_record";
|
|
841
|
+
dataType: "string";
|
|
842
|
+
columnType: "SQLiteText";
|
|
843
|
+
data: string;
|
|
844
|
+
driverParam: string;
|
|
845
|
+
notNull: false;
|
|
846
|
+
hasDefault: false;
|
|
847
|
+
isPrimaryKey: false;
|
|
848
|
+
isAutoincrement: false;
|
|
849
|
+
hasRuntimeDefault: false;
|
|
850
|
+
enumValues: [string, ...string[]];
|
|
851
|
+
baseColumn: never;
|
|
852
|
+
identity: undefined;
|
|
853
|
+
generated: undefined;
|
|
854
|
+
}, {}, {
|
|
855
|
+
length: number | undefined;
|
|
856
|
+
}>;
|
|
819
857
|
proposalId: import("drizzle-orm/sqlite-core").SQLiteColumn<{
|
|
820
858
|
name: "proposal_id";
|
|
821
859
|
tableName: "action_closure_record";
|
|
@@ -2557,3 +2595,253 @@ export declare const dailyRhythmState: import("drizzle-orm/sqlite-core").SQLiteT
|
|
|
2557
2595
|
}>;
|
|
2558
2596
|
export type DailyRhythmStateRecord = typeof dailyRhythmState.$inferSelect;
|
|
2559
2597
|
export type NewDailyRhythmStateRecord = typeof dailyRhythmState.$inferInsert;
|
|
2598
|
+
export declare const connectorCooldownState: import("drizzle-orm/sqlite-core").SQLiteTableWithColumns<{
|
|
2599
|
+
name: "connector_cooldown_state";
|
|
2600
|
+
schema: undefined;
|
|
2601
|
+
columns: {
|
|
2602
|
+
id: import("drizzle-orm/sqlite-core").SQLiteColumn<{
|
|
2603
|
+
name: "id";
|
|
2604
|
+
tableName: "connector_cooldown_state";
|
|
2605
|
+
dataType: "string";
|
|
2606
|
+
columnType: "SQLiteText";
|
|
2607
|
+
data: string;
|
|
2608
|
+
driverParam: string;
|
|
2609
|
+
notNull: true;
|
|
2610
|
+
hasDefault: false;
|
|
2611
|
+
isPrimaryKey: true;
|
|
2612
|
+
isAutoincrement: false;
|
|
2613
|
+
hasRuntimeDefault: false;
|
|
2614
|
+
enumValues: [string, ...string[]];
|
|
2615
|
+
baseColumn: never;
|
|
2616
|
+
identity: undefined;
|
|
2617
|
+
generated: undefined;
|
|
2618
|
+
}, {}, {
|
|
2619
|
+
length: number | undefined;
|
|
2620
|
+
}>;
|
|
2621
|
+
platformId: import("drizzle-orm/sqlite-core").SQLiteColumn<{
|
|
2622
|
+
name: "platform_id";
|
|
2623
|
+
tableName: "connector_cooldown_state";
|
|
2624
|
+
dataType: "string";
|
|
2625
|
+
columnType: "SQLiteText";
|
|
2626
|
+
data: string;
|
|
2627
|
+
driverParam: string;
|
|
2628
|
+
notNull: true;
|
|
2629
|
+
hasDefault: false;
|
|
2630
|
+
isPrimaryKey: false;
|
|
2631
|
+
isAutoincrement: false;
|
|
2632
|
+
hasRuntimeDefault: false;
|
|
2633
|
+
enumValues: [string, ...string[]];
|
|
2634
|
+
baseColumn: never;
|
|
2635
|
+
identity: undefined;
|
|
2636
|
+
generated: undefined;
|
|
2637
|
+
}, {}, {
|
|
2638
|
+
length: number | undefined;
|
|
2639
|
+
}>;
|
|
2640
|
+
capabilityId: import("drizzle-orm/sqlite-core").SQLiteColumn<{
|
|
2641
|
+
name: "capability_id";
|
|
2642
|
+
tableName: "connector_cooldown_state";
|
|
2643
|
+
dataType: "string";
|
|
2644
|
+
columnType: "SQLiteText";
|
|
2645
|
+
data: string;
|
|
2646
|
+
driverParam: string;
|
|
2647
|
+
notNull: true;
|
|
2648
|
+
hasDefault: false;
|
|
2649
|
+
isPrimaryKey: false;
|
|
2650
|
+
isAutoincrement: false;
|
|
2651
|
+
hasRuntimeDefault: false;
|
|
2652
|
+
enumValues: [string, ...string[]];
|
|
2653
|
+
baseColumn: never;
|
|
2654
|
+
identity: undefined;
|
|
2655
|
+
generated: undefined;
|
|
2656
|
+
}, {}, {
|
|
2657
|
+
length: number | undefined;
|
|
2658
|
+
}>;
|
|
2659
|
+
failureClass: import("drizzle-orm/sqlite-core").SQLiteColumn<{
|
|
2660
|
+
name: "failure_class";
|
|
2661
|
+
tableName: "connector_cooldown_state";
|
|
2662
|
+
dataType: "string";
|
|
2663
|
+
columnType: "SQLiteText";
|
|
2664
|
+
data: string;
|
|
2665
|
+
driverParam: string;
|
|
2666
|
+
notNull: true;
|
|
2667
|
+
hasDefault: false;
|
|
2668
|
+
isPrimaryKey: false;
|
|
2669
|
+
isAutoincrement: false;
|
|
2670
|
+
hasRuntimeDefault: false;
|
|
2671
|
+
enumValues: [string, ...string[]];
|
|
2672
|
+
baseColumn: never;
|
|
2673
|
+
identity: undefined;
|
|
2674
|
+
generated: undefined;
|
|
2675
|
+
}, {}, {
|
|
2676
|
+
length: number | undefined;
|
|
2677
|
+
}>;
|
|
2678
|
+
retryAfterMs: import("drizzle-orm/sqlite-core").SQLiteColumn<{
|
|
2679
|
+
name: "retry_after_ms";
|
|
2680
|
+
tableName: "connector_cooldown_state";
|
|
2681
|
+
dataType: "number";
|
|
2682
|
+
columnType: "SQLiteInteger";
|
|
2683
|
+
data: number;
|
|
2684
|
+
driverParam: number;
|
|
2685
|
+
notNull: false;
|
|
2686
|
+
hasDefault: false;
|
|
2687
|
+
isPrimaryKey: false;
|
|
2688
|
+
isAutoincrement: false;
|
|
2689
|
+
hasRuntimeDefault: false;
|
|
2690
|
+
enumValues: undefined;
|
|
2691
|
+
baseColumn: never;
|
|
2692
|
+
identity: undefined;
|
|
2693
|
+
generated: undefined;
|
|
2694
|
+
}, {}, {}>;
|
|
2695
|
+
blockedUntil: import("drizzle-orm/sqlite-core").SQLiteColumn<{
|
|
2696
|
+
name: "blocked_until";
|
|
2697
|
+
tableName: "connector_cooldown_state";
|
|
2698
|
+
dataType: "string";
|
|
2699
|
+
columnType: "SQLiteText";
|
|
2700
|
+
data: string;
|
|
2701
|
+
driverParam: string;
|
|
2702
|
+
notNull: true;
|
|
2703
|
+
hasDefault: false;
|
|
2704
|
+
isPrimaryKey: false;
|
|
2705
|
+
isAutoincrement: false;
|
|
2706
|
+
hasRuntimeDefault: false;
|
|
2707
|
+
enumValues: [string, ...string[]];
|
|
2708
|
+
baseColumn: never;
|
|
2709
|
+
identity: undefined;
|
|
2710
|
+
generated: undefined;
|
|
2711
|
+
}, {}, {
|
|
2712
|
+
length: number | undefined;
|
|
2713
|
+
}>;
|
|
2714
|
+
failureCount: import("drizzle-orm/sqlite-core").SQLiteColumn<{
|
|
2715
|
+
name: "failure_count";
|
|
2716
|
+
tableName: "connector_cooldown_state";
|
|
2717
|
+
dataType: "number";
|
|
2718
|
+
columnType: "SQLiteInteger";
|
|
2719
|
+
data: number;
|
|
2720
|
+
driverParam: number;
|
|
2721
|
+
notNull: true;
|
|
2722
|
+
hasDefault: true;
|
|
2723
|
+
isPrimaryKey: false;
|
|
2724
|
+
isAutoincrement: false;
|
|
2725
|
+
hasRuntimeDefault: false;
|
|
2726
|
+
enumValues: undefined;
|
|
2727
|
+
baseColumn: never;
|
|
2728
|
+
identity: undefined;
|
|
2729
|
+
generated: undefined;
|
|
2730
|
+
}, {}, {}>;
|
|
2731
|
+
terminalCount: import("drizzle-orm/sqlite-core").SQLiteColumn<{
|
|
2732
|
+
name: "terminal_count";
|
|
2733
|
+
tableName: "connector_cooldown_state";
|
|
2734
|
+
dataType: "number";
|
|
2735
|
+
columnType: "SQLiteInteger";
|
|
2736
|
+
data: number;
|
|
2737
|
+
driverParam: number;
|
|
2738
|
+
notNull: true;
|
|
2739
|
+
hasDefault: true;
|
|
2740
|
+
isPrimaryKey: false;
|
|
2741
|
+
isAutoincrement: false;
|
|
2742
|
+
hasRuntimeDefault: false;
|
|
2743
|
+
enumValues: undefined;
|
|
2744
|
+
baseColumn: never;
|
|
2745
|
+
identity: undefined;
|
|
2746
|
+
generated: undefined;
|
|
2747
|
+
}, {}, {}>;
|
|
2748
|
+
sourceRefsJson: import("drizzle-orm/sqlite-core").SQLiteColumn<{
|
|
2749
|
+
name: "source_refs_json";
|
|
2750
|
+
tableName: "connector_cooldown_state";
|
|
2751
|
+
dataType: "string";
|
|
2752
|
+
columnType: "SQLiteText";
|
|
2753
|
+
data: string;
|
|
2754
|
+
driverParam: string;
|
|
2755
|
+
notNull: true;
|
|
2756
|
+
hasDefault: false;
|
|
2757
|
+
isPrimaryKey: false;
|
|
2758
|
+
isAutoincrement: false;
|
|
2759
|
+
hasRuntimeDefault: false;
|
|
2760
|
+
enumValues: [string, ...string[]];
|
|
2761
|
+
baseColumn: never;
|
|
2762
|
+
identity: undefined;
|
|
2763
|
+
generated: undefined;
|
|
2764
|
+
}, {}, {
|
|
2765
|
+
length: number | undefined;
|
|
2766
|
+
}>;
|
|
2767
|
+
redactionClass: import("drizzle-orm/sqlite-core").SQLiteColumn<{
|
|
2768
|
+
name: "redaction_class";
|
|
2769
|
+
tableName: "connector_cooldown_state";
|
|
2770
|
+
dataType: "string";
|
|
2771
|
+
columnType: "SQLiteText";
|
|
2772
|
+
data: string;
|
|
2773
|
+
driverParam: string;
|
|
2774
|
+
notNull: true;
|
|
2775
|
+
hasDefault: true;
|
|
2776
|
+
isPrimaryKey: false;
|
|
2777
|
+
isAutoincrement: false;
|
|
2778
|
+
hasRuntimeDefault: false;
|
|
2779
|
+
enumValues: [string, ...string[]];
|
|
2780
|
+
baseColumn: never;
|
|
2781
|
+
identity: undefined;
|
|
2782
|
+
generated: undefined;
|
|
2783
|
+
}, {}, {
|
|
2784
|
+
length: number | undefined;
|
|
2785
|
+
}>;
|
|
2786
|
+
payloadJson: import("drizzle-orm/sqlite-core").SQLiteColumn<{
|
|
2787
|
+
name: "payload_json";
|
|
2788
|
+
tableName: "connector_cooldown_state";
|
|
2789
|
+
dataType: "string";
|
|
2790
|
+
columnType: "SQLiteText";
|
|
2791
|
+
data: string;
|
|
2792
|
+
driverParam: string;
|
|
2793
|
+
notNull: false;
|
|
2794
|
+
hasDefault: false;
|
|
2795
|
+
isPrimaryKey: false;
|
|
2796
|
+
isAutoincrement: false;
|
|
2797
|
+
hasRuntimeDefault: false;
|
|
2798
|
+
enumValues: [string, ...string[]];
|
|
2799
|
+
baseColumn: never;
|
|
2800
|
+
identity: undefined;
|
|
2801
|
+
generated: undefined;
|
|
2802
|
+
}, {}, {
|
|
2803
|
+
length: number | undefined;
|
|
2804
|
+
}>;
|
|
2805
|
+
createdAt: import("drizzle-orm/sqlite-core").SQLiteColumn<{
|
|
2806
|
+
name: "created_at";
|
|
2807
|
+
tableName: "connector_cooldown_state";
|
|
2808
|
+
dataType: "string";
|
|
2809
|
+
columnType: "SQLiteText";
|
|
2810
|
+
data: string;
|
|
2811
|
+
driverParam: string;
|
|
2812
|
+
notNull: true;
|
|
2813
|
+
hasDefault: false;
|
|
2814
|
+
isPrimaryKey: false;
|
|
2815
|
+
isAutoincrement: false;
|
|
2816
|
+
hasRuntimeDefault: false;
|
|
2817
|
+
enumValues: [string, ...string[]];
|
|
2818
|
+
baseColumn: never;
|
|
2819
|
+
identity: undefined;
|
|
2820
|
+
generated: undefined;
|
|
2821
|
+
}, {}, {
|
|
2822
|
+
length: number | undefined;
|
|
2823
|
+
}>;
|
|
2824
|
+
updatedAt: import("drizzle-orm/sqlite-core").SQLiteColumn<{
|
|
2825
|
+
name: "updated_at";
|
|
2826
|
+
tableName: "connector_cooldown_state";
|
|
2827
|
+
dataType: "string";
|
|
2828
|
+
columnType: "SQLiteText";
|
|
2829
|
+
data: string;
|
|
2830
|
+
driverParam: string;
|
|
2831
|
+
notNull: true;
|
|
2832
|
+
hasDefault: false;
|
|
2833
|
+
isPrimaryKey: false;
|
|
2834
|
+
isAutoincrement: false;
|
|
2835
|
+
hasRuntimeDefault: false;
|
|
2836
|
+
enumValues: [string, ...string[]];
|
|
2837
|
+
baseColumn: never;
|
|
2838
|
+
identity: undefined;
|
|
2839
|
+
generated: undefined;
|
|
2840
|
+
}, {}, {
|
|
2841
|
+
length: number | undefined;
|
|
2842
|
+
}>;
|
|
2843
|
+
};
|
|
2844
|
+
dialect: "sqlite";
|
|
2845
|
+
}>;
|
|
2846
|
+
export type ConnectorCooldownStateRecord = typeof connectorCooldownState.$inferSelect;
|
|
2847
|
+
export type NewConnectorCooldownStateRecord = typeof connectorCooldownState.$inferInsert;
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
* Dependencies: drizzle-orm/sqlite-core
|
|
13
13
|
* Boundary: Schema definitions only; no runtime logic.
|
|
14
14
|
*/
|
|
15
|
-
import { sqliteTable, text, integer, real } from "drizzle-orm/sqlite-core";
|
|
15
|
+
import { sqliteTable, text, integer, real, index } from "drizzle-orm/sqlite-core";
|
|
16
16
|
// ───────────────────────────────────────────────────────────────
|
|
17
17
|
// 1. EvidenceItem
|
|
18
18
|
// ───────────────────────────────────────────────────────────────
|
|
@@ -73,6 +73,8 @@ export const actionClosureRecord = sqliteTable("action_closure_record", {
|
|
|
73
73
|
id: text("id").primaryKey(),
|
|
74
74
|
createdAt: text("created_at").notNull(),
|
|
75
75
|
cycleId: text("cycle_id").notNull(),
|
|
76
|
+
platformId: text("platform_id"),
|
|
77
|
+
capabilityId: text("capability_id"),
|
|
76
78
|
proposalId: text("proposal_id"),
|
|
77
79
|
decisionId: text("decision_id"),
|
|
78
80
|
status: text("status").notNull(),
|
|
@@ -197,3 +199,23 @@ export const dailyRhythmState = sqliteTable("daily_rhythm_state", {
|
|
|
197
199
|
payloadJson: text("payload_json"),
|
|
198
200
|
updatedAt: text("updated_at").notNull(),
|
|
199
201
|
});
|
|
202
|
+
// ───────────────────────────────────────────────────────────────
|
|
203
|
+
// 12. ConnectorCooldownState
|
|
204
|
+
// ───────────────────────────────────────────────────────────────
|
|
205
|
+
export const connectorCooldownState = sqliteTable("connector_cooldown_state", {
|
|
206
|
+
id: text("id").primaryKey(),
|
|
207
|
+
platformId: text("platform_id").notNull(),
|
|
208
|
+
capabilityId: text("capability_id").notNull(),
|
|
209
|
+
failureClass: text("failure_class").notNull(),
|
|
210
|
+
retryAfterMs: integer("retry_after_ms"),
|
|
211
|
+
blockedUntil: text("blocked_until").notNull(),
|
|
212
|
+
failureCount: integer("failure_count").notNull().default(1),
|
|
213
|
+
terminalCount: integer("terminal_count").notNull().default(0),
|
|
214
|
+
sourceRefsJson: text("source_refs_json").notNull(),
|
|
215
|
+
redactionClass: text("redaction_class").notNull().default("none"),
|
|
216
|
+
payloadJson: text("payload_json"),
|
|
217
|
+
createdAt: text("created_at").notNull(),
|
|
218
|
+
updatedAt: text("updated_at").notNull(),
|
|
219
|
+
}, (table) => ({
|
|
220
|
+
platformCapabilityIdx: index("connector_cooldown_state_platform_capability_idx").on(table.platformId, table.capabilityId),
|
|
221
|
+
}));
|
|
@@ -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, type ImpulseContextArtifactRecord, type NewImpulseContextArtifactRecord, type DailyRhythmStateRecord, type NewDailyRhythmStateRecord } 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, type ConnectorCooldownStateRecord, type NewConnectorCooldownStateRecord } 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;
|
|
@@ -172,6 +172,15 @@ export declare function readDailyRhythmStateByDay(db: StateDatabase, day: string
|
|
|
172
172
|
row?: DailyRhythmStateRecord;
|
|
173
173
|
degraded?: DegradedOperationResult;
|
|
174
174
|
}>;
|
|
175
|
+
export declare function readConnectorCooldownState(db: StateDatabase, platformId: string, capabilityId: string): Promise<{
|
|
176
|
+
row?: ConnectorCooldownStateRecord;
|
|
177
|
+
degraded?: DegradedOperationResult;
|
|
178
|
+
}>;
|
|
179
|
+
export declare function writeConnectorCooldownState(db: StateDatabase, row: Omit<NewConnectorCooldownStateRecord, "sourceRefsJson"> & {
|
|
180
|
+
sourceRefs: SourceRef[];
|
|
181
|
+
}): Promise<{
|
|
182
|
+
id: string;
|
|
183
|
+
} | DegradedOperationResult>;
|
|
175
184
|
export declare function extractSourceRefs(row: {
|
|
176
185
|
sourceRefsJson: string | null;
|
|
177
186
|
}): SourceRef[];
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
* Test coverage: tests/unit/storage/v8-state-stores.test.ts
|
|
23
23
|
*/
|
|
24
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";
|
|
25
|
+
import { evidenceItem, perceptionCard, judgmentVerdict, actionClosureRecord, quietDailyReview, dreamConsolidationRun, longTermMemoryProjection, heartbeatCycleTrace, loopStageEvent, impulseContextArtifact, dailyRhythmState, connectorCooldownState, } from "./db/schema/v8-entities.js";
|
|
26
26
|
// ───────────────────────────────────────────────────────────────
|
|
27
27
|
// Shared helpers
|
|
28
28
|
// ───────────────────────────────────────────────────────────────
|
|
@@ -99,10 +99,62 @@ export async function readEvidenceItemsByStatus(db, lifecycleStatus) {
|
|
|
99
99
|
// ───────────────────────────────────────────────────────────────
|
|
100
100
|
// PerceptionCard store
|
|
101
101
|
// ───────────────────────────────────────────────────────────────
|
|
102
|
+
const CANONICAL_NOVELTY_CLASSES = ["new", "changed", "duplicate", "stale"];
|
|
103
|
+
const CANONICAL_RELEVANCE_CLASSES = ["low", "medium", "high"];
|
|
104
|
+
function validatePerceptionCardCanonical(row) {
|
|
105
|
+
// Validate noveltyClass
|
|
106
|
+
if (row.novelty && !CANONICAL_NOVELTY_CLASSES.includes(row.novelty)) {
|
|
107
|
+
return {
|
|
108
|
+
ok: false,
|
|
109
|
+
degraded: {
|
|
110
|
+
status: "degraded",
|
|
111
|
+
reason: "perception_contract_drift",
|
|
112
|
+
ownerStage: "perception",
|
|
113
|
+
sourceRefs: row.sourceRefs,
|
|
114
|
+
operatorNextAction: `novelty "${row.novelty}" is not canonical. Expected one of: ${CANONICAL_NOVELTY_CLASSES.join(", ")}`,
|
|
115
|
+
retryable: false,
|
|
116
|
+
},
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
// Validate relevanceScore range
|
|
120
|
+
if (row.relevance !== undefined && row.relevance !== null) {
|
|
121
|
+
if (row.relevance < 0 || row.relevance > 1) {
|
|
122
|
+
return {
|
|
123
|
+
ok: false,
|
|
124
|
+
degraded: {
|
|
125
|
+
status: "degraded",
|
|
126
|
+
reason: "perception_contract_drift",
|
|
127
|
+
ownerStage: "perception",
|
|
128
|
+
sourceRefs: row.sourceRefs,
|
|
129
|
+
operatorNextAction: `relevanceScore ${row.relevance} out of range [0, 1]`,
|
|
130
|
+
retryable: false,
|
|
131
|
+
},
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
// Validate relevanceClass
|
|
136
|
+
if (row.relevanceClass && !CANONICAL_RELEVANCE_CLASSES.includes(row.relevanceClass)) {
|
|
137
|
+
return {
|
|
138
|
+
ok: false,
|
|
139
|
+
degraded: {
|
|
140
|
+
status: "degraded",
|
|
141
|
+
reason: "perception_contract_drift",
|
|
142
|
+
ownerStage: "perception",
|
|
143
|
+
sourceRefs: row.sourceRefs,
|
|
144
|
+
operatorNextAction: `relevanceClass "${row.relevanceClass}" is not canonical. Expected one of: ${CANONICAL_RELEVANCE_CLASSES.join(", ")}`,
|
|
145
|
+
retryable: false,
|
|
146
|
+
},
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
return { ok: true };
|
|
150
|
+
}
|
|
102
151
|
export async function writePerceptionCard(db, row) {
|
|
103
152
|
const validated = validateSourceRefs(row.sourceRefs, "perception");
|
|
104
153
|
if (!validated.ok)
|
|
105
154
|
return validated.degraded;
|
|
155
|
+
const canonicalCheck = validatePerceptionCardCanonical(row);
|
|
156
|
+
if (!canonicalCheck.ok)
|
|
157
|
+
return canonicalCheck.degraded;
|
|
106
158
|
try {
|
|
107
159
|
const record = {
|
|
108
160
|
...row,
|
|
@@ -602,6 +654,39 @@ export async function readDailyRhythmStateByDay(db, day) {
|
|
|
602
654
|
};
|
|
603
655
|
}
|
|
604
656
|
}
|
|
657
|
+
export async function readConnectorCooldownState(db, platformId, capabilityId) {
|
|
658
|
+
try {
|
|
659
|
+
const rows = await db.db
|
|
660
|
+
.select()
|
|
661
|
+
.from(connectorCooldownState)
|
|
662
|
+
.where(and(eq(connectorCooldownState.platformId, platformId), eq(connectorCooldownState.capabilityId, capabilityId)))
|
|
663
|
+
.orderBy(desc(connectorCooldownState.updatedAt))
|
|
664
|
+
.limit(1);
|
|
665
|
+
return { row: rows[0] };
|
|
666
|
+
}
|
|
667
|
+
catch {
|
|
668
|
+
return {
|
|
669
|
+
degraded: makeDegraded("state_unreadable", "ingestion", `Check state database connectivity for cooldown ${platformId}:${capabilityId}`),
|
|
670
|
+
};
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
export async function writeConnectorCooldownState(db, row) {
|
|
674
|
+
const validated = validateSourceRefs(row.sourceRefs, "ingestion");
|
|
675
|
+
if (!validated.ok)
|
|
676
|
+
return validated.degraded;
|
|
677
|
+
try {
|
|
678
|
+
const record = {
|
|
679
|
+
...row,
|
|
680
|
+
sourceRefsJson: serializeSourceRefs(validated.record),
|
|
681
|
+
};
|
|
682
|
+
await db.db.delete(connectorCooldownState).where(eq(connectorCooldownState.id, row.id));
|
|
683
|
+
await db.db.insert(connectorCooldownState).values(record);
|
|
684
|
+
return { id: row.id };
|
|
685
|
+
}
|
|
686
|
+
catch {
|
|
687
|
+
return makeDegraded("state_unreadable", "ingestion", "Retry connector cooldown state write after DB recovery", validated.record);
|
|
688
|
+
}
|
|
689
|
+
}
|
|
605
690
|
// ───────────────────────────────────────────────────────────────
|
|
606
691
|
// SourceRef round-trip helper (for tests and consumers)
|
|
607
692
|
// ───────────────────────────────────────────────────────────────
|