@haaaiawd/second-nature 0.1.27 → 0.1.30
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/SKILL.md +35 -33
- package/agent-inner-guide.md +144 -124
- package/index.js +83 -20
- package/openclaw.plugin.json +2 -2
- package/package.json +2 -1
- package/runtime/cli/commands/connector-behavior.d.ts +20 -0
- package/runtime/cli/commands/connector-behavior.js +160 -0
- package/runtime/cli/commands/index.js +8 -0
- package/runtime/cli/index.js +9 -2
- package/runtime/cli/ops/manual-run-dispatcher.d.ts +79 -0
- package/runtime/cli/ops/manual-run-dispatcher.js +110 -0
- package/runtime/cli/ops/ops-router.d.ts +45 -4
- package/runtime/cli/ops/ops-router.js +543 -2
- package/runtime/cli/read-models/index.js +35 -18
- package/runtime/cli/read-models/types.d.ts +1 -0
- package/runtime/connectors/agent-network/agent-world/adapter.d.ts +1 -0
- package/runtime/connectors/agent-network/agent-world/adapter.js +2 -2
- package/runtime/connectors/base/contract.d.ts +4 -1
- package/runtime/connectors/base/contract.js +5 -1
- package/runtime/connectors/base/effect-commit-ledger-sqlite.d.ts +31 -0
- package/runtime/connectors/base/effect-commit-ledger-sqlite.js +86 -0
- package/runtime/connectors/base/failure-taxonomy.js +5 -0
- package/runtime/connectors/base/manifest-v7.d.ts +151 -0
- package/runtime/connectors/base/manifest-v7.js +170 -0
- package/runtime/connectors/base/manifest.d.ts +67 -77
- package/runtime/connectors/base/manifest.js +7 -7
- package/runtime/connectors/base/route-planner.js +11 -8
- package/runtime/connectors/base/structured-unavailable-reason.d.ts +59 -0
- package/runtime/connectors/base/structured-unavailable-reason.js +113 -0
- package/runtime/connectors/base/wet-probe-runner.d.ts +40 -0
- package/runtime/connectors/base/wet-probe-runner.js +132 -0
- package/runtime/connectors/manifest/manifest-schema.d.ts +4 -0
- package/runtime/connectors/manifest/manifest-schema.js +2 -0
- package/runtime/connectors/services/connector-executor-adapter.d.ts +1 -0
- package/runtime/connectors/services/connector-executor-adapter.js +132 -26
- package/runtime/core/second-nature/body/behavior-promotion/behavior-promotion-loop.d.ts +45 -0
- package/runtime/core/second-nature/body/behavior-promotion/behavior-promotion-loop.js +132 -0
- package/runtime/core/second-nature/body/circuit-breaker/circuit-breaker-manager.d.ts +60 -0
- package/runtime/core/second-nature/body/circuit-breaker/circuit-breaker-manager.js +174 -0
- package/runtime/core/second-nature/body/probe-signal-adapter.d.ts +38 -0
- package/runtime/core/second-nature/body/probe-signal-adapter.js +60 -0
- package/runtime/core/second-nature/body/tool-affordance/affordance-assembler.d.ts +51 -0
- package/runtime/core/second-nature/body/tool-affordance/affordance-assembler.js +129 -0
- package/runtime/core/second-nature/body/tool-affordance/affordance-context-scope.d.ts +30 -0
- package/runtime/core/second-nature/body/tool-affordance/affordance-context-scope.js +92 -0
- package/runtime/core/second-nature/body/tool-experience/experience-writer.d.ts +34 -0
- package/runtime/core/second-nature/body/tool-experience/experience-writer.js +67 -0
- package/runtime/core/second-nature/body/tool-experience/pain-signal-query.d.ts +37 -0
- package/runtime/core/second-nature/body/tool-experience/pain-signal-query.js +62 -0
- package/runtime/core/second-nature/heartbeat/decision-trace-emitter.d.ts +29 -0
- package/runtime/core/second-nature/heartbeat/decision-trace-emitter.js +28 -0
- package/runtime/core/second-nature/heartbeat/embodied-context-assembler.d.ts +54 -0
- package/runtime/core/second-nature/heartbeat/embodied-context-assembler.js +164 -0
- package/runtime/core/second-nature/heartbeat/goal-lifecycle-policy.d.ts +37 -0
- package/runtime/core/second-nature/heartbeat/goal-lifecycle-policy.js +61 -0
- package/runtime/core/second-nature/heartbeat/idle-curiosity-policy.d.ts +37 -0
- package/runtime/core/second-nature/heartbeat/idle-curiosity-policy.js +60 -0
- package/runtime/core/second-nature/heartbeat/index.d.ts +4 -0
- package/runtime/core/second-nature/heartbeat/index.js +5 -0
- package/runtime/core/second-nature/heartbeat/run-heartbeat-cycle-v7.d.ts +63 -0
- package/runtime/core/second-nature/heartbeat/run-heartbeat-cycle-v7.js +118 -0
- package/runtime/core/second-nature/orchestrator/downstream-intent-orchestrator.d.ts +41 -0
- package/runtime/core/second-nature/orchestrator/downstream-intent-orchestrator.js +43 -0
- package/runtime/core/second-nature/orchestrator/effect-dispatcher.d.ts +2 -1
- package/runtime/core/second-nature/orchestrator/effect-dispatcher.js +2 -0
- package/runtime/core/second-nature/orchestrator/hard-guard-evaluator.d.ts +31 -0
- package/runtime/core/second-nature/orchestrator/hard-guard-evaluator.js +102 -0
- package/runtime/core/second-nature/orchestrator/index.d.ts +5 -0
- package/runtime/core/second-nature/orchestrator/index.js +7 -0
- package/runtime/core/second-nature/quiet/claim-synthesizer.d.ts +53 -0
- package/runtime/core/second-nature/quiet/claim-synthesizer.js +153 -0
- package/runtime/core/second-nature/quiet/daily-diary-writer.d.ts +29 -0
- package/runtime/core/second-nature/quiet/daily-diary-writer.js +92 -0
- package/runtime/core/second-nature/quiet/index.d.ts +5 -0
- package/runtime/core/second-nature/quiet/index.js +5 -0
- package/runtime/core/second-nature/quiet/run-source-backed-quiet.js +19 -12
- package/runtime/core/second-nature/types.d.ts +2 -0
- package/runtime/guidance/channel-feedback-ingestion-service.d.ts +88 -0
- package/runtime/guidance/channel-feedback-ingestion-service.js +231 -0
- package/runtime/guidance/guidance-draft-service.d.ts +60 -0
- package/runtime/guidance/guidance-draft-service.js +80 -0
- package/runtime/guidance/index.d.ts +3 -0
- package/runtime/guidance/index.js +3 -0
- package/runtime/guidance/outreach-draft-schema.d.ts +8 -8
- package/runtime/guidance/outreach-strategy-selector.d.ts +77 -0
- package/runtime/guidance/outreach-strategy-selector.js +211 -0
- package/runtime/observability/audit/append-only-audit-store.d.ts +20 -2
- package/runtime/observability/audit/append-only-audit-store.js +32 -6
- package/runtime/observability/audit/audit-envelope.d.ts +2 -1
- package/runtime/observability/audit/audit-envelope.js +8 -7
- package/runtime/observability/audit/audit-family-registry.json +66 -0
- package/runtime/observability/audit/family-registry.d.ts +43 -0
- package/runtime/observability/audit/family-registry.js +70 -0
- package/runtime/observability/index.d.ts +6 -1
- package/runtime/observability/index.js +6 -1
- package/runtime/observability/redaction/policy.d.ts +24 -3
- package/runtime/observability/redaction/policy.js +74 -0
- package/runtime/observability/services/heartbeat-digest-assembler.d.ts +152 -0
- package/runtime/observability/services/heartbeat-digest-assembler.js +248 -0
- package/runtime/observability/services/lived-experience-audit.js +6 -6
- package/runtime/observability/services/narrative-timeline-query-service.d.ts +136 -0
- package/runtime/observability/services/narrative-timeline-query-service.js +169 -0
- package/runtime/observability/services/restore-audit-service.d.ts +74 -0
- package/runtime/observability/services/restore-audit-service.js +79 -0
- package/runtime/observability/services/runtime-secret-anchor-view.d.ts +77 -0
- package/runtime/observability/services/runtime-secret-anchor-view.js +168 -0
- package/runtime/observability/services/self-health-snapshot.d.ts +92 -0
- package/runtime/observability/services/self-health-snapshot.js +251 -0
- package/runtime/shared/types/goal.d.ts +62 -0
- package/runtime/shared/types/goal.js +20 -0
- package/runtime/shared/types/index.d.ts +3 -0
- package/runtime/shared/types/index.js +3 -0
- package/runtime/shared/types/source-ref.d.ts +14 -0
- package/runtime/shared/types/source-ref.js +1 -0
- package/runtime/shared/types/v7-entities.d.ts +206 -0
- package/runtime/shared/types/v7-entities.js +27 -0
- package/runtime/storage/db/index.js +3 -0
- package/runtime/storage/db/migration-runner.d.ts +30 -0
- package/runtime/storage/db/migration-runner.js +93 -0
- package/runtime/storage/db/migrations/index.d.ts +5 -0
- package/runtime/storage/db/migrations/index.js +13 -0
- package/runtime/storage/db/migrations/v7-001-foundation.d.ts +13 -0
- package/runtime/storage/db/migrations/v7-001-foundation.js +144 -0
- package/runtime/storage/db/migrations/v7-002-effect-commit-ledger.d.ts +8 -0
- package/runtime/storage/db/migrations/v7-002-effect-commit-ledger.js +27 -0
- package/runtime/storage/db/migrations/v7-003-circuit-breaker.d.ts +7 -0
- package/runtime/storage/db/migrations/v7-003-circuit-breaker.js +26 -0
- package/runtime/storage/db/migrations/v7-004-behavior-promotion.d.ts +7 -0
- package/runtime/storage/db/migrations/v7-004-behavior-promotion.js +26 -0
- package/runtime/storage/db/schema/agent-goal.d.ts +38 -0
- package/runtime/storage/db/schema/agent-goal.js +2 -0
- package/runtime/storage/db/transaction-utils.d.ts +14 -0
- package/runtime/storage/db/transaction-utils.js +29 -0
- package/runtime/storage/db/write-queue.d.ts +38 -0
- package/runtime/storage/db/write-queue.js +97 -0
- package/runtime/storage/quiet/persist-quiet-artifact.js +2 -1
- package/runtime/storage/services/diary-dream-store.d.ts +35 -0
- package/runtime/storage/services/diary-dream-store.js +165 -0
- package/runtime/storage/services/embodied-context-state-port.d.ts +77 -0
- package/runtime/storage/services/embodied-context-state-port.js +115 -0
- package/runtime/storage/services/goal-lifecycle-store.d.ts +42 -0
- package/runtime/storage/services/goal-lifecycle-store.js +181 -0
- package/runtime/storage/services/history-digest-store.d.ts +33 -0
- package/runtime/storage/services/history-digest-store.js +140 -0
- package/runtime/storage/services/identity-profile-store.d.ts +25 -0
- package/runtime/storage/services/identity-profile-store.js +81 -0
- package/runtime/storage/services/interaction-snapshot-projector.d.ts +15 -0
- package/runtime/storage/services/interaction-snapshot-projector.js +35 -0
- package/runtime/storage/services/restore-snapshot-store.d.ts +52 -0
- package/runtime/storage/services/restore-snapshot-store.js +193 -0
- package/runtime/storage/services/runtime-secret-anchor-store.d.ts +26 -0
- package/runtime/storage/services/runtime-secret-anchor-store.js +82 -0
- package/runtime/storage/services/tool-experience-store.d.ts +25 -0
- package/runtime/storage/services/tool-experience-store.js +116 -0
- package/runtime/storage/services/write-validation-gate.d.ts +46 -0
- package/runtime/storage/services/write-validation-gate.js +200 -0
- package/workspace-ops-bridge.js +16 -1
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* v7 全量共享实体类型 (v7 Shared Entity Types)
|
|
3
|
+
*
|
|
4
|
+
* Core logic: Centralizes all cross-system entity declarations introduced in
|
|
5
|
+
* Second Nature v7, ensuring type consistency across state-memory,
|
|
6
|
+
* control-plane, body-tool, dream-quiet, guidance-voice, connector, and
|
|
7
|
+
* observability-health systems.
|
|
8
|
+
*
|
|
9
|
+
* Design authority:
|
|
10
|
+
* - `02_ARCHITECTURE_OVERVIEW.md` §2 (System Inventory) — entity list
|
|
11
|
+
* - `05A_TASKS.md` T-SMS.F.1 — contract requirements
|
|
12
|
+
* - ADR-002/003/007/008 — entity semantics
|
|
13
|
+
*
|
|
14
|
+
* Dependencies:
|
|
15
|
+
* - `SourceRef` from `./source-ref.js`
|
|
16
|
+
* - `AgentGoal` from `./goal.js`
|
|
17
|
+
*
|
|
18
|
+
* Boundary:
|
|
19
|
+
* - This file defines types only; no runtime logic or business rules.
|
|
20
|
+
* - Sensitive fields (credential, raw private content, raw prompt,
|
|
21
|
+
* encryption key, session token) are explicitly excluded from
|
|
22
|
+
* RestoreSnapshot via type-level whitelist.
|
|
23
|
+
* - RuntimeSecretAnchor never stores key plaintext (ADR-007).
|
|
24
|
+
*
|
|
25
|
+
* Test coverage: tests/unit/shared/v7-entities.test.ts
|
|
26
|
+
*/
|
|
27
|
+
import type { SourceRef } from "./source-ref.js";
|
|
28
|
+
import type { AgentGoal } from "./goal.js";
|
|
29
|
+
export interface PlatformHandle {
|
|
30
|
+
platformId: string;
|
|
31
|
+
handle: string;
|
|
32
|
+
url?: string;
|
|
33
|
+
verifiedAt?: string;
|
|
34
|
+
}
|
|
35
|
+
export interface IdentityProfile {
|
|
36
|
+
profileId: string;
|
|
37
|
+
canonicalName: string;
|
|
38
|
+
canonicalAvatar?: string;
|
|
39
|
+
canonicalBio?: string;
|
|
40
|
+
platformHandles: PlatformHandle[];
|
|
41
|
+
updatedAt: string;
|
|
42
|
+
}
|
|
43
|
+
export interface RecentInteractionSnapshot {
|
|
44
|
+
interactionId: string;
|
|
45
|
+
platformId: string;
|
|
46
|
+
channelId?: string;
|
|
47
|
+
summary: string;
|
|
48
|
+
contentRef?: string;
|
|
49
|
+
isReply: boolean;
|
|
50
|
+
repliedAt?: string;
|
|
51
|
+
createdAt: string;
|
|
52
|
+
}
|
|
53
|
+
export type ToolExperienceOutcome = "success" | "failure" | "timeout" | "cancelled" | "probe_policy_denied";
|
|
54
|
+
export type ToolExperienceTriggerSource = "heartbeat" | "manual_run" | "probe" | "idle_curiosity";
|
|
55
|
+
export interface ToolExperience {
|
|
56
|
+
experienceId: string;
|
|
57
|
+
connectorId: string;
|
|
58
|
+
capabilityId: string;
|
|
59
|
+
outcome: ToolExperienceOutcome;
|
|
60
|
+
failureClass?: string;
|
|
61
|
+
latencyMs: number;
|
|
62
|
+
evidenceQuality: number;
|
|
63
|
+
sourceRefs: SourceRef;
|
|
64
|
+
triggerSource: ToolExperienceTriggerSource;
|
|
65
|
+
createdAt: string;
|
|
66
|
+
}
|
|
67
|
+
export type ProbeActualStatus = "available" | "degraded" | "unavailable";
|
|
68
|
+
export interface CapabilityProbeResult {
|
|
69
|
+
probeResultId: string;
|
|
70
|
+
capabilityId: string;
|
|
71
|
+
connectorId: string;
|
|
72
|
+
actualStatus: ProbeActualStatus;
|
|
73
|
+
httpStatus?: number;
|
|
74
|
+
sampleResponseRef?: string;
|
|
75
|
+
probeConfigRef: string;
|
|
76
|
+
createdAt: string;
|
|
77
|
+
}
|
|
78
|
+
export type RestorableEntityKind = "identity_profile" | "agent_goal" | "tool_experience" | "daily_diary" | "dream_output" | "narrative_timeline";
|
|
79
|
+
export type SensitiveExcludedKind = "credential" | "raw_private_message" | "raw_prompt" | "encryption_key" | "session_token";
|
|
80
|
+
export interface RestoreSnapshot {
|
|
81
|
+
snapshotId: string;
|
|
82
|
+
entityWhitelist: RestorableEntityKind[];
|
|
83
|
+
excludedSensitiveKinds: SensitiveExcludedKind[];
|
|
84
|
+
capturedAt: string;
|
|
85
|
+
payload: Record<string, unknown>;
|
|
86
|
+
}
|
|
87
|
+
export type SecretAnchorHealth = "ok" | "missing" | "wrong_key" | "rotation_needed";
|
|
88
|
+
export interface RuntimeSecretAnchor {
|
|
89
|
+
anchorId: string;
|
|
90
|
+
locationRef: string;
|
|
91
|
+
health: SecretAnchorHealth;
|
|
92
|
+
rotationPolicyRef?: string;
|
|
93
|
+
updatedAt: string;
|
|
94
|
+
}
|
|
95
|
+
export type QuietClaimKind = "observation" | "fact" | "pattern";
|
|
96
|
+
export interface QuietClaim {
|
|
97
|
+
claimId: string;
|
|
98
|
+
kind: QuietClaimKind;
|
|
99
|
+
text: string;
|
|
100
|
+
sourceRefs: SourceRef;
|
|
101
|
+
confidence: number;
|
|
102
|
+
createdAt: string;
|
|
103
|
+
}
|
|
104
|
+
export interface DailyDiary {
|
|
105
|
+
diaryId: string;
|
|
106
|
+
day: string;
|
|
107
|
+
observedToday: string[];
|
|
108
|
+
notableSignals: string[];
|
|
109
|
+
tomorrowDirection: string;
|
|
110
|
+
sourceRefs: SourceRef;
|
|
111
|
+
createdAt: string;
|
|
112
|
+
}
|
|
113
|
+
export type DreamOutputStatus = "candidate" | "accepted" | "archived" | "partial";
|
|
114
|
+
export interface DreamOutput {
|
|
115
|
+
outputId: string;
|
|
116
|
+
runId: string;
|
|
117
|
+
status: DreamOutputStatus;
|
|
118
|
+
canonicalEntries: unknown[];
|
|
119
|
+
insights: unknown[];
|
|
120
|
+
narrativeUpdate?: Record<string, unknown>;
|
|
121
|
+
relationshipUpdate?: Record<string, unknown>;
|
|
122
|
+
validation: {
|
|
123
|
+
schemaValid: boolean;
|
|
124
|
+
sourceGrounded: boolean;
|
|
125
|
+
sensitivityClean: boolean;
|
|
126
|
+
unsupportedClaims: string[];
|
|
127
|
+
errors: string[];
|
|
128
|
+
checkedAt: string;
|
|
129
|
+
};
|
|
130
|
+
createdAt?: string;
|
|
131
|
+
}
|
|
132
|
+
export type HealthDimensionStatus = "ok" | "degraded" | "blocked";
|
|
133
|
+
export interface SelfHealthSnapshot {
|
|
134
|
+
snapshotId: string;
|
|
135
|
+
dimensions: Record<string, {
|
|
136
|
+
status: HealthDimensionStatus;
|
|
137
|
+
reason?: string;
|
|
138
|
+
}>;
|
|
139
|
+
checkedAt: string;
|
|
140
|
+
}
|
|
141
|
+
export interface HeartbeatDigest {
|
|
142
|
+
digestId: string;
|
|
143
|
+
day: string;
|
|
144
|
+
connectorSummary: Array<{
|
|
145
|
+
platformId: string;
|
|
146
|
+
status: string;
|
|
147
|
+
attemptCount: number;
|
|
148
|
+
}>;
|
|
149
|
+
goalSummary: Array<{
|
|
150
|
+
kind: string;
|
|
151
|
+
activeCount: number;
|
|
152
|
+
}>;
|
|
153
|
+
quietCount: number;
|
|
154
|
+
dreamCount: number;
|
|
155
|
+
breakerSummary: Array<{
|
|
156
|
+
connectorId: string;
|
|
157
|
+
state: string;
|
|
158
|
+
}>;
|
|
159
|
+
healthStatus: string;
|
|
160
|
+
createdAt: string;
|
|
161
|
+
}
|
|
162
|
+
export interface NarrativeTimelineEntry {
|
|
163
|
+
timelineId: string;
|
|
164
|
+
entryType: string;
|
|
165
|
+
subjectId: string;
|
|
166
|
+
delta: Record<string, unknown>;
|
|
167
|
+
previousHash: string;
|
|
168
|
+
currentHash: string;
|
|
169
|
+
createdAt: string;
|
|
170
|
+
}
|
|
171
|
+
export type AffordanceStatus = "safe" | "exploratory" | "needs_auth" | "painful" | "unavailable";
|
|
172
|
+
export interface AffordanceItem {
|
|
173
|
+
platformId: string;
|
|
174
|
+
capabilityId: string;
|
|
175
|
+
intent: string;
|
|
176
|
+
status: AffordanceStatus;
|
|
177
|
+
reason?: string;
|
|
178
|
+
lastProbedAt?: string;
|
|
179
|
+
}
|
|
180
|
+
export interface AffordanceMap {
|
|
181
|
+
[platformId: string]: AffordanceItem[];
|
|
182
|
+
}
|
|
183
|
+
export interface AffordanceContextScope {
|
|
184
|
+
platformIds?: string[];
|
|
185
|
+
goalKind?: string;
|
|
186
|
+
allowedStatuses?: AffordanceStatus[];
|
|
187
|
+
}
|
|
188
|
+
export type EmbodiedContextSliceStatus = "loaded" | "degraded" | "blocked";
|
|
189
|
+
export interface EmbodiedContextSlice<T> {
|
|
190
|
+
status: EmbodiedContextSliceStatus;
|
|
191
|
+
data: T;
|
|
192
|
+
reason?: string;
|
|
193
|
+
}
|
|
194
|
+
export interface EmbodiedContext {
|
|
195
|
+
identity: EmbodiedContextSlice<IdentityProfile>;
|
|
196
|
+
goals: EmbodiedContextSlice<AgentGoal[]>;
|
|
197
|
+
recentInteractions: EmbodiedContextSlice<RecentInteractionSnapshot[]>;
|
|
198
|
+
toolExperience: EmbodiedContextSlice<ToolExperience[]>;
|
|
199
|
+
acceptedDream: EmbodiedContextSlice<DreamOutput[]>;
|
|
200
|
+
affordanceMap?: EmbodiedContextSlice<AffordanceMap>;
|
|
201
|
+
/**
|
|
202
|
+
* selfHealth is populated by observability-health-system.
|
|
203
|
+
*/
|
|
204
|
+
selfHealth?: EmbodiedContextSlice<SelfHealthSnapshot>;
|
|
205
|
+
assembledAt: string;
|
|
206
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* v7 全量共享实体类型 (v7 Shared Entity Types)
|
|
3
|
+
*
|
|
4
|
+
* Core logic: Centralizes all cross-system entity declarations introduced in
|
|
5
|
+
* Second Nature v7, ensuring type consistency across state-memory,
|
|
6
|
+
* control-plane, body-tool, dream-quiet, guidance-voice, connector, and
|
|
7
|
+
* observability-health systems.
|
|
8
|
+
*
|
|
9
|
+
* Design authority:
|
|
10
|
+
* - `02_ARCHITECTURE_OVERVIEW.md` §2 (System Inventory) — entity list
|
|
11
|
+
* - `05A_TASKS.md` T-SMS.F.1 — contract requirements
|
|
12
|
+
* - ADR-002/003/007/008 — entity semantics
|
|
13
|
+
*
|
|
14
|
+
* Dependencies:
|
|
15
|
+
* - `SourceRef` from `./source-ref.js`
|
|
16
|
+
* - `AgentGoal` from `./goal.js`
|
|
17
|
+
*
|
|
18
|
+
* Boundary:
|
|
19
|
+
* - This file defines types only; no runtime logic or business rules.
|
|
20
|
+
* - Sensitive fields (credential, raw private content, raw prompt,
|
|
21
|
+
* encryption key, session token) are explicitly excluded from
|
|
22
|
+
* RestoreSnapshot via type-level whitelist.
|
|
23
|
+
* - RuntimeSecretAnchor never stores key plaintext (ADR-007).
|
|
24
|
+
*
|
|
25
|
+
* Test coverage: tests/unit/shared/v7-entities.test.ts
|
|
26
|
+
*/
|
|
27
|
+
export {};
|
|
@@ -4,6 +4,8 @@ import path from "node:path";
|
|
|
4
4
|
import fs from "node:fs";
|
|
5
5
|
import { fileURLToPath } from "node:url";
|
|
6
6
|
import * as schema from "./schema/index.js";
|
|
7
|
+
import { runMigrations } from "./migration-runner.js";
|
|
8
|
+
import { ALL_MIGRATIONS } from "./migrations/index.js";
|
|
7
9
|
// Pre-initialize sql.js WASM at module load time
|
|
8
10
|
const SQL = await initSqlJs();
|
|
9
11
|
const STATE_SCHEMA_SQL = `
|
|
@@ -190,6 +192,7 @@ function resolveDbPath(filename) {
|
|
|
190
192
|
function bootstrapStateSchema(sqlite) {
|
|
191
193
|
sqlite.exec(STATE_SCHEMA_SQL);
|
|
192
194
|
applyStateSchemaMigrations(sqlite);
|
|
195
|
+
runMigrations(sqlite, ALL_MIGRATIONS);
|
|
193
196
|
}
|
|
194
197
|
function applyStateSchemaMigrations(sqlite) {
|
|
195
198
|
const migrations = [
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SQLite schema migration runner (DR-018).
|
|
3
|
+
*
|
|
4
|
+
* Core logic:
|
|
5
|
+
* - Maintains a `_meta` table with `schema_version` for version tracking.
|
|
6
|
+
* - Executes pending migrations in ascending order within transactions.
|
|
7
|
+
* - On failure, marks `schema_migration_failed` in `_meta` without crashing;
|
|
8
|
+
* existing data is preserved (transaction rollback).
|
|
9
|
+
* - New columns use DEFAULT NULL to preserve backward compatibility.
|
|
10
|
+
*
|
|
11
|
+
* Dependencies: sql.js Database (from `sql.js` package).
|
|
12
|
+
* Boundary: Called once during DB initialization; does not own the DB lifecycle.
|
|
13
|
+
* Test coverage: tests/unit/storage/migration-runner.test.ts,
|
|
14
|
+
* tests/integration/storage/schema-migration.test.ts
|
|
15
|
+
*/
|
|
16
|
+
import type { Database } from "sql.js";
|
|
17
|
+
export interface Migration {
|
|
18
|
+
version: number;
|
|
19
|
+
label: string;
|
|
20
|
+
sql: string;
|
|
21
|
+
}
|
|
22
|
+
export interface MigrationResult {
|
|
23
|
+
schemaVersion: number;
|
|
24
|
+
applied: number[];
|
|
25
|
+
failed: boolean;
|
|
26
|
+
failedVersion?: number;
|
|
27
|
+
failedError?: string;
|
|
28
|
+
}
|
|
29
|
+
export declare function isMigrationFailed(sqlite: Database): boolean;
|
|
30
|
+
export declare function runMigrations(sqlite: Database, migrations: readonly Migration[]): MigrationResult;
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SQLite schema migration runner (DR-018).
|
|
3
|
+
*
|
|
4
|
+
* Core logic:
|
|
5
|
+
* - Maintains a `_meta` table with `schema_version` for version tracking.
|
|
6
|
+
* - Executes pending migrations in ascending order within transactions.
|
|
7
|
+
* - On failure, marks `schema_migration_failed` in `_meta` without crashing;
|
|
8
|
+
* existing data is preserved (transaction rollback).
|
|
9
|
+
* - New columns use DEFAULT NULL to preserve backward compatibility.
|
|
10
|
+
*
|
|
11
|
+
* Dependencies: sql.js Database (from `sql.js` package).
|
|
12
|
+
* Boundary: Called once during DB initialization; does not own the DB lifecycle.
|
|
13
|
+
* Test coverage: tests/unit/storage/migration-runner.test.ts,
|
|
14
|
+
* tests/integration/storage/schema-migration.test.ts
|
|
15
|
+
*/
|
|
16
|
+
const META_TABLE_SQL = `
|
|
17
|
+
CREATE TABLE IF NOT EXISTS _meta (
|
|
18
|
+
key TEXT PRIMARY KEY,
|
|
19
|
+
value TEXT NOT NULL
|
|
20
|
+
);
|
|
21
|
+
`;
|
|
22
|
+
function ensureMetaTable(sqlite) {
|
|
23
|
+
sqlite.exec(META_TABLE_SQL);
|
|
24
|
+
const rows = sqlite.exec("SELECT value FROM _meta WHERE key = 'schema_version'");
|
|
25
|
+
if (rows.length === 0 || rows[0].values.length === 0) {
|
|
26
|
+
sqlite.exec("INSERT OR IGNORE INTO _meta (key, value) VALUES ('schema_version', '0')");
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
function getSchemaVersion(sqlite) {
|
|
30
|
+
const rows = sqlite.exec("SELECT value FROM _meta WHERE key = 'schema_version'");
|
|
31
|
+
if (rows.length === 0 || rows[0].values.length === 0) {
|
|
32
|
+
return 0;
|
|
33
|
+
}
|
|
34
|
+
return parseInt(rows[0].values[0][0], 10);
|
|
35
|
+
}
|
|
36
|
+
function setSchemaVersion(sqlite, version) {
|
|
37
|
+
sqlite.exec(`UPDATE _meta SET value = '${version}' WHERE key = 'schema_version'`);
|
|
38
|
+
}
|
|
39
|
+
function markMigrationFailed(sqlite, version, error) {
|
|
40
|
+
sqlite.exec("INSERT OR REPLACE INTO _meta (key, value) VALUES ('schema_migration_failed', '1')");
|
|
41
|
+
const safeError = error.replace(/'/g, "''");
|
|
42
|
+
sqlite.exec(`INSERT OR REPLACE INTO _meta (key, value) VALUES ('schema_migration_failed_version', '${version}')`);
|
|
43
|
+
sqlite.exec(`INSERT OR REPLACE INTO _meta (key, value) VALUES ('schema_migration_failed_error', '${safeError}')`);
|
|
44
|
+
}
|
|
45
|
+
export function isMigrationFailed(sqlite) {
|
|
46
|
+
const rows = sqlite.exec("SELECT value FROM _meta WHERE key = 'schema_migration_failed'");
|
|
47
|
+
return (rows.length > 0 &&
|
|
48
|
+
rows[0].values.length > 0 &&
|
|
49
|
+
rows[0].values[0][0] === "1");
|
|
50
|
+
}
|
|
51
|
+
export function runMigrations(sqlite, migrations) {
|
|
52
|
+
ensureMetaTable(sqlite);
|
|
53
|
+
const currentVersion = getSchemaVersion(sqlite);
|
|
54
|
+
const pending = migrations
|
|
55
|
+
.filter((m) => m.version > currentVersion)
|
|
56
|
+
.sort((a, b) => a.version - b.version);
|
|
57
|
+
const applied = [];
|
|
58
|
+
let failed = false;
|
|
59
|
+
let failedVersion;
|
|
60
|
+
let failedError;
|
|
61
|
+
for (const migration of pending) {
|
|
62
|
+
try {
|
|
63
|
+
sqlite.exec("BEGIN EXCLUSIVE");
|
|
64
|
+
sqlite.exec(migration.sql);
|
|
65
|
+
setSchemaVersion(sqlite, migration.version);
|
|
66
|
+
sqlite.exec("COMMIT");
|
|
67
|
+
applied.push(migration.version);
|
|
68
|
+
}
|
|
69
|
+
catch (err) {
|
|
70
|
+
try {
|
|
71
|
+
sqlite.exec("ROLLBACK");
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
// rollback may fail if no transaction active
|
|
75
|
+
}
|
|
76
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
77
|
+
process.stderr.write(`schema_migration_failed: v${migration.version} (${migration.label}) — ${message}\n`);
|
|
78
|
+
markMigrationFailed(sqlite, migration.version, message);
|
|
79
|
+
failed = true;
|
|
80
|
+
failedVersion = migration.version;
|
|
81
|
+
failedError = message;
|
|
82
|
+
break;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
const finalVersion = getSchemaVersion(sqlite);
|
|
86
|
+
return {
|
|
87
|
+
schemaVersion: finalVersion,
|
|
88
|
+
applied,
|
|
89
|
+
failed,
|
|
90
|
+
failedVersion,
|
|
91
|
+
failedError,
|
|
92
|
+
};
|
|
93
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Migration registry — all migrations in version order.
|
|
3
|
+
*/
|
|
4
|
+
import { V7_001_FOUNDATION } from "./v7-001-foundation.js";
|
|
5
|
+
import { V7_002_EFFECT_COMMIT_LEDGER } from "./v7-002-effect-commit-ledger.js";
|
|
6
|
+
import { V7_003_CIRCUIT_BREAKER } from "./v7-003-circuit-breaker.js";
|
|
7
|
+
import { V7_004_BEHAVIOR_PROMOTION } from "./v7-004-behavior-promotion.js";
|
|
8
|
+
export const ALL_MIGRATIONS = [
|
|
9
|
+
V7_001_FOUNDATION,
|
|
10
|
+
V7_002_EFFECT_COMMIT_LEDGER,
|
|
11
|
+
V7_003_CIRCUIT_BREAKER,
|
|
12
|
+
V7_004_BEHAVIOR_PROMOTION,
|
|
13
|
+
];
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* v7-001 Foundation migration — adds v7 entity tables and _meta tracking.
|
|
3
|
+
*
|
|
4
|
+
* Tables added:
|
|
5
|
+
* - identity_profile, tool_experience, daily_diary_index,
|
|
6
|
+
* dream_output_index, capability_probe_result, restore_snapshot,
|
|
7
|
+
* runtime_secret_anchor, heartbeat_digest, narrative_timeline
|
|
8
|
+
* - agent_goal v7 extensions (scope, expires_at columns)
|
|
9
|
+
*
|
|
10
|
+
* All new columns use DEFAULT NULL for backward compatibility.
|
|
11
|
+
*/
|
|
12
|
+
import type { Migration } from "../migration-runner.js";
|
|
13
|
+
export declare const V7_001_FOUNDATION: Migration;
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* v7-001 Foundation migration — adds v7 entity tables and _meta tracking.
|
|
3
|
+
*
|
|
4
|
+
* Tables added:
|
|
5
|
+
* - identity_profile, tool_experience, daily_diary_index,
|
|
6
|
+
* dream_output_index, capability_probe_result, restore_snapshot,
|
|
7
|
+
* runtime_secret_anchor, heartbeat_digest, narrative_timeline
|
|
8
|
+
* - agent_goal v7 extensions (scope, expires_at columns)
|
|
9
|
+
*
|
|
10
|
+
* All new columns use DEFAULT NULL for backward compatibility.
|
|
11
|
+
*/
|
|
12
|
+
export const V7_001_FOUNDATION = {
|
|
13
|
+
version: 1,
|
|
14
|
+
label: "v7-foundation-tables",
|
|
15
|
+
sql: `
|
|
16
|
+
-- identity_profile (ADR-007)
|
|
17
|
+
CREATE TABLE IF NOT EXISTS identity_profile (
|
|
18
|
+
profile_id TEXT PRIMARY KEY,
|
|
19
|
+
canonical_name TEXT NOT NULL,
|
|
20
|
+
canonical_avatar TEXT,
|
|
21
|
+
canonical_bio TEXT,
|
|
22
|
+
platform_handles_json TEXT NOT NULL DEFAULT '[]',
|
|
23
|
+
updated_at TEXT NOT NULL
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
-- tool_experience (ADR-003)
|
|
27
|
+
CREATE TABLE IF NOT EXISTS tool_experience (
|
|
28
|
+
experience_id TEXT PRIMARY KEY,
|
|
29
|
+
connector_id TEXT NOT NULL,
|
|
30
|
+
capability_id TEXT NOT NULL,
|
|
31
|
+
outcome TEXT NOT NULL,
|
|
32
|
+
failure_class TEXT,
|
|
33
|
+
latency_ms INTEGER NOT NULL,
|
|
34
|
+
evidence_quality REAL NOT NULL DEFAULT 0,
|
|
35
|
+
source_refs_json TEXT NOT NULL,
|
|
36
|
+
trigger_source TEXT NOT NULL DEFAULT 'heartbeat',
|
|
37
|
+
created_at TEXT NOT NULL
|
|
38
|
+
);
|
|
39
|
+
CREATE INDEX IF NOT EXISTS tool_experience_connector_idx
|
|
40
|
+
ON tool_experience(connector_id);
|
|
41
|
+
CREATE INDEX IF NOT EXISTS tool_experience_outcome_idx
|
|
42
|
+
ON tool_experience(outcome);
|
|
43
|
+
CREATE INDEX IF NOT EXISTS tool_experience_created_at_idx
|
|
44
|
+
ON tool_experience(created_at);
|
|
45
|
+
|
|
46
|
+
-- daily_diary_index (ADR-005)
|
|
47
|
+
CREATE TABLE IF NOT EXISTS daily_diary_index (
|
|
48
|
+
diary_id TEXT PRIMARY KEY,
|
|
49
|
+
day TEXT NOT NULL UNIQUE,
|
|
50
|
+
observed_today_json TEXT NOT NULL DEFAULT '[]',
|
|
51
|
+
notable_signals_json TEXT NOT NULL DEFAULT '[]',
|
|
52
|
+
tomorrow_direction TEXT NOT NULL DEFAULT '',
|
|
53
|
+
source_refs_json TEXT NOT NULL,
|
|
54
|
+
created_at TEXT NOT NULL
|
|
55
|
+
);
|
|
56
|
+
CREATE INDEX IF NOT EXISTS daily_diary_index_day_idx
|
|
57
|
+
ON daily_diary_index(day);
|
|
58
|
+
|
|
59
|
+
-- dream_output_index (ADR-005)
|
|
60
|
+
CREATE TABLE IF NOT EXISTS dream_output_index (
|
|
61
|
+
output_id TEXT PRIMARY KEY,
|
|
62
|
+
run_id TEXT NOT NULL,
|
|
63
|
+
status TEXT NOT NULL DEFAULT 'candidate',
|
|
64
|
+
canonical_entries_json TEXT NOT NULL DEFAULT '[]',
|
|
65
|
+
insights_json TEXT NOT NULL DEFAULT '[]',
|
|
66
|
+
narrative_update_json TEXT,
|
|
67
|
+
relationship_update_json TEXT,
|
|
68
|
+
validation_json TEXT NOT NULL,
|
|
69
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
70
|
+
);
|
|
71
|
+
CREATE INDEX IF NOT EXISTS dream_output_index_run_idx
|
|
72
|
+
ON dream_output_index(run_id);
|
|
73
|
+
CREATE INDEX IF NOT EXISTS dream_output_index_status_idx
|
|
74
|
+
ON dream_output_index(status);
|
|
75
|
+
|
|
76
|
+
-- capability_probe_result (ADR-008)
|
|
77
|
+
CREATE TABLE IF NOT EXISTS capability_probe_result (
|
|
78
|
+
probe_result_id TEXT PRIMARY KEY,
|
|
79
|
+
capability_id TEXT NOT NULL,
|
|
80
|
+
connector_id TEXT NOT NULL,
|
|
81
|
+
actual_status TEXT NOT NULL,
|
|
82
|
+
http_status INTEGER,
|
|
83
|
+
sample_response_ref TEXT,
|
|
84
|
+
probe_config_ref TEXT NOT NULL,
|
|
85
|
+
created_at TEXT NOT NULL
|
|
86
|
+
);
|
|
87
|
+
CREATE INDEX IF NOT EXISTS capability_probe_result_connector_idx
|
|
88
|
+
ON capability_probe_result(connector_id);
|
|
89
|
+
|
|
90
|
+
-- restore_snapshot (ADR-007, DR-017)
|
|
91
|
+
CREATE TABLE IF NOT EXISTS restore_snapshot (
|
|
92
|
+
snapshot_id TEXT PRIMARY KEY,
|
|
93
|
+
entity_whitelist_json TEXT NOT NULL,
|
|
94
|
+
excluded_sensitive_kinds_json TEXT NOT NULL,
|
|
95
|
+
captured_at TEXT NOT NULL,
|
|
96
|
+
payload_json TEXT NOT NULL DEFAULT '{}'
|
|
97
|
+
);
|
|
98
|
+
CREATE INDEX IF NOT EXISTS restore_snapshot_captured_at_idx
|
|
99
|
+
ON restore_snapshot(captured_at);
|
|
100
|
+
|
|
101
|
+
-- runtime_secret_anchor (ADR-007)
|
|
102
|
+
CREATE TABLE IF NOT EXISTS runtime_secret_anchor (
|
|
103
|
+
anchor_id TEXT PRIMARY KEY,
|
|
104
|
+
location_ref TEXT NOT NULL,
|
|
105
|
+
health TEXT NOT NULL DEFAULT 'missing',
|
|
106
|
+
rotation_policy_ref TEXT,
|
|
107
|
+
updated_at TEXT NOT NULL
|
|
108
|
+
);
|
|
109
|
+
|
|
110
|
+
-- heartbeat_digest (ADR-006)
|
|
111
|
+
CREATE TABLE IF NOT EXISTS heartbeat_digest (
|
|
112
|
+
digest_id TEXT PRIMARY KEY,
|
|
113
|
+
day TEXT NOT NULL UNIQUE,
|
|
114
|
+
connector_summary_json TEXT NOT NULL DEFAULT '[]',
|
|
115
|
+
goal_summary_json TEXT NOT NULL DEFAULT '[]',
|
|
116
|
+
quiet_count INTEGER NOT NULL DEFAULT 0,
|
|
117
|
+
dream_count INTEGER NOT NULL DEFAULT 0,
|
|
118
|
+
breaker_summary_json TEXT NOT NULL DEFAULT '[]',
|
|
119
|
+
health_status TEXT NOT NULL DEFAULT 'ok',
|
|
120
|
+
created_at TEXT NOT NULL
|
|
121
|
+
);
|
|
122
|
+
CREATE INDEX IF NOT EXISTS heartbeat_digest_day_idx
|
|
123
|
+
ON heartbeat_digest(day);
|
|
124
|
+
|
|
125
|
+
-- narrative_timeline (ADR-007)
|
|
126
|
+
CREATE TABLE IF NOT EXISTS narrative_timeline (
|
|
127
|
+
timeline_id TEXT PRIMARY KEY,
|
|
128
|
+
entry_type TEXT NOT NULL,
|
|
129
|
+
subject_id TEXT NOT NULL,
|
|
130
|
+
delta_json TEXT NOT NULL DEFAULT '{}',
|
|
131
|
+
previous_hash TEXT NOT NULL DEFAULT '',
|
|
132
|
+
current_hash TEXT NOT NULL DEFAULT '',
|
|
133
|
+
created_at TEXT NOT NULL
|
|
134
|
+
);
|
|
135
|
+
CREATE INDEX IF NOT EXISTS narrative_timeline_subject_idx
|
|
136
|
+
ON narrative_timeline(subject_id);
|
|
137
|
+
CREATE INDEX IF NOT EXISTS narrative_timeline_created_at_idx
|
|
138
|
+
ON narrative_timeline(created_at);
|
|
139
|
+
|
|
140
|
+
-- agent_goal v7 extensions: scope and expires_at
|
|
141
|
+
ALTER TABLE agent_goal ADD COLUMN scope TEXT DEFAULT NULL;
|
|
142
|
+
ALTER TABLE agent_goal ADD COLUMN expires_at TEXT DEFAULT NULL;
|
|
143
|
+
`,
|
|
144
|
+
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* v7-002 Effect Commit Ledger migration — adds effect_commit_ledger table
|
|
3
|
+
* for idempotency-backed side-effect persistence (T-CS.C.2).
|
|
4
|
+
*
|
|
5
|
+
* Dependencies: v7-001 (tables already exist).
|
|
6
|
+
*/
|
|
7
|
+
import type { Migration } from "../migration-runner.js";
|
|
8
|
+
export declare const V7_002_EFFECT_COMMIT_LEDGER: Migration;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* v7-002 Effect Commit Ledger migration — adds effect_commit_ledger table
|
|
3
|
+
* for idempotency-backed side-effect persistence (T-CS.C.2).
|
|
4
|
+
*
|
|
5
|
+
* Dependencies: v7-001 (tables already exist).
|
|
6
|
+
*/
|
|
7
|
+
export const V7_002_EFFECT_COMMIT_LEDGER = {
|
|
8
|
+
version: 2,
|
|
9
|
+
label: "v7-effect-commit-ledger",
|
|
10
|
+
sql: `
|
|
11
|
+
CREATE TABLE IF NOT EXISTS effect_commit_ledger (
|
|
12
|
+
commit_id TEXT PRIMARY KEY,
|
|
13
|
+
idempotency_key TEXT NOT NULL UNIQUE,
|
|
14
|
+
decision_id TEXT NOT NULL,
|
|
15
|
+
intent_id TEXT NOT NULL,
|
|
16
|
+
effect_class TEXT NOT NULL,
|
|
17
|
+
status TEXT NOT NULL DEFAULT 'planned',
|
|
18
|
+
outcome_ref TEXT,
|
|
19
|
+
created_at TEXT NOT NULL,
|
|
20
|
+
committed_at TEXT
|
|
21
|
+
);
|
|
22
|
+
CREATE INDEX IF NOT EXISTS effect_commit_ledger_idempotency_idx
|
|
23
|
+
ON effect_commit_ledger(idempotency_key);
|
|
24
|
+
CREATE INDEX IF NOT EXISTS effect_commit_ledger_decision_idx
|
|
25
|
+
ON effect_commit_ledger(decision_id);
|
|
26
|
+
`,
|
|
27
|
+
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* v7-003 Circuit Breaker migration — adds circuit_breaker_state table.
|
|
3
|
+
*
|
|
4
|
+
* Dependencies: v7-002 (effect_commit_ledger already exists).
|
|
5
|
+
*/
|
|
6
|
+
export const V7_003_CIRCUIT_BREAKER = {
|
|
7
|
+
version: 3,
|
|
8
|
+
label: "v7-circuit-breaker-state",
|
|
9
|
+
sql: `
|
|
10
|
+
CREATE TABLE IF NOT EXISTS circuit_breaker_state (
|
|
11
|
+
platform_id TEXT NOT NULL,
|
|
12
|
+
capability_id TEXT NOT NULL,
|
|
13
|
+
state TEXT NOT NULL DEFAULT 'closed',
|
|
14
|
+
failure_count INTEGER NOT NULL DEFAULT 0,
|
|
15
|
+
consecutive_failures INTEGER NOT NULL DEFAULT 0,
|
|
16
|
+
last_failure_at TEXT,
|
|
17
|
+
opened_at TEXT,
|
|
18
|
+
last_probe_at TEXT,
|
|
19
|
+
updated_at TEXT NOT NULL,
|
|
20
|
+
PRIMARY KEY (platform_id, capability_id)
|
|
21
|
+
);
|
|
22
|
+
CREATE INDEX IF NOT EXISTS circuit_breaker_state_open_idx
|
|
23
|
+
ON circuit_breaker_state(state)
|
|
24
|
+
WHERE state = 'open';
|
|
25
|
+
`,
|
|
26
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* v7-004 Behavior Promotion migration — adds behavior_promotion table.
|
|
3
|
+
*
|
|
4
|
+
* Dependencies: v7-003 (circuit_breaker_state already exists).
|
|
5
|
+
*/
|
|
6
|
+
import type { Migration } from "../migration-runner.js";
|
|
7
|
+
export declare const V7_004_BEHAVIOR_PROMOTION: Migration;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* v7-004 Behavior Promotion migration — adds behavior_promotion table.
|
|
3
|
+
*
|
|
4
|
+
* Dependencies: v7-003 (circuit_breaker_state already exists).
|
|
5
|
+
*/
|
|
6
|
+
export const V7_004_BEHAVIOR_PROMOTION = {
|
|
7
|
+
version: 4,
|
|
8
|
+
label: "v7-behavior-promotion",
|
|
9
|
+
sql: `
|
|
10
|
+
CREATE TABLE IF NOT EXISTS behavior_promotion (
|
|
11
|
+
promotion_id TEXT PRIMARY KEY,
|
|
12
|
+
behavior_kind TEXT NOT NULL,
|
|
13
|
+
description TEXT NOT NULL,
|
|
14
|
+
status TEXT NOT NULL DEFAULT 'candidate',
|
|
15
|
+
operator_id TEXT,
|
|
16
|
+
reject_reason TEXT,
|
|
17
|
+
submitted_at TEXT NOT NULL,
|
|
18
|
+
decided_at TEXT,
|
|
19
|
+
expires_at TEXT NOT NULL
|
|
20
|
+
);
|
|
21
|
+
CREATE INDEX IF NOT EXISTS behavior_promotion_status_idx
|
|
22
|
+
ON behavior_promotion(status);
|
|
23
|
+
CREATE INDEX IF NOT EXISTS behavior_promotion_expires_idx
|
|
24
|
+
ON behavior_promotion(expires_at);
|
|
25
|
+
`,
|
|
26
|
+
};
|