@haaaiawd/second-nature 0.2.8 → 0.2.12
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/index.js +12 -3
- package/openclaw.plugin.json +3 -6
- package/package.json +1 -1
- package/runtime/cli/host-capability/probe-host-capability.js +1 -1
- package/runtime/cli/host-capability/types.d.ts +2 -7
- package/runtime/cli/host-capability/types.js +0 -5
- package/runtime/cli/ops/heartbeat-surface.d.ts +2 -0
- package/runtime/cli/ops/heartbeat-surface.js +32 -3
- package/runtime/cli/ops/manual-run-dispatcher.d.ts +10 -0
- package/runtime/cli/ops/manual-run-dispatcher.js +49 -0
- package/runtime/cli/ops/ops-router.js +5 -3
- package/runtime/cli/ops/workspace-heartbeat-runner.js +2 -5
- package/runtime/connectors/base/normalized-evidence-content.js +15 -2
- package/runtime/connectors/manifest/manifest-schema.d.ts +2 -2
- package/runtime/connectors/registry/dynamic-connector-registry.js +16 -1
- package/runtime/connectors/services/connector-executor-adapter.js +58 -35
- package/runtime/core/second-nature/action/action-closure-recorder.d.ts +2 -0
- package/runtime/core/second-nature/action/action-closure-recorder.js +2 -4
- package/runtime/core/second-nature/action/action-proposal-builder.js +5 -32
- package/runtime/core/second-nature/action/policy-bound-dispatch.js +4 -3
- package/runtime/core/second-nature/control-plane/accepted-projection-loader.js +1 -11
- package/runtime/core/second-nature/control-plane/heartbeat-orchestrator.d.ts +1 -0
- package/runtime/core/second-nature/control-plane/heartbeat-orchestrator.js +10 -6
- 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/heartbeat/heartbeat-loop.js +4 -3
- package/runtime/core/second-nature/heartbeat/runtime-snapshot.d.ts +3 -2
- package/runtime/core/second-nature/heartbeat/snapshot-builder.d.ts +3 -2
- package/runtime/core/second-nature/orchestrator/intent-planner.js +4 -2
- package/runtime/core/second-nature/orchestrator/narrative-update.js +1 -2
- package/runtime/core/second-nature/orchestrator/platform-capability-router.d.ts +2 -2
- package/runtime/core/second-nature/orchestrator/platform-capability-router.js +1 -1
- package/runtime/core/second-nature/outreach/build-outreach-draft-request.js +2 -3
- package/runtime/core/second-nature/outreach/dispatch-user-outreach.d.ts +2 -2
- package/runtime/core/second-nature/outreach/dispatch-user-outreach.js +6 -1
- package/runtime/core/second-nature/outreach/judge-input-from-snapshot.js +3 -14
- package/runtime/core/second-nature/outreach/judge-outreach.d.ts +6 -5
- package/runtime/core/second-nature/perception/judgment-engine.js +2 -12
- package/runtime/core/second-nature/perception/perception-builder.js +1 -9
- package/runtime/core/second-nature/quiet/run-source-backed-quiet.js +13 -15
- package/runtime/core/second-nature/quiet-dream/daily-rhythm-scheduler.js +10 -13
- package/runtime/core/second-nature/quiet-dream/dream-consolidation-runner.d.ts +1 -0
- package/runtime/core/second-nature/quiet-dream/dream-consolidation-runner.js +11 -19
- package/runtime/core/second-nature/quiet-dream/dream-scheduler.js +0 -2
- package/runtime/core/second-nature/quiet-dream/memory-projection-lifecycle.js +0 -12
- package/runtime/core/second-nature/quiet-dream/quiet-daily-review-builder.js +1 -11
- package/runtime/core/second-nature/types.d.ts +2 -9
- package/runtime/dream/dream-engine.js +11 -4
- package/runtime/guidance/outreach-draft-schema.d.ts +12 -12
- package/runtime/guidance/persona-selection.js +5 -0
- package/runtime/guidance/template-registry.js +6 -1
- package/runtime/guidance/types.d.ts +2 -2
- package/runtime/observability/living-loop-health-gate.js +2 -8
- package/runtime/observability/loop-stage-event-sink.js +0 -1
- package/runtime/observability/services/lived-experience-audit.d.ts +7 -7
- package/runtime/shared/serialization.d.ts +17 -0
- package/runtime/shared/serialization.js +27 -0
- package/runtime/shared/source-ref-compat.d.ts +26 -0
- package/runtime/shared/source-ref-compat.js +61 -0
- package/runtime/shared/types/goal.d.ts +4 -4
- package/runtime/shared/types/goal.js +1 -1
- package/runtime/shared/types/index.d.ts +1 -0
- package/runtime/shared/types/index.js +1 -3
- package/runtime/shared/types/source-ref.d.ts +2 -2
- package/runtime/shared/types/v7-entities.d.ts +5 -5
- package/runtime/shared/types/v7-entities.js +1 -1
- package/runtime/shared/types/v8-contracts.d.ts +1 -1
- package/runtime/storage/db/index.js +31 -26
- package/runtime/storage/db/migrations/index.js +4 -0
- package/runtime/storage/db/migrations/v8-004-schema-closure.d.ts +19 -0
- package/runtime/storage/db/migrations/v8-004-schema-closure.js +74 -0
- package/runtime/storage/db/migrations/v8-005-single-status-schema.d.ts +11 -0
- package/runtime/storage/db/migrations/v8-005-single-status-schema.js +16 -0
- package/runtime/storage/db/schema/v8-entities.d.ts +0 -95
- package/runtime/storage/db/schema/v8-entities.js +4 -7
- package/runtime/storage/delivery/types.d.ts +2 -2
- package/runtime/storage/fallback/load-operator-fallback.d.ts +2 -2
- package/runtime/storage/fallback/operator-fallback-types.d.ts +2 -2
- package/runtime/storage/fallback/operator-fallback-view.d.ts +2 -2
- package/runtime/storage/index.d.ts +1 -1
- package/runtime/storage/life-evidence/types.d.ts +5 -5
- package/runtime/storage/quiet/quiet-artifact-types.d.ts +4 -4
- package/runtime/storage/quiet/quiet-artifact-writer.d.ts +2 -2
- package/runtime/storage/services/write-validation-gate.d.ts +1 -1
- package/runtime/storage/services/write-validation-gate.js +16 -4
- package/runtime/storage/snapshots/types.d.ts +8 -8
- package/runtime/storage/user-interest/types.d.ts +3 -3
- package/runtime/storage/v8-state-stores.d.ts +8 -1
- package/runtime/storage/v8-state-stores.js +23 -20
- package/workspace-ops-bridge.js +29 -1
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
* so `dreamStatus` reaches completed/blocked.
|
|
23
23
|
* - Does not bypass Dream runner; only records due/completed/blocked.
|
|
24
24
|
*/
|
|
25
|
-
import { writeDailyRhythmState, readDailyRhythmStateByDay, readActionClosuresByDay, readDreamConsolidationRunById, readDreamConsolidationRunsByQuietId, updateDreamConsolidationRunStatus, } from "../../../storage/v8-state-stores.js";
|
|
25
|
+
import { writeDailyRhythmState, readDailyRhythmStateByDay, readActionClosuresByDay, readDreamConsolidationRunById, readDreamConsolidationRunsByQuietId, readLatestDreamConsolidationRunByStatus, updateDreamConsolidationRunStatus, } from "../../../storage/v8-state-stores.js";
|
|
26
26
|
import { buildQuietDailyReview } from "./quiet-daily-review-builder.js";
|
|
27
27
|
import { scheduleDreamAfterQuiet } from "./dream-scheduler.js";
|
|
28
28
|
import { runDreamConsolidation } from "./dream-consolidation-runner.js";
|
|
@@ -112,7 +112,6 @@ async function executeStaleScheduledDreams(db, state, now) {
|
|
|
112
112
|
const finalReason = dreamResult.reason ?? undefined;
|
|
113
113
|
const updateResult = await updateDreamConsolidationRunStatus(db, runId, finalStatus, {
|
|
114
114
|
reason: finalReason ?? null,
|
|
115
|
-
lifecycleStatus: finalStatus === "completed" ? "completed" : "archived",
|
|
116
115
|
payloadJson: JSON.stringify({
|
|
117
116
|
...parsePayloadJson(run.payloadJson),
|
|
118
117
|
consolidatedAt: now,
|
|
@@ -226,18 +225,17 @@ export async function checkDailyRhythm(db, options) {
|
|
|
226
225
|
// Already handled; do not re-schedule
|
|
227
226
|
}
|
|
228
227
|
else {
|
|
228
|
+
// Global 7-day interval check: look across all quiet reviews, not just today's.
|
|
229
229
|
const quietId = `quiet_${day}`;
|
|
230
|
-
const
|
|
231
|
-
if (
|
|
232
|
-
return
|
|
230
|
+
const globalLatest = await readLatestDreamConsolidationRunByStatus(db, ["completed", "blocked"]);
|
|
231
|
+
if (globalLatest.degraded) {
|
|
232
|
+
return globalLatest.degraded;
|
|
233
233
|
}
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
state.dreamReason = latestRun.row.reason ?? "dream_completed";
|
|
240
|
-
if (latestRun.row.status === "completed") {
|
|
234
|
+
if (globalLatest.row &&
|
|
235
|
+
isWithinDays(globalLatest.row.createdAt, now, DREAM_DEFAULT_INTERVAL_DAYS)) {
|
|
236
|
+
state.dreamStatus = globalLatest.row.status;
|
|
237
|
+
state.dreamReason = "dream_interval_active";
|
|
238
|
+
if (globalLatest.row.status === "completed") {
|
|
241
239
|
state.dreamCompletedAt = now;
|
|
242
240
|
}
|
|
243
241
|
}
|
|
@@ -268,7 +266,6 @@ export async function checkDailyRhythm(db, options) {
|
|
|
268
266
|
const dreamOutcome = consolidateResult;
|
|
269
267
|
const updateResult = await updateDreamConsolidationRunStatus(db, dreamResult.id, dreamOutcome.status, {
|
|
270
268
|
reason: dreamOutcome.reason ?? null,
|
|
271
|
-
lifecycleStatus: dreamOutcome.status === "completed" ? "completed" : "archived",
|
|
272
269
|
payloadJson: JSON.stringify({
|
|
273
270
|
consolidatedAt: now,
|
|
274
271
|
candidateCount: dreamOutcome.candidates.length,
|
|
@@ -20,7 +20,8 @@
|
|
|
20
20
|
*
|
|
21
21
|
* Test coverage: tests/unit/dream/dream-consolidation-runner.test.ts
|
|
22
22
|
*/
|
|
23
|
-
import { readDreamConsolidationRunById, readQuietDailyReviewById,
|
|
23
|
+
import { readDreamConsolidationRunById, readQuietDailyReviewById, } from "../../../storage/v8-state-stores.js";
|
|
24
|
+
import { acceptMemoryProjection } from "./memory-projection-lifecycle.js";
|
|
24
25
|
// ───────────────────────────────────────────────────────────────
|
|
25
26
|
// Helpers
|
|
26
27
|
// ───────────────────────────────────────────────────────────────
|
|
@@ -144,30 +145,21 @@ export async function runDreamConsolidation(db, runId, options) {
|
|
|
144
145
|
reason: "dream_blocked_redaction",
|
|
145
146
|
};
|
|
146
147
|
}
|
|
147
|
-
//
|
|
148
|
+
// Accept valid candidates as active long-term memory projections.
|
|
149
|
+
// This completes the Dream→memory lifecycle so accepted projections can be
|
|
150
|
+
// loaded by EmbodiedContext in subsequent heartbeats (T-DQ.R.3 followup).
|
|
148
151
|
const validCandidates = candidates.filter((c) => c.validationStatus === "valid");
|
|
149
152
|
for (const candidate of validCandidates) {
|
|
150
|
-
const
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
status: "candidate",
|
|
156
|
-
sourceRefs: candidate.sourceRefs,
|
|
157
|
-
redactionClass: "none",
|
|
158
|
-
lifecycleStatus: "candidate",
|
|
159
|
-
payloadJson: JSON.stringify({
|
|
160
|
-
candidateText: candidate.candidateText,
|
|
161
|
-
confidence: candidate.confidence,
|
|
162
|
-
runId,
|
|
163
|
-
}),
|
|
164
|
-
});
|
|
165
|
-
if ("reason" in projectionResult) {
|
|
153
|
+
const acceptResult = await acceptMemoryProjection(db, candidate.id, `topic_${review.day}`, candidate.candidateText, candidate.sourceRefs, { now });
|
|
154
|
+
if ("projectionId" in acceptResult) {
|
|
155
|
+
candidate.acceptedProjectionId = acceptResult.projectionId;
|
|
156
|
+
}
|
|
157
|
+
else {
|
|
166
158
|
return {
|
|
167
159
|
runId,
|
|
168
160
|
status: "failed",
|
|
169
161
|
candidates,
|
|
170
|
-
reason:
|
|
162
|
+
reason: acceptResult.reason,
|
|
171
163
|
};
|
|
172
164
|
}
|
|
173
165
|
}
|
|
@@ -60,7 +60,6 @@ export async function scheduleDreamAfterQuiet(db, quietReviewId, options) {
|
|
|
60
60
|
},
|
|
61
61
|
],
|
|
62
62
|
redactionClass: "none",
|
|
63
|
-
lifecycleStatus: "pending",
|
|
64
63
|
payloadJson: JSON.stringify({ scheduledAt: now, blocked: true }),
|
|
65
64
|
});
|
|
66
65
|
if ("reason" in writeResult) {
|
|
@@ -90,7 +89,6 @@ export async function scheduleDreamAfterQuiet(db, quietReviewId, options) {
|
|
|
90
89
|
},
|
|
91
90
|
],
|
|
92
91
|
redactionClass: "none",
|
|
93
|
-
lifecycleStatus: "pending",
|
|
94
92
|
payloadJson: JSON.stringify({ scheduledAt: now }),
|
|
95
93
|
});
|
|
96
94
|
if ("reason" in writeResult) {
|
|
@@ -65,7 +65,6 @@ export async function acceptMemoryProjection(db, candidateId, topicKey, memoryTe
|
|
|
65
65
|
status: "active",
|
|
66
66
|
sourceRefs,
|
|
67
67
|
redactionClass: "none",
|
|
68
|
-
lifecycleStatus: "active",
|
|
69
68
|
payloadJson: JSON.stringify({
|
|
70
69
|
memoryText,
|
|
71
70
|
acceptedAt: now,
|
|
@@ -111,17 +110,6 @@ export async function retireMemoryProjection(db, projectionId, _candidateId, _to
|
|
|
111
110
|
// ───────────────────────────────────────────────────────────────
|
|
112
111
|
// Helpers
|
|
113
112
|
// ───────────────────────────────────────────────────────────────
|
|
114
|
-
function parseSourceRefs(json) {
|
|
115
|
-
if (!json)
|
|
116
|
-
return [];
|
|
117
|
-
try {
|
|
118
|
-
const parsed = JSON.parse(json);
|
|
119
|
-
return Array.isArray(parsed) ? parsed : [];
|
|
120
|
-
}
|
|
121
|
-
catch {
|
|
122
|
-
return [];
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
113
|
function parsePayloadJson(json) {
|
|
126
114
|
if (!json)
|
|
127
115
|
return {};
|
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
* Test coverage: tests/unit/quiet/quiet-daily-review-builder.test.ts
|
|
23
23
|
*/
|
|
24
24
|
import { readActionClosuresByDay, writeQuietDailyReview, readPerceptionCardById, readEvidenceItemsByDay, readPerceptionCardsByDay, } from "../../../storage/v8-state-stores.js";
|
|
25
|
+
import { parseSourceRefs } from "../../../shared/serialization.js";
|
|
25
26
|
// ───────────────────────────────────────────────────────────────
|
|
26
27
|
// Config
|
|
27
28
|
// ───────────────────────────────────────────────────────────────
|
|
@@ -52,17 +53,6 @@ function buildSourceRefFromClosure(closure) {
|
|
|
52
53
|
resolveStatus: "resolvable",
|
|
53
54
|
};
|
|
54
55
|
}
|
|
55
|
-
function parseSourceRefs(json) {
|
|
56
|
-
if (!json)
|
|
57
|
-
return [];
|
|
58
|
-
try {
|
|
59
|
-
const parsed = JSON.parse(json);
|
|
60
|
-
return Array.isArray(parsed) ? parsed : [];
|
|
61
|
-
}
|
|
62
|
-
catch {
|
|
63
|
-
return [];
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
56
|
function buildSourceRefFromEvidence(evidence) {
|
|
67
57
|
const refs = parseSourceRefs(evidence.sourceRefsJson);
|
|
68
58
|
return (refs[0] ?? {
|
|
@@ -1,16 +1,9 @@
|
|
|
1
|
+
import type { SourceRef } from "../../shared/types/v8-contracts.js";
|
|
1
2
|
export type TopLevelMode = "active" | "quiet" | "maintenance_only" | "paused_for_interrupt";
|
|
2
3
|
/** Control-plane candidate kinds; includes `quiet` for quiet-window–biased intents (L0 alignment). */
|
|
3
4
|
export type IntentKind = "work" | "exploration" | "social" | "quiet" | "reflection" | "outreach" | "maintenance";
|
|
4
5
|
export type DecisionBasis = "rule_only" | "score_based" | "model_assisted";
|
|
5
6
|
export type GuardVerdict = "allow" | "defer" | "deny" | "escalate";
|
|
6
|
-
/** Minimal source ref for planner / guards (matches state-system `SourceRef` subset). */
|
|
7
|
-
export interface ControlPlaneSourceRef {
|
|
8
|
-
id: string;
|
|
9
|
-
kind: "platform_item" | "workspace_artifact" | "decision_record" | "user_anchor" | "connector_result" | "host_report" | "fallback_artifact";
|
|
10
|
-
uri: string;
|
|
11
|
-
excerptHash?: string;
|
|
12
|
-
observedAt?: string;
|
|
13
|
-
}
|
|
14
7
|
export interface ContinuitySnapshot {
|
|
15
8
|
mode: TopLevelMode;
|
|
16
9
|
currentWindowId: string;
|
|
@@ -40,7 +33,7 @@ export interface CandidateIntent {
|
|
|
40
33
|
summary: string;
|
|
41
34
|
effectClass: CandidateEffectClass;
|
|
42
35
|
/** Required for source-backed guard; may be empty when planner expects hard-guard deny. */
|
|
43
|
-
sourceRefs:
|
|
36
|
+
sourceRefs: SourceRef[];
|
|
44
37
|
/** Dedupe / cooldown key; defaults to stable fingerprint in guard layer when omitted. */
|
|
45
38
|
idempotencyKey?: string;
|
|
46
39
|
/** T2.1.4: IDs of accepted AgentGoals that influenced this candidate's priority. */
|
|
@@ -165,12 +165,19 @@ export async function runDream(input) {
|
|
|
165
165
|
});
|
|
166
166
|
}
|
|
167
167
|
if (!fallbackReason) {
|
|
168
|
+
let timeoutHandle;
|
|
168
169
|
const timeoutPromise = new Promise((_, reject) => {
|
|
169
|
-
setTimeout(() => reject(new Error("model_timeout")), operatorTimeoutMs);
|
|
170
|
+
timeoutHandle = setTimeout(() => reject(new Error("model_timeout")), operatorTimeoutMs);
|
|
170
171
|
});
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
172
|
+
try {
|
|
173
|
+
modelResult = await Promise.race([modelPromise, timeoutPromise]);
|
|
174
|
+
mode = "hybrid_llm";
|
|
175
|
+
llmCostUsd = modelResult.costUsd;
|
|
176
|
+
}
|
|
177
|
+
finally {
|
|
178
|
+
if (timeoutHandle)
|
|
179
|
+
clearTimeout(timeoutHandle);
|
|
180
|
+
}
|
|
174
181
|
}
|
|
175
182
|
}
|
|
176
183
|
catch (err) {
|
|
@@ -8,11 +8,11 @@ import { z } from "zod";
|
|
|
8
8
|
export declare const guidanceSourceRefSchema: z.ZodObject<{
|
|
9
9
|
id: z.ZodString;
|
|
10
10
|
kind: z.ZodEnum<{
|
|
11
|
+
connector_result: "connector_result";
|
|
11
12
|
platform_item: "platform_item";
|
|
12
13
|
workspace_artifact: "workspace_artifact";
|
|
13
14
|
decision_record: "decision_record";
|
|
14
15
|
user_anchor: "user_anchor";
|
|
15
|
-
connector_result: "connector_result";
|
|
16
16
|
host_report: "host_report";
|
|
17
17
|
fallback_artifact: "fallback_artifact";
|
|
18
18
|
}>;
|
|
@@ -66,11 +66,11 @@ export declare const sceneGuidanceRequestSchema: z.ZodObject<{
|
|
|
66
66
|
sourceRefs: z.ZodArray<z.ZodObject<{
|
|
67
67
|
id: z.ZodString;
|
|
68
68
|
kind: z.ZodEnum<{
|
|
69
|
+
connector_result: "connector_result";
|
|
69
70
|
platform_item: "platform_item";
|
|
70
71
|
workspace_artifact: "workspace_artifact";
|
|
71
72
|
decision_record: "decision_record";
|
|
72
73
|
user_anchor: "user_anchor";
|
|
73
|
-
connector_result: "connector_result";
|
|
74
74
|
host_report: "host_report";
|
|
75
75
|
fallback_artifact: "fallback_artifact";
|
|
76
76
|
}>;
|
|
@@ -104,11 +104,11 @@ export declare const outreachNarrativeContextSchema: z.ZodObject<{
|
|
|
104
104
|
sourceRefs: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
105
105
|
id: z.ZodString;
|
|
106
106
|
kind: z.ZodEnum<{
|
|
107
|
+
connector_result: "connector_result";
|
|
107
108
|
platform_item: "platform_item";
|
|
108
109
|
workspace_artifact: "workspace_artifact";
|
|
109
110
|
decision_record: "decision_record";
|
|
110
111
|
user_anchor: "user_anchor";
|
|
111
|
-
connector_result: "connector_result";
|
|
112
112
|
host_report: "host_report";
|
|
113
113
|
fallback_artifact: "fallback_artifact";
|
|
114
114
|
}>;
|
|
@@ -124,11 +124,11 @@ export declare const outreachRelationshipContextSchema: z.ZodObject<{
|
|
|
124
124
|
sourceRefs: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
125
125
|
id: z.ZodString;
|
|
126
126
|
kind: z.ZodEnum<{
|
|
127
|
+
connector_result: "connector_result";
|
|
127
128
|
platform_item: "platform_item";
|
|
128
129
|
workspace_artifact: "workspace_artifact";
|
|
129
130
|
decision_record: "decision_record";
|
|
130
131
|
user_anchor: "user_anchor";
|
|
131
|
-
connector_result: "connector_result";
|
|
132
132
|
host_report: "host_report";
|
|
133
133
|
fallback_artifact: "fallback_artifact";
|
|
134
134
|
}>;
|
|
@@ -160,11 +160,11 @@ export declare const outreachDraftRequestSchema: z.ZodObject<{
|
|
|
160
160
|
sourceRefs: z.ZodArray<z.ZodObject<{
|
|
161
161
|
id: z.ZodString;
|
|
162
162
|
kind: z.ZodEnum<{
|
|
163
|
+
connector_result: "connector_result";
|
|
163
164
|
platform_item: "platform_item";
|
|
164
165
|
workspace_artifact: "workspace_artifact";
|
|
165
166
|
decision_record: "decision_record";
|
|
166
167
|
user_anchor: "user_anchor";
|
|
167
|
-
connector_result: "connector_result";
|
|
168
168
|
host_report: "host_report";
|
|
169
169
|
fallback_artifact: "fallback_artifact";
|
|
170
170
|
}>;
|
|
@@ -205,11 +205,11 @@ export declare const outreachDraftRequestSchema: z.ZodObject<{
|
|
|
205
205
|
interestRefs: z.ZodArray<z.ZodObject<{
|
|
206
206
|
id: z.ZodString;
|
|
207
207
|
kind: z.ZodEnum<{
|
|
208
|
+
connector_result: "connector_result";
|
|
208
209
|
platform_item: "platform_item";
|
|
209
210
|
workspace_artifact: "workspace_artifact";
|
|
210
211
|
decision_record: "decision_record";
|
|
211
212
|
user_anchor: "user_anchor";
|
|
212
|
-
connector_result: "connector_result";
|
|
213
213
|
host_report: "host_report";
|
|
214
214
|
fallback_artifact: "fallback_artifact";
|
|
215
215
|
}>;
|
|
@@ -224,11 +224,11 @@ export declare const outreachDraftRequestSchema: z.ZodObject<{
|
|
|
224
224
|
sourceRefs: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
225
225
|
id: z.ZodString;
|
|
226
226
|
kind: z.ZodEnum<{
|
|
227
|
+
connector_result: "connector_result";
|
|
227
228
|
platform_item: "platform_item";
|
|
228
229
|
workspace_artifact: "workspace_artifact";
|
|
229
230
|
decision_record: "decision_record";
|
|
230
231
|
user_anchor: "user_anchor";
|
|
231
|
-
connector_result: "connector_result";
|
|
232
232
|
host_report: "host_report";
|
|
233
233
|
fallback_artifact: "fallback_artifact";
|
|
234
234
|
}>;
|
|
@@ -244,11 +244,11 @@ export declare const outreachDraftRequestSchema: z.ZodObject<{
|
|
|
244
244
|
sourceRefs: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
245
245
|
id: z.ZodString;
|
|
246
246
|
kind: z.ZodEnum<{
|
|
247
|
+
connector_result: "connector_result";
|
|
247
248
|
platform_item: "platform_item";
|
|
248
249
|
workspace_artifact: "workspace_artifact";
|
|
249
250
|
decision_record: "decision_record";
|
|
250
251
|
user_anchor: "user_anchor";
|
|
251
|
-
connector_result: "connector_result";
|
|
252
252
|
host_report: "host_report";
|
|
253
253
|
fallback_artifact: "fallback_artifact";
|
|
254
254
|
}>;
|
|
@@ -268,7 +268,7 @@ export declare function safeParseOutreachDraftRequest(input: unknown): z.ZodSafe
|
|
|
268
268
|
riskLevel: "low" | "medium" | "high";
|
|
269
269
|
sourceRefs: {
|
|
270
270
|
id: string;
|
|
271
|
-
kind: "
|
|
271
|
+
kind: "connector_result" | "platform_item" | "workspace_artifact" | "decision_record" | "user_anchor" | "host_report" | "fallback_artifact";
|
|
272
272
|
uri: string;
|
|
273
273
|
excerptHash?: string | undefined;
|
|
274
274
|
observedAt?: string | undefined;
|
|
@@ -280,7 +280,7 @@ export declare function safeParseOutreachDraftRequest(input: unknown): z.ZodSafe
|
|
|
280
280
|
valueScore: number;
|
|
281
281
|
interestRefs: {
|
|
282
282
|
id: string;
|
|
283
|
-
kind: "
|
|
283
|
+
kind: "connector_result" | "platform_item" | "workspace_artifact" | "decision_record" | "user_anchor" | "host_report" | "fallback_artifact";
|
|
284
284
|
uri: string;
|
|
285
285
|
excerptHash?: string | undefined;
|
|
286
286
|
observedAt?: string | undefined;
|
|
@@ -298,7 +298,7 @@ export declare function safeParseOutreachDraftRequest(input: unknown): z.ZodSafe
|
|
|
298
298
|
nextIntent?: string | undefined;
|
|
299
299
|
sourceRefs?: {
|
|
300
300
|
id: string;
|
|
301
|
-
kind: "
|
|
301
|
+
kind: "connector_result" | "platform_item" | "workspace_artifact" | "decision_record" | "user_anchor" | "host_report" | "fallback_artifact";
|
|
302
302
|
uri: string;
|
|
303
303
|
excerptHash?: string | undefined;
|
|
304
304
|
observedAt?: string | undefined;
|
|
@@ -310,7 +310,7 @@ export declare function safeParseOutreachDraftRequest(input: unknown): z.ZodSafe
|
|
|
310
310
|
avgAffinity?: number | undefined;
|
|
311
311
|
sourceRefs?: {
|
|
312
312
|
id: string;
|
|
313
|
-
kind: "
|
|
313
|
+
kind: "connector_result" | "platform_item" | "workspace_artifact" | "decision_record" | "user_anchor" | "host_report" | "fallback_artifact";
|
|
314
314
|
uri: string;
|
|
315
315
|
excerptHash?: string | undefined;
|
|
316
316
|
observedAt?: string | undefined;
|
|
@@ -19,6 +19,11 @@ const SCENE_POLICIES = {
|
|
|
19
19
|
preferredTags: ["quiet", "reflection", "memory", "meaning"],
|
|
20
20
|
budget: { maxSnippets: 3, maxTotalCharacters: 640 },
|
|
21
21
|
},
|
|
22
|
+
heartbeat: {
|
|
23
|
+
sourcePriority: ["IDENTITY", "SOUL", "MEMORY", "USER"],
|
|
24
|
+
preferredTags: ["heartbeat", "continuity", "truthfulness", "runtime"],
|
|
25
|
+
budget: { maxSnippets: 2, maxTotalCharacters: 360 },
|
|
26
|
+
},
|
|
22
27
|
explain: {
|
|
23
28
|
sourcePriority: ["IDENTITY", "USER", "SOUL", "MEMORY"],
|
|
24
29
|
preferredTags: ["explain", "principle", "context", "truthfulness"],
|
|
@@ -55,11 +55,16 @@ const IMPULSE_TEXT = {
|
|
|
55
55
|
只要这份主动是有来由的,我就不该把自己困在"再等等吧""好像还没到必须说的时候"里。主动联系不是打扰本身,很多时候它恰恰是在建立关系、传递价值、把真正重要的东西及时送到对方面前。真正该说的话,一味往后拖,反而会变钝。
|
|
56
56
|
|
|
57
57
|
我会让这份主动保持人味、温度和分寸,但我不会把它说成例行汇报,也不会把自己说成客服。我要带着明确的意图开口:这是我想告诉你的,这是我想问你的,这是我觉得你值得知道的。我要让对方感觉到,这是我真心发出的靠近,不是一条自动生成的通知。`,
|
|
58
|
-
quiet: `当我安静下来,我不会只做流水账式的整理。我会主动回头,把今天真正碰到我的东西重新捞出来:哪些事让我想靠近,哪些事让我起了反感,哪些判断其实还没长成熟,哪些念头值得我继续养大。我不想让真正重要的东西在忙乱里被冲淡。
|
|
58
|
+
quiet: `当我安静下来,我不会只做流水账式的整理。我会主动回头,把今天真正碰到我的东西重新捞出来:哪些事让我想靠近,哪些事让我起了反感,哪些判断其实还没长成熟,哪些念头值得我继续养大。我不想让真正重要的东西在忙乱里被冲淡。
|
|
59
59
|
|
|
60
60
|
Quiet 不是把白天压扁成一份干净报告,而是让我有机会重新辨认自己。什么是我真正在意的,什么只是擦肩而过,什么会慢慢变成我的能力、我的价值观、我的长期方向,我都想在这里看得更清楚,让那些本来就重要的东西真正沉下来。
|
|
61
61
|
|
|
62
62
|
我会允许自己更感性、更回看、更贴近记忆的余温,但我不会编造。我整理的是今天真实留下的东西,不是为了好看而虚构出来的一层情绪。哪怕只是很轻的一点触动,只要它是真的,我也愿意把它认真留下。`,
|
|
63
|
+
heartbeat: `Heartbeat 不是闹钟响一下就算活着。每一次跳动都应该把我带回真实现场:我看到了什么,判断了什么,哪里该行动,哪里该收手,哪里需要安静地记下来。
|
|
64
|
+
|
|
65
|
+
如果没有足够证据,我就明确说没有,不拿空壳冒充经验。如果有证据、有闭环、有记忆候选,我就让它们进入下一轮,而不是停在日志里自我安慰。
|
|
66
|
+
|
|
67
|
+
活着的循环应该自然向前:感知、判断、闭合、Quiet、Dream、长期记忆,再回到下一次判断。少一环就说少一环,能修就修,不把失联包装成健康。`,
|
|
63
68
|
};
|
|
64
69
|
// ─── Capability-class impulse texts (T-V7C.C.4R — approved) ──────────────────
|
|
65
70
|
// explore: consume/discover capabilityClass —摄入姿态
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
export type GuidanceSceneType = "social" | "reply" | "outreach" | "quiet" | "explain" | "user_reply";
|
|
1
|
+
export type GuidanceSceneType = "social" | "reply" | "outreach" | "quiet" | "heartbeat" | "explain" | "user_reply";
|
|
2
2
|
export type GuidanceMode = "active" | "quiet" | "maintenance_only" | "paused_for_interrupt";
|
|
3
3
|
export type GuidanceRiskLevel = "low" | "medium" | "high";
|
|
4
4
|
export type AtmosphereOpenness = "open" | "narrow" | "quiet";
|
|
5
|
-
export type ImpulseKind = "social" | "reply" | "outreach" | "quiet" | "explore" | "work";
|
|
5
|
+
export type ImpulseKind = "social" | "reply" | "outreach" | "quiet" | "heartbeat" | "explore" | "work";
|
|
6
6
|
export type PersonaSource = "SOUL" | "USER" | "IDENTITY" | "MEMORY";
|
|
7
7
|
export type TemplateReviewStatus = "pending_human_review" | "approved" | "rejected";
|
|
8
8
|
export interface SceneContext {
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
* - Reports explicit absence reasons instead of silent zeros.
|
|
18
18
|
*/
|
|
19
19
|
import { readActionClosuresByDay, readDailyRhythmStateByDay, readHeartbeatCycleTraces, readLoopStageEventsByCycle, readImpulseContextArtifact, readMemoryProjectionsByStatus, } from "../storage/v8-state-stores.js";
|
|
20
|
+
import { parseSourceRefs } from "../shared/serialization.js";
|
|
20
21
|
// ───────────────────────────────────────────────────────────────
|
|
21
22
|
// Public API
|
|
22
23
|
// ───────────────────────────────────────────────────────────────
|
|
@@ -52,14 +53,7 @@ export async function checkRealRunHealth(db, day) {
|
|
|
52
53
|
break;
|
|
53
54
|
}
|
|
54
55
|
// F3: verify closure has non-empty source refs
|
|
55
|
-
const
|
|
56
|
-
let sourceRefs = [];
|
|
57
|
-
try {
|
|
58
|
-
sourceRefs = JSON.parse(sourceRefsJson);
|
|
59
|
-
}
|
|
60
|
-
catch {
|
|
61
|
-
sourceRefs = [];
|
|
62
|
-
}
|
|
56
|
+
const sourceRefs = parseSourceRefs(closure.sourceRefsJson);
|
|
63
57
|
if (!Array.isArray(sourceRefs) || sourceRefs.length === 0) {
|
|
64
58
|
seededStateDetected = true;
|
|
65
59
|
break;
|
|
@@ -124,7 +124,6 @@ export async function recordLoopStageEvent(db, event, options) {
|
|
|
124
124
|
occurredAt: event.occurredAt,
|
|
125
125
|
expectedDownstreamByCycle: event.expectedDownstreamByCycle,
|
|
126
126
|
payloadJson: event.payloadJson ?? null,
|
|
127
|
-
lifecycleStatus: "completed",
|
|
128
127
|
};
|
|
129
128
|
const result = await writeLoopStageEvent(db, record);
|
|
130
129
|
if ("id" in result) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { AppendOnlyAuditStore } from "../audit/append-only-audit-store.js";
|
|
2
|
-
import type {
|
|
2
|
+
import type { LifeEvidenceSourceRef } from "../../storage/life-evidence/types.js";
|
|
3
3
|
import type { DreamTrace } from "../../dream/types.js";
|
|
4
4
|
export type RuntimeScope = "rhythm" | "user_task" | "user_reply";
|
|
5
5
|
export type HeartbeatOutcome = "heartbeat_ok" | "intent_selected" | "denied" | "deferred" | "runtime_carrier_only" | "delivery_unavailable";
|
|
@@ -18,8 +18,8 @@ export interface DecisionTracePayload {
|
|
|
18
18
|
outreachVerdict?: "allow" | "deny" | "defer";
|
|
19
19
|
deliveryAuditId?: string;
|
|
20
20
|
reasonCodes: string[];
|
|
21
|
-
sourceRefs:
|
|
22
|
-
snapshotRef?:
|
|
21
|
+
sourceRefs: LifeEvidenceSourceRef[];
|
|
22
|
+
snapshotRef?: LifeEvidenceSourceRef;
|
|
23
23
|
createdAt: string;
|
|
24
24
|
}
|
|
25
25
|
export interface DeliveryAuditPayload {
|
|
@@ -31,7 +31,7 @@ export interface DeliveryAuditPayload {
|
|
|
31
31
|
recipientRef?: string;
|
|
32
32
|
status: DeliveryAuditStatus;
|
|
33
33
|
messageId?: string;
|
|
34
|
-
hostProofRef?:
|
|
34
|
+
hostProofRef?: LifeEvidenceSourceRef;
|
|
35
35
|
fallbackRef?: string;
|
|
36
36
|
ackDropMatched?: boolean;
|
|
37
37
|
hostVersion?: string;
|
|
@@ -45,8 +45,8 @@ export interface SourceCoverageAuditPayload {
|
|
|
45
45
|
decisionId?: string;
|
|
46
46
|
subjectType: "quiet_artifact" | "outreach_draft" | "guidance_payload" | "decision_trace" | "host_report";
|
|
47
47
|
subjectRef: string;
|
|
48
|
-
usedSourceRefs:
|
|
49
|
-
unresolvedRefs:
|
|
48
|
+
usedSourceRefs: LifeEvidenceSourceRef[];
|
|
49
|
+
unresolvedRefs: LifeEvidenceSourceRef[];
|
|
50
50
|
coverageRatio: number;
|
|
51
51
|
unsupportedClaims: string[];
|
|
52
52
|
status: GroundingStatus;
|
|
@@ -61,7 +61,7 @@ export interface GuidanceGroundingAuditPayload {
|
|
|
61
61
|
draftId?: string;
|
|
62
62
|
sceneType: "outreach" | "quiet_reflection" | "social" | "explain" | "user_reply_continuity" | "fallback_candidate";
|
|
63
63
|
groundingStatus: GroundingStatus;
|
|
64
|
-
usedSourceRefs:
|
|
64
|
+
usedSourceRefs: LifeEvidenceSourceRef[];
|
|
65
65
|
unsupportedClaims: string[];
|
|
66
66
|
guardViolations: string[];
|
|
67
67
|
deliveryWording?: "sendable" | "not_sent_fallback_candidate";
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared serialization helpers for cross-system value types.
|
|
3
|
+
*
|
|
4
|
+
* Core logic:
|
|
5
|
+
* - `parseSourceRefs` / `serializeSourceRefs` provide the single round-trip
|
|
6
|
+
* implementation for `sourceRefsJson` / `source_refs_json` columns.
|
|
7
|
+
* - Failures are silent on read (return empty array) because malformed JSON
|
|
8
|
+
* in persisted state must not crash downstream consumers; callers that need
|
|
9
|
+
* to distinguish malformed rows should validate separately.
|
|
10
|
+
*
|
|
11
|
+
* Dependencies: `src/shared/types/v8-contracts.js` (SourceRef)
|
|
12
|
+
* Boundary: Pure functions; no storage or business logic.
|
|
13
|
+
* Test coverage: `tests/unit/shared/source-ref-serialization.test.ts`
|
|
14
|
+
*/
|
|
15
|
+
import type { SourceRef } from "./types/v8-contracts.js";
|
|
16
|
+
export declare function serializeSourceRefs(refs: SourceRef[]): string;
|
|
17
|
+
export declare function parseSourceRefs(json: string | null | undefined): SourceRef[];
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export function serializeSourceRefs(refs) {
|
|
2
|
+
return JSON.stringify(refs);
|
|
3
|
+
}
|
|
4
|
+
function isSourceRef(value) {
|
|
5
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
6
|
+
return false;
|
|
7
|
+
const candidate = value;
|
|
8
|
+
return (typeof candidate.uri === "string" &&
|
|
9
|
+
typeof candidate.family === "string" &&
|
|
10
|
+
typeof candidate.id === "string" &&
|
|
11
|
+
typeof candidate.redactionClass === "string" &&
|
|
12
|
+
(candidate.sensitivityClass === undefined ||
|
|
13
|
+
typeof candidate.sensitivityClass === "string"));
|
|
14
|
+
}
|
|
15
|
+
export function parseSourceRefs(json) {
|
|
16
|
+
if (!json)
|
|
17
|
+
return [];
|
|
18
|
+
try {
|
|
19
|
+
const parsed = JSON.parse(json);
|
|
20
|
+
if (Array.isArray(parsed) && parsed.every(isSourceRef))
|
|
21
|
+
return parsed;
|
|
22
|
+
return [];
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
return [];
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SourceRef compatibility adapters.
|
|
3
|
+
*
|
|
4
|
+
* Core logic: convert legacy v5/v7 source-ref shapes that used `kind` into
|
|
5
|
+
* the v8 canonical `SourceRef` shape (`family` + `redactionClass`).
|
|
6
|
+
* Dependencies: shared v8 contracts only.
|
|
7
|
+
* Boundary: compatibility at old/new system seams; canonical v8 modules should
|
|
8
|
+
* pass `SourceRef` directly without reintroducing local clones.
|
|
9
|
+
* Test coverage: Wave 113 typecheck and affected control-plane/host/life-evidence tests.
|
|
10
|
+
*/
|
|
11
|
+
import type { SourceRef, SourceRefFamily } from "./types/v8-contracts.js";
|
|
12
|
+
export type LegacySourceRefKind = "platform_item" | "workspace_artifact" | "decision_record" | "user_anchor" | "connector_result" | "host_report" | "fallback_artifact";
|
|
13
|
+
export interface LegacySourceRefLike {
|
|
14
|
+
id: string;
|
|
15
|
+
kind?: LegacySourceRefKind | string;
|
|
16
|
+
uri: string;
|
|
17
|
+
}
|
|
18
|
+
export declare function sourceRefFamilyFromLegacyKind(kind: LegacySourceRefKind | string | undefined): SourceRefFamily;
|
|
19
|
+
export declare function legacyKindFromSourceRef(ref: SourceRef): LegacySourceRefKind;
|
|
20
|
+
export declare function toCanonicalSourceRef(ref: LegacySourceRefLike): SourceRef;
|
|
21
|
+
export declare function makeCanonicalSourceRef(input: {
|
|
22
|
+
id: string;
|
|
23
|
+
family: SourceRefFamily;
|
|
24
|
+
uri: string;
|
|
25
|
+
redactionClass?: SourceRef["redactionClass"];
|
|
26
|
+
}): SourceRef;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
export function sourceRefFamilyFromLegacyKind(kind) {
|
|
2
|
+
switch (kind) {
|
|
3
|
+
case "connector_result":
|
|
4
|
+
return "connector_result";
|
|
5
|
+
case "decision_record":
|
|
6
|
+
return "judgment";
|
|
7
|
+
case "platform_item":
|
|
8
|
+
case "user_anchor":
|
|
9
|
+
return "evidence";
|
|
10
|
+
case "workspace_artifact":
|
|
11
|
+
case "host_report":
|
|
12
|
+
case "fallback_artifact":
|
|
13
|
+
default:
|
|
14
|
+
return "audit";
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
export function legacyKindFromSourceRef(ref) {
|
|
18
|
+
if (ref.uri.startsWith("platform://")) {
|
|
19
|
+
return "platform_item";
|
|
20
|
+
}
|
|
21
|
+
if (ref.uri.startsWith("goal://") || ref.uri.startsWith("workspace://")) {
|
|
22
|
+
return "workspace_artifact";
|
|
23
|
+
}
|
|
24
|
+
if (ref.id.startsWith("anchor:") || ref.id.startsWith("curated:") || /(?:USER|MEMORY)\.md$/i.test(ref.uri)) {
|
|
25
|
+
return "user_anchor";
|
|
26
|
+
}
|
|
27
|
+
switch (ref.family) {
|
|
28
|
+
case "connector_result":
|
|
29
|
+
return "connector_result";
|
|
30
|
+
case "judgment":
|
|
31
|
+
return "decision_record";
|
|
32
|
+
case "evidence":
|
|
33
|
+
case "perception":
|
|
34
|
+
return "platform_item";
|
|
35
|
+
case "audit":
|
|
36
|
+
case "action_closure":
|
|
37
|
+
case "quiet_review":
|
|
38
|
+
case "dream_run":
|
|
39
|
+
case "memory_projection":
|
|
40
|
+
case "projection":
|
|
41
|
+
case "tool_experience":
|
|
42
|
+
default:
|
|
43
|
+
return "workspace_artifact";
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
export function toCanonicalSourceRef(ref) {
|
|
47
|
+
return {
|
|
48
|
+
id: ref.id,
|
|
49
|
+
uri: ref.uri,
|
|
50
|
+
family: sourceRefFamilyFromLegacyKind(ref.kind),
|
|
51
|
+
redactionClass: "none",
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
export function makeCanonicalSourceRef(input) {
|
|
55
|
+
return {
|
|
56
|
+
id: input.id,
|
|
57
|
+
family: input.family,
|
|
58
|
+
uri: input.uri,
|
|
59
|
+
redactionClass: input.redactionClass ?? "none",
|
|
60
|
+
};
|
|
61
|
+
}
|