@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
|
@@ -60,7 +60,6 @@ export async function recordNoActionClosure(db, cycleId, noActionReason, options
|
|
|
60
60
|
},
|
|
61
61
|
],
|
|
62
62
|
redactionClass: "none",
|
|
63
|
-
lifecycleStatus: "closed",
|
|
64
63
|
payloadJson: JSON.stringify({ dispatchAttempt: 0, inputSummary: "no-action" }),
|
|
65
64
|
});
|
|
66
65
|
if ("reason" in result) {
|
|
@@ -78,12 +77,13 @@ export async function recordRememberClosure(db, cycleId, memoryReviewCandidate,
|
|
|
78
77
|
id: closureId,
|
|
79
78
|
createdAt: now,
|
|
80
79
|
cycleId,
|
|
80
|
+
platformId: options?.platformId ?? "heartbeat",
|
|
81
|
+
capabilityId: options?.capabilityId,
|
|
81
82
|
status: "completed",
|
|
82
83
|
reason: "remember_for_review",
|
|
83
84
|
nextState: "pending_daily_review",
|
|
84
85
|
sourceRefs: memoryReviewCandidate.sourceRefs,
|
|
85
86
|
redactionClass: "none",
|
|
86
|
-
lifecycleStatus: "closed",
|
|
87
87
|
payloadJson: JSON.stringify({
|
|
88
88
|
memoryReviewCandidate,
|
|
89
89
|
dispatchAttempt: 1,
|
|
@@ -132,7 +132,6 @@ export async function recordPolicyOutcomeClosure(db, cycleId, closureStatus, rea
|
|
|
132
132
|
nextState: params.nextState ?? "await_next_cycle",
|
|
133
133
|
sourceRefs,
|
|
134
134
|
redactionClass: "none",
|
|
135
|
-
lifecycleStatus: "closed",
|
|
136
135
|
payloadJson: JSON.stringify({
|
|
137
136
|
dispatchAttempt: 1,
|
|
138
137
|
inputSummary: buildInputSummary(params.proposalId, params.decisionId),
|
|
@@ -173,7 +172,6 @@ export async function recordExecutionClosure(db, cycleId, closureStatus, reason,
|
|
|
173
172
|
nextState: params.nextState ?? (closureStatus === "completed" ? "await_next_cycle" : "retryable"),
|
|
174
173
|
sourceRefs,
|
|
175
174
|
redactionClass: "none",
|
|
176
|
-
lifecycleStatus: "closed",
|
|
177
175
|
payloadJson: JSON.stringify({
|
|
178
176
|
dispatchAttempt: 1,
|
|
179
177
|
executionResultRef: params.executionResultRef,
|
|
@@ -22,22 +22,12 @@
|
|
|
22
22
|
*
|
|
23
23
|
* Test coverage: tests/unit/action/action-proposal-builder.test.ts
|
|
24
24
|
*/
|
|
25
|
-
import { readJudgmentVerdictById,
|
|
25
|
+
import { readJudgmentVerdictById, } from "../../../storage/v8-state-stores.js";
|
|
26
|
+
import { parseSourceRefs } from "../../../shared/serialization.js";
|
|
26
27
|
import { ACTION_KIND_REGISTRY } from "../../../shared/types/v8-contracts.js";
|
|
27
28
|
// ───────────────────────────────────────────────────────────────
|
|
28
29
|
// Helpers
|
|
29
30
|
// ───────────────────────────────────────────────────────────────
|
|
30
|
-
function parseVerdictSourceRefs(json) {
|
|
31
|
-
if (!json)
|
|
32
|
-
return [];
|
|
33
|
-
try {
|
|
34
|
-
const parsed = JSON.parse(json);
|
|
35
|
-
return Array.isArray(parsed) ? parsed : [];
|
|
36
|
-
}
|
|
37
|
-
catch {
|
|
38
|
-
return [];
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
31
|
function buildExpectedOutput(actionKind) {
|
|
42
32
|
switch (actionKind) {
|
|
43
33
|
case "ignore":
|
|
@@ -99,8 +89,8 @@ export async function buildActionProposal(db, judgmentVerdictId, options) {
|
|
|
99
89
|
judgmentVerdictId,
|
|
100
90
|
};
|
|
101
91
|
}
|
|
102
|
-
const sourceRefs =
|
|
103
|
-
// remember → memory review candidate
|
|
92
|
+
const sourceRefs = parseSourceRefs(verdict.sourceRefsJson);
|
|
93
|
+
// remember → memory review candidate (no direct projection; orchestrator writes closure)
|
|
104
94
|
if (actionKind === "remember") {
|
|
105
95
|
const candidate = {
|
|
106
96
|
closureSubtype: "remember_for_review",
|
|
@@ -131,27 +121,10 @@ export async function buildActionProposal(db, judgmentVerdictId, options) {
|
|
|
131
121
|
},
|
|
132
122
|
]),
|
|
133
123
|
};
|
|
134
|
-
const closureId = `cls_remember_${judgmentVerdictId}_${now.replace(/[:.]/g, "")}`;
|
|
135
|
-
const writeResult = await writeActionClosureRecord(db, {
|
|
136
|
-
id: closureId,
|
|
137
|
-
createdAt: now,
|
|
138
|
-
cycleId,
|
|
139
|
-
platformId: "heartbeat",
|
|
140
|
-
status: "completed",
|
|
141
|
-
reason: "remember_for_review",
|
|
142
|
-
nextState: "pending_daily_review",
|
|
143
|
-
sourceRefs: candidate.sourceRefs,
|
|
144
|
-
redactionClass: "none",
|
|
145
|
-
lifecycleStatus: "closed",
|
|
146
|
-
payloadJson: JSON.stringify({ memoryReviewCandidate: candidate }),
|
|
147
|
-
});
|
|
148
|
-
if ("reason" in writeResult) {
|
|
149
|
-
return writeResult;
|
|
150
|
-
}
|
|
151
124
|
return {
|
|
152
125
|
status: "remember_for_review",
|
|
153
126
|
memoryReviewCandidate: candidate,
|
|
154
|
-
closureId,
|
|
127
|
+
closureId: `cls_remember_${judgmentVerdictId}_${now.replace(/[:.]/g, "")}`,
|
|
155
128
|
};
|
|
156
129
|
}
|
|
157
130
|
// Actionable verdict → build proposal
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
*
|
|
21
21
|
* Test coverage: tests/unit/action/policy-bound-dispatch.test.ts
|
|
22
22
|
*/
|
|
23
|
+
import { serializeSourceRefs } from "../../../shared/serialization.js";
|
|
23
24
|
// ───────────────────────────────────────────────────────────────
|
|
24
25
|
// Helpers
|
|
25
26
|
// ───────────────────────────────────────────────────────────────
|
|
@@ -60,7 +61,7 @@ export function dispatchAllowedAction(proposal, decision, options) {
|
|
|
60
61
|
actionKind: target,
|
|
61
62
|
draftType,
|
|
62
63
|
policyProof: { decisionId: decision.id, decision: decision.decision },
|
|
63
|
-
sourceRefs:
|
|
64
|
+
sourceRefs: serializeSourceRefs(decision.proofRefs),
|
|
64
65
|
},
|
|
65
66
|
};
|
|
66
67
|
}
|
|
@@ -75,7 +76,7 @@ export function dispatchAllowedAction(proposal, decision, options) {
|
|
|
75
76
|
capabilityId: proposal.targetCapabilityId ?? "run_connector",
|
|
76
77
|
idempotencyKey: proposal.idempotencyKey,
|
|
77
78
|
policyProof: { decisionId: decision.id, decision: decision.decision },
|
|
78
|
-
sourceRefs:
|
|
79
|
+
sourceRefs: serializeSourceRefs(proposal.sourceRefs),
|
|
79
80
|
},
|
|
80
81
|
};
|
|
81
82
|
}
|
|
@@ -91,7 +92,7 @@ export function dispatchAllowedAction(proposal, decision, options) {
|
|
|
91
92
|
actionKind: proposal.actionKind,
|
|
92
93
|
draftType,
|
|
93
94
|
policyProof: { decisionId: decision.id, decision: decision.decision },
|
|
94
|
-
sourceRefs:
|
|
95
|
+
sourceRefs: serializeSourceRefs(proposal.sourceRefs),
|
|
95
96
|
},
|
|
96
97
|
};
|
|
97
98
|
}
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
* Test coverage: tests/unit/control-plane/accepted-projection-loader.test.ts
|
|
21
21
|
*/
|
|
22
22
|
import { readMemoryProjectionsByStatus, } from "../../../storage/v8-state-stores.js";
|
|
23
|
+
import { parseSourceRefs } from "../../../shared/serialization.js";
|
|
23
24
|
// ───────────────────────────────────────────────────────────────
|
|
24
25
|
// Helpers
|
|
25
26
|
// ───────────────────────────────────────────────────────────────
|
|
@@ -33,17 +34,6 @@ function parsePayloadJson(json) {
|
|
|
33
34
|
return {};
|
|
34
35
|
}
|
|
35
36
|
}
|
|
36
|
-
function parseSourceRefs(json) {
|
|
37
|
-
if (!json)
|
|
38
|
-
return [];
|
|
39
|
-
try {
|
|
40
|
-
const parsed = JSON.parse(json);
|
|
41
|
-
return Array.isArray(parsed) ? parsed : [];
|
|
42
|
-
}
|
|
43
|
-
catch {
|
|
44
|
-
return [];
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
37
|
// ───────────────────────────────────────────────────────────────
|
|
48
38
|
// Public API
|
|
49
39
|
// ───────────────────────────────────────────────────────────────
|
|
@@ -35,6 +35,7 @@ export interface HeartbeatOrchestrationResult {
|
|
|
35
35
|
closureRef?: SourceRef;
|
|
36
36
|
noActionReason?: V8ReasonCode;
|
|
37
37
|
degraded?: DegradedOperationResult;
|
|
38
|
+
rhythmDegraded?: DegradedOperationResult;
|
|
38
39
|
rhythmState?: DailyRhythmState;
|
|
39
40
|
}
|
|
40
41
|
export declare function runHeartbeatCycle(db: StateDatabase, request: HeartbeatOrchestrationRequest): Promise<HeartbeatOrchestrationResult | DegradedOperationResult>;
|
|
@@ -191,7 +191,7 @@ export async function runHeartbeatCycle(db, request) {
|
|
|
191
191
|
reason: degradedReason,
|
|
192
192
|
sourceRefs: degradedClosureRef ? [degradedClosureRef, cycleRef] : [cycleRef],
|
|
193
193
|
});
|
|
194
|
-
const { rhythmState } = await advanceAndRecordDailyRhythm(db, cycleId, cycleSequence, cycleRef, now);
|
|
194
|
+
const { rhythmState, rhythmDegraded } = await advanceAndRecordDailyRhythm(db, cycleId, cycleSequence, cycleRef, now);
|
|
195
195
|
return {
|
|
196
196
|
cycleId,
|
|
197
197
|
cycleSequence,
|
|
@@ -206,7 +206,8 @@ export async function runHeartbeatCycle(db, request) {
|
|
|
206
206
|
operatorNextAction: "Retry heartbeat after perception recovery",
|
|
207
207
|
retryable: true,
|
|
208
208
|
}
|
|
209
|
-
:
|
|
209
|
+
: rhythmDegraded,
|
|
210
|
+
rhythmDegraded,
|
|
210
211
|
rhythmState,
|
|
211
212
|
};
|
|
212
213
|
}
|
|
@@ -245,12 +246,14 @@ export async function runHeartbeatCycle(db, request) {
|
|
|
245
246
|
reason: "evidence_batch_empty",
|
|
246
247
|
sourceRefs: emptyClosureRef ? [emptyClosureRef, cycleRef] : [cycleRef],
|
|
247
248
|
});
|
|
248
|
-
const { rhythmState } = await advanceAndRecordDailyRhythm(db, cycleId, cycleSequence, cycleRef, now);
|
|
249
|
+
const { rhythmState, rhythmDegraded } = await advanceAndRecordDailyRhythm(db, cycleId, cycleSequence, cycleRef, now);
|
|
249
250
|
return {
|
|
250
251
|
cycleId,
|
|
251
252
|
cycleSequence,
|
|
252
253
|
closureRef: emptyClosureRef,
|
|
253
254
|
noActionReason: "evidence_batch_empty",
|
|
255
|
+
degraded: rhythmDegraded,
|
|
256
|
+
rhythmDegraded,
|
|
254
257
|
rhythmState,
|
|
255
258
|
};
|
|
256
259
|
}
|
|
@@ -365,7 +368,7 @@ export async function runHeartbeatCycle(db, request) {
|
|
|
365
368
|
}
|
|
366
369
|
else if (proposalResult.status === "remember_for_review") {
|
|
367
370
|
const remember = proposalResult;
|
|
368
|
-
const closureResult = await recordRememberClosure(db, cycleId, remember.memoryReviewCandidate, { now });
|
|
371
|
+
const closureResult = await recordRememberClosure(db, cycleId, remember.memoryReviewCandidate, { now, platformId: "heartbeat" });
|
|
369
372
|
if ("closureId" in closureResult) {
|
|
370
373
|
closureRef = {
|
|
371
374
|
uri: `sn://closure/${closureResult.closureId}`,
|
|
@@ -540,13 +543,14 @@ export async function runHeartbeatCycle(db, request) {
|
|
|
540
543
|
noActionReason = "proposal_no_action";
|
|
541
544
|
}
|
|
542
545
|
// T-CP.R.3: Advance daily rhythm after closure/no-action
|
|
543
|
-
const { rhythmState } = await advanceAndRecordDailyRhythm(db, cycleId, cycleSequence, cycleRef, now);
|
|
546
|
+
const { rhythmState, rhythmDegraded } = await advanceAndRecordDailyRhythm(db, cycleId, cycleSequence, cycleRef, now);
|
|
544
547
|
return {
|
|
545
548
|
cycleId,
|
|
546
549
|
cycleSequence,
|
|
547
550
|
closureRef,
|
|
548
551
|
noActionReason,
|
|
549
|
-
degraded: closureDegraded,
|
|
552
|
+
degraded: closureDegraded ?? rhythmDegraded,
|
|
553
|
+
rhythmDegraded,
|
|
550
554
|
rhythmState,
|
|
551
555
|
};
|
|
552
556
|
}
|
|
@@ -31,5 +31,7 @@ export interface RealRuntimeSpineResult {
|
|
|
31
31
|
noActionReason?: V8ReasonCode;
|
|
32
32
|
degraded?: DegradedOperationResult;
|
|
33
33
|
rhythmState?: DailyRhythmState;
|
|
34
|
+
rhythmDegraded?: DegradedOperationResult;
|
|
35
|
+
impulseContextArtifactId?: string;
|
|
34
36
|
}
|
|
35
37
|
export declare function runRealRuntimeHeartbeatCycle(options: RealRuntimeSpineOptions): Promise<RealRuntimeSpineResult | DegradedOperationResult>;
|
|
@@ -38,5 +38,6 @@ export async function runRealRuntimeHeartbeatCycle(options) {
|
|
|
38
38
|
noActionReason: orchestrationResult.noActionReason,
|
|
39
39
|
degraded: orchestrationResult.degraded,
|
|
40
40
|
rhythmState: orchestrationResult.rhythmState,
|
|
41
|
+
rhythmDegraded: orchestrationResult.rhythmDegraded,
|
|
41
42
|
};
|
|
42
43
|
}
|
|
@@ -12,6 +12,7 @@ import { mapLifeEvidence } from "../../../connectors/base/map-life-evidence.js";
|
|
|
12
12
|
import { appendLifeEvidence } from "../../../storage/life-evidence/append-life-evidence.js";
|
|
13
13
|
import { normalizeConnectorEvidence } from "../../../connectors/evidence-normalizer.js";
|
|
14
14
|
import { recordConnectorAttemptAudit } from "../../../observability/services/audit-closure-recorders.js";
|
|
15
|
+
import { makeCanonicalSourceRef } from "../../../shared/source-ref-compat.js";
|
|
15
16
|
/**
|
|
16
17
|
* Resolves the heartbeat outcome for a guard-allowed intent (outreach dispatch, quiet orchestration, or default).
|
|
17
18
|
* Exported for unit tests (CR-M1 wiring).
|
|
@@ -302,11 +303,11 @@ export async function ingestRhythmSignal(signal, deps) {
|
|
|
302
303
|
effectClass: "connector_action",
|
|
303
304
|
capabilityIntent: idleResult.candidate.capabilityId,
|
|
304
305
|
sourceRefs: [
|
|
305
|
-
{
|
|
306
|
+
makeCanonicalSourceRef({
|
|
306
307
|
id: "idle_curiosity",
|
|
307
|
-
|
|
308
|
+
family: "audit",
|
|
308
309
|
uri: `idle://${idleResult.candidate.platformId}`,
|
|
309
|
-
},
|
|
310
|
+
}),
|
|
310
311
|
],
|
|
311
312
|
idempotencyKey: `idle:${idleResult.candidate.platformId}:${idleResult.candidate.capabilityId}`,
|
|
312
313
|
goalInfluenceRefs: [],
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* HeartbeatRuntimeSnapshot assembly for candidate planner + hard guards (T2.1.3, T2.2.1).
|
|
3
3
|
*/
|
|
4
|
-
import type { ContinuitySnapshot
|
|
4
|
+
import type { ContinuitySnapshot } from "../types.js";
|
|
5
|
+
import type { SourceRef } from "../../../shared/types/v8-contracts.js";
|
|
5
6
|
import type { RhythmPolicy } from "../rhythm/rhythm-policy.js";
|
|
6
7
|
import { type PlannerRhythmWindowSlice } from "../rhythm/planner-rhythm-window.js";
|
|
7
8
|
import type { SnapshotInputs } from "./snapshot-builder.js";
|
|
8
9
|
import type { AffordanceMap } from "../../../shared/types/v7-entities.js";
|
|
9
10
|
export interface PlannerLifeEvidenceSlice {
|
|
10
|
-
evidenceRefs:
|
|
11
|
+
evidenceRefs: SourceRef[];
|
|
11
12
|
platformEventCount: number;
|
|
12
13
|
workEventCount: number;
|
|
13
14
|
emptyReason?: "no_sources" | "state_unavailable" | "redacted_only";
|
|
@@ -6,7 +6,8 @@
|
|
|
6
6
|
*
|
|
7
7
|
* Per design doc §4.2: SnapshotBuilder prepares inputs for the Rhythm Engine.
|
|
8
8
|
*/
|
|
9
|
-
import type { ContinuitySnapshot,
|
|
9
|
+
import type { ContinuitySnapshot, TopLevelMode } from "../types.js";
|
|
10
|
+
import type { SourceRef } from "../../../shared/types/v8-contracts.js";
|
|
10
11
|
import type { RhythmPolicy } from "../rhythm/rhythm-policy.js";
|
|
11
12
|
import type { DeliveryCapabilitySnapshot } from "../outreach/delivery-target.js";
|
|
12
13
|
import type { UserInterestSnapshot } from "../../../storage/user-interest/types.js";
|
|
@@ -30,7 +31,7 @@ export interface SnapshotInputs {
|
|
|
30
31
|
awaitingUserInput?: boolean;
|
|
31
32
|
riskSuppressed?: boolean;
|
|
32
33
|
/** Evidence refs for source-backed planner/guards (T2.1.3 / T2.2.1). */
|
|
33
|
-
lifeEvidenceRefs?:
|
|
34
|
+
lifeEvidenceRefs?: SourceRef[];
|
|
34
35
|
platformEventCount?: number;
|
|
35
36
|
workEventCount?: number;
|
|
36
37
|
lifeEvidenceEmptyReason?: "no_sources" | "state_unavailable" | "redacted_only";
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
+
import { makeCanonicalSourceRef } from "../../../shared/source-ref-compat.js";
|
|
1
2
|
import { isLifeEvidenceSliceEmpty } from "../heartbeat/runtime-snapshot.js";
|
|
2
3
|
import { buildHeartbeatRuntimeSnapshot } from "../heartbeat/runtime-snapshot.js";
|
|
3
4
|
import { resolvePlatformForIntent, } from "./platform-capability-router.js";
|
|
4
5
|
import { isGoalRelatedToCandidate } from "./goal-priority.js";
|
|
5
6
|
const MAX_CANDIDATE_INTENTS = 6;
|
|
6
7
|
const OBLIGATION_SOURCE = [
|
|
7
|
-
{ id: "obligation-anchor",
|
|
8
|
+
makeCanonicalSourceRef({ id: "obligation-anchor", family: "audit", uri: "workspace://obligations/pending" }),
|
|
8
9
|
];
|
|
9
10
|
function evidenceRefsForConnector(runtime) {
|
|
10
11
|
if (!isLifeEvidenceSliceEmpty(runtime.lifeEvidence) && runtime.lifeEvidence.evidenceRefs.length > 0) {
|
|
@@ -253,8 +254,9 @@ export function planCandidateIntents(runtime, options) {
|
|
|
253
254
|
if (intent.sourceRefs.length === 0 && related.length > 0) {
|
|
254
255
|
intent.sourceRefs = related.slice(0, 4).map((g) => ({
|
|
255
256
|
id: g.goalId,
|
|
256
|
-
|
|
257
|
+
family: "audit",
|
|
257
258
|
uri: `goal://${g.goalId}`,
|
|
259
|
+
redactionClass: "none",
|
|
258
260
|
}));
|
|
259
261
|
}
|
|
260
262
|
}
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
* - Optional registry: when absent, resolution is best-effort from goals/evidence.
|
|
13
13
|
*/
|
|
14
14
|
import type { IntentKind } from "../types.js";
|
|
15
|
-
import type {
|
|
15
|
+
import type { SourceRef } from "../../../shared/types/v8-contracts.js";
|
|
16
16
|
import type { CapabilityContractRegistry } from "../../../connectors/base/manifest.js";
|
|
17
17
|
/** Minimal goal shape accepted by the router to avoid coupling to AgentGoal. M-03 decoupling. */
|
|
18
18
|
interface GoalRouterContext {
|
|
@@ -24,7 +24,7 @@ export interface PlatformResolutionContext {
|
|
|
24
24
|
/** Accepted goals that may name a platform or capability. */
|
|
25
25
|
acceptedGoals?: GoalRouterContext[];
|
|
26
26
|
/** Evidence refs that may embed platform identity. */
|
|
27
|
-
evidenceRefs?:
|
|
27
|
+
evidenceRefs?: SourceRef[];
|
|
28
28
|
}
|
|
29
29
|
/**
|
|
30
30
|
* Resolve an explicit platformId for a candidate intent kind.
|
|
@@ -48,7 +48,7 @@ function extractPlatformIdsFromGoals(goals, kind, platformIds) {
|
|
|
48
48
|
function extractPlatformIdsFromEvidence(refs, platformIds) {
|
|
49
49
|
const results = new Set();
|
|
50
50
|
for (const ref of refs) {
|
|
51
|
-
if (ref.
|
|
51
|
+
if (ref.family === "connector_result" && ref.id) {
|
|
52
52
|
for (const pid of platformIds) {
|
|
53
53
|
if (ref.id.includes(pid)) {
|
|
54
54
|
results.add(pid);
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
* Aligns with control-plane-system.detail §3.9 buildOutreachDraftRequest.
|
|
4
4
|
*/
|
|
5
5
|
import * as crypto from "node:crypto";
|
|
6
|
+
import { legacyKindFromSourceRef } from "../../../shared/source-ref-compat.js";
|
|
6
7
|
function inferRhythmWindowKind(windowId) {
|
|
7
8
|
const id = windowId.toLowerCase();
|
|
8
9
|
if (id.includes("work"))
|
|
@@ -20,10 +21,8 @@ function inferRhythmWindowKind(windowId) {
|
|
|
20
21
|
function toGuidanceRefs(refs) {
|
|
21
22
|
return refs.map((r) => ({
|
|
22
23
|
id: r.id,
|
|
23
|
-
kind: r
|
|
24
|
+
kind: legacyKindFromSourceRef(r),
|
|
24
25
|
uri: r.uri,
|
|
25
|
-
excerptHash: r.excerptHash,
|
|
26
|
-
observedAt: r.observedAt,
|
|
27
26
|
}));
|
|
28
27
|
}
|
|
29
28
|
function mapDeliveryVerdict(verdict) {
|
|
@@ -7,7 +7,7 @@ import type { CandidateIntent } from "../types.js";
|
|
|
7
7
|
import type { HeartbeatRuntimeSnapshot } from "../heartbeat/runtime-snapshot.js";
|
|
8
8
|
import type { HeartbeatCycleResult } from "../heartbeat/signal.js";
|
|
9
9
|
import type { StateDatabase } from "../../../storage/db/index.js";
|
|
10
|
-
import type {
|
|
10
|
+
import type { LifeEvidenceSourceRef } from "../../../storage/life-evidence/types.js";
|
|
11
11
|
import { type JudgeOutreachInput } from "./judge-outreach.js";
|
|
12
12
|
import { type DeliveryTargetResolution } from "./delivery-target.js";
|
|
13
13
|
export interface OpenClawDeliverySendResult {
|
|
@@ -16,7 +16,7 @@ export interface OpenClawDeliverySendResult {
|
|
|
16
16
|
errorClass?: string;
|
|
17
17
|
messageId?: string;
|
|
18
18
|
/** Host-reported delivery proof when messageId is absent (T4.3.1). */
|
|
19
|
-
hostProofRef?:
|
|
19
|
+
hostProofRef?: LifeEvidenceSourceRef;
|
|
20
20
|
}
|
|
21
21
|
export interface OpenClawDeliveryPort {
|
|
22
22
|
sendDeliveryRequest(input: {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { legacyKindFromSourceRef } from "../../../shared/source-ref-compat.js";
|
|
1
2
|
import { writeDeliveryAttempt } from "../../../storage/delivery/write-delivery-attempt.js";
|
|
2
3
|
import { writeOperatorFallback } from "../../../storage/fallback/write-operator-fallback.js";
|
|
3
4
|
import { judgeOutreach } from "./judge-outreach.js";
|
|
@@ -6,7 +7,11 @@ import { buildOutreachDraftRequest } from "./build-outreach-draft-request.js";
|
|
|
6
7
|
import { createNarrativeStateStore } from "../../../storage/narrative/narrative-state-store.js";
|
|
7
8
|
import { createRelationshipMemoryStore } from "../../../storage/relationship/relationship-memory-store.js";
|
|
8
9
|
function toSourceRefs(refs) {
|
|
9
|
-
return refs.map((r) => ({
|
|
10
|
+
return refs.map((r) => ({
|
|
11
|
+
id: r.id,
|
|
12
|
+
kind: legacyKindFromSourceRef(r),
|
|
13
|
+
uri: r.uri,
|
|
14
|
+
}));
|
|
10
15
|
}
|
|
11
16
|
function hasDeliveryProof(attempt) {
|
|
12
17
|
return Boolean(attempt.messageId?.trim()) || Boolean(attempt.hostProofRef);
|
|
@@ -1,12 +1,7 @@
|
|
|
1
|
+
import { toCanonicalSourceRef } from "../../../shared/source-ref-compat.js";
|
|
1
2
|
import { isLifeEvidenceSliceEmpty } from "../heartbeat/runtime-snapshot.js";
|
|
2
3
|
function toControlPlaneRefs(refs) {
|
|
3
|
-
return refs.map((r) => (
|
|
4
|
-
id: r.id,
|
|
5
|
-
kind: r.kind,
|
|
6
|
-
uri: r.uri,
|
|
7
|
-
excerptHash: r.excerptHash,
|
|
8
|
-
observedAt: r.observedAt,
|
|
9
|
-
}));
|
|
4
|
+
return refs.map((r) => toCanonicalSourceRef(r));
|
|
10
5
|
}
|
|
11
6
|
export function userInterestSnapshotToJudge(snapshot) {
|
|
12
7
|
if (!snapshot) {
|
|
@@ -18,13 +13,7 @@ export function userInterestSnapshotToJudge(snapshot) {
|
|
|
18
13
|
signals: snapshot.signals.map((s) => ({
|
|
19
14
|
topic: s.topic,
|
|
20
15
|
confidence: s.confidence,
|
|
21
|
-
sourceRefs: s.sourceRefs.map((r) => (
|
|
22
|
-
id: r.id,
|
|
23
|
-
kind: r.kind,
|
|
24
|
-
uri: r.uri,
|
|
25
|
-
excerptHash: r.excerptHash,
|
|
26
|
-
observedAt: r.observedAt,
|
|
27
|
-
})),
|
|
16
|
+
sourceRefs: s.sourceRefs.map((r) => toCanonicalSourceRef(r)),
|
|
28
17
|
})),
|
|
29
18
|
sourceRefs: toControlPlaneRefs(snapshot.sourceRefs),
|
|
30
19
|
};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type { CandidateIntent
|
|
1
|
+
import type { CandidateIntent } from "../types.js";
|
|
2
|
+
import type { SourceRef } from "../../../shared/types/v8-contracts.js";
|
|
2
3
|
import { type DeliveryCapabilitySnapshot, type DeliveryTargetResolution } from "./delivery-target.js";
|
|
3
4
|
export type OutreachJudgmentVerdict = "allow" | "deny" | "defer";
|
|
4
5
|
export type CooldownState = "clear" | "cooling_down" | "duplicate";
|
|
@@ -8,9 +9,9 @@ export interface JudgeOutreachUserInterest {
|
|
|
8
9
|
signals: Array<{
|
|
9
10
|
topic: string;
|
|
10
11
|
confidence: number;
|
|
11
|
-
sourceRefs:
|
|
12
|
+
sourceRefs: SourceRef[];
|
|
12
13
|
}>;
|
|
13
|
-
sourceRefs:
|
|
14
|
+
sourceRefs: SourceRef[];
|
|
14
15
|
}
|
|
15
16
|
export interface JudgeOutreachLifeEvidence {
|
|
16
17
|
empty: boolean;
|
|
@@ -31,8 +32,8 @@ export interface OutreachJudgment {
|
|
|
31
32
|
valueScore: number;
|
|
32
33
|
userRelevance: number;
|
|
33
34
|
actionability: number;
|
|
34
|
-
interestRefs:
|
|
35
|
-
sourceRefs:
|
|
35
|
+
interestRefs: SourceRef[];
|
|
36
|
+
sourceRefs: SourceRef[];
|
|
36
37
|
cooldownState: CooldownState;
|
|
37
38
|
deliveryVerdict: DeliveryTargetResolution["verdict"];
|
|
38
39
|
reasons: string[];
|
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
* Test coverage: tests/unit/judgment/judgment-engine.test.ts
|
|
23
23
|
*/
|
|
24
24
|
import { readPerceptionCardById, writeJudgmentVerdict, } from "../../../storage/v8-state-stores.js";
|
|
25
|
+
import { parseSourceRefs } from "../../../shared/serialization.js";
|
|
25
26
|
import { ACTION_KIND_REGISTRY } from "../../../shared/types/v8-contracts.js";
|
|
26
27
|
// ───────────────────────────────────────────────────────────────
|
|
27
28
|
// Config
|
|
@@ -42,17 +43,6 @@ function inferRiskPosture(sensitivityClass, riskFlags) {
|
|
|
42
43
|
}
|
|
43
44
|
return "low";
|
|
44
45
|
}
|
|
45
|
-
function parseCardSourceRefs(json) {
|
|
46
|
-
if (!json)
|
|
47
|
-
return [];
|
|
48
|
-
try {
|
|
49
|
-
const parsed = JSON.parse(json);
|
|
50
|
-
return Array.isArray(parsed) ? parsed : [];
|
|
51
|
-
}
|
|
52
|
-
catch {
|
|
53
|
-
return [];
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
46
|
function selectVerdict(relevance, confidence, riskPosture, hasSourceRefs, possibleIntents) {
|
|
57
47
|
// Missing source refs → ignore/watch only
|
|
58
48
|
if (!hasSourceRefs) {
|
|
@@ -125,7 +115,7 @@ export async function runAgentJudgment(db, perceptionCardId, options) {
|
|
|
125
115
|
retryable: false,
|
|
126
116
|
};
|
|
127
117
|
}
|
|
128
|
-
const sourceRefs =
|
|
118
|
+
const sourceRefs = parseSourceRefs(card.sourceRefsJson);
|
|
129
119
|
const hasSourceRefs = sourceRefs.length > 0;
|
|
130
120
|
// Parse sensitivity class from payload (stored there by perception-builder)
|
|
131
121
|
let sensitivityClass = "public_general";
|
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
* Test coverage: tests/unit/perception/perception-builder.test.ts
|
|
23
23
|
*/
|
|
24
24
|
import { readEvidenceItemsByStatus, writePerceptionCard, updateEvidenceItemLifecycleStatus, } from "../../../storage/v8-state-stores.js";
|
|
25
|
+
import { parseSourceRefs } from "../../../shared/serialization.js";
|
|
25
26
|
// ───────────────────────────────────────────────────────────────
|
|
26
27
|
// Config
|
|
27
28
|
// ───────────────────────────────────────────────────────────────
|
|
@@ -29,15 +30,6 @@ const PERCEPTION_MAX_EVIDENCE_PER_CYCLE = 50;
|
|
|
29
30
|
// ───────────────────────────────────────────────────────────────
|
|
30
31
|
// Helpers
|
|
31
32
|
// ───────────────────────────────────────────────────────────────
|
|
32
|
-
function parseSourceRefs(json) {
|
|
33
|
-
try {
|
|
34
|
-
const parsed = JSON.parse(json);
|
|
35
|
-
return Array.isArray(parsed) ? parsed : [];
|
|
36
|
-
}
|
|
37
|
-
catch {
|
|
38
|
-
return [];
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
33
|
function parsePayload(json) {
|
|
42
34
|
if (!json)
|
|
43
35
|
return undefined;
|
|
@@ -3,13 +3,21 @@ import { writeQuietArtifact } from "../../../storage/quiet/quiet-artifact-writer
|
|
|
3
3
|
import { persistQuietArtifactToWorkspace } from "../../../storage/quiet/persist-quiet-artifact.js";
|
|
4
4
|
import { buildEvidencePack, buildQuietNarrativeGuidance, selectInterestBasis } from "../../../guidance/evidence-guidance.js";
|
|
5
5
|
import { recordQuietArtifactAudit } from "../../../observability/services/audit-closure-recorders.js";
|
|
6
|
+
import { legacyKindFromSourceRef } from "../../../shared/source-ref-compat.js";
|
|
6
7
|
function toGuidanceRef(r) {
|
|
7
8
|
return {
|
|
8
9
|
id: r.id,
|
|
9
|
-
kind: r
|
|
10
|
+
kind: legacyKindFromSourceRef(r),
|
|
10
11
|
uri: r.uri,
|
|
11
|
-
|
|
12
|
-
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
function toLifeEvidenceRef(ref) {
|
|
15
|
+
return {
|
|
16
|
+
id: ref.id,
|
|
17
|
+
kind: ref.kind,
|
|
18
|
+
uri: ref.uri,
|
|
19
|
+
excerptHash: ref.excerptHash,
|
|
20
|
+
observedAt: ref.observedAt,
|
|
13
21
|
};
|
|
14
22
|
}
|
|
15
23
|
/**
|
|
@@ -116,24 +124,14 @@ export async function runSourceBackedQuiet(params) {
|
|
|
116
124
|
confidence: userInterestSnapshot?.confidence ?? 0,
|
|
117
125
|
signalCount: userInterestSnapshot?.signals.length ?? 0,
|
|
118
126
|
});
|
|
119
|
-
const groundedSourceRefs = ep.pack.groundedRefs.map(
|
|
120
|
-
id: g.id,
|
|
121
|
-
kind: g.kind,
|
|
122
|
-
uri: g.uri,
|
|
123
|
-
excerptHash: g.excerptHash,
|
|
124
|
-
observedAt: g.observedAt,
|
|
125
|
-
}));
|
|
127
|
+
const groundedSourceRefs = ep.pack.groundedRefs.map(toLifeEvidenceRef);
|
|
126
128
|
const claims = ep.pack.groundedRefs.map((g, i) => ({
|
|
127
129
|
id: `fact:${g.id}`,
|
|
128
130
|
text: `Evidence-backed note ${i + 1}`,
|
|
129
131
|
claimType: "fact",
|
|
130
132
|
sourceRefs: [
|
|
131
133
|
{
|
|
132
|
-
|
|
133
|
-
kind: g.kind,
|
|
134
|
-
uri: g.uri,
|
|
135
|
-
excerptHash: g.excerptHash,
|
|
136
|
-
observedAt: g.observedAt,
|
|
134
|
+
...toLifeEvidenceRef(g),
|
|
137
135
|
},
|
|
138
136
|
],
|
|
139
137
|
}));
|