@haaaiawd/second-nature 0.1.8 → 0.1.10
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 +281 -69
- package/openclaw.plugin.json +1 -1
- package/package.json +2 -1
- package/runtime/cli/commands/index.d.ts +2 -0
- package/runtime/cli/commands/index.js +61 -6
- package/runtime/cli/explain/explain-surface-subject.d.ts +8 -0
- package/runtime/cli/explain/explain-surface-subject.js +9 -0
- package/runtime/cli/explain/format-explanation.d.ts +2 -0
- package/runtime/cli/explain/format-explanation.js +2 -0
- package/runtime/cli/explain/resolve-subject.js +15 -0
- package/runtime/cli/host-capability/classify-delivery.d.ts +14 -0
- package/runtime/cli/host-capability/classify-delivery.js +20 -0
- package/runtime/cli/host-capability/probe-host-capability.d.ts +2 -0
- package/runtime/cli/host-capability/probe-host-capability.js +58 -0
- package/runtime/cli/host-capability/record-host-capability.d.ts +6 -0
- package/runtime/cli/host-capability/record-host-capability.js +14 -0
- package/runtime/cli/host-capability/types.d.ts +71 -0
- package/runtime/cli/host-capability/types.js +6 -0
- package/runtime/cli/host-smoke/run-host-smoke.d.ts +2 -0
- package/runtime/cli/host-smoke/run-host-smoke.js +40 -0
- package/runtime/cli/host-smoke/types.d.ts +35 -0
- package/runtime/cli/host-smoke/types.js +6 -0
- package/runtime/cli/index.js +18 -0
- package/runtime/cli/ops/heartbeat-surface.d.ts +35 -0
- package/runtime/cli/ops/heartbeat-surface.js +71 -0
- package/runtime/cli/ops/ops-router.d.ts +16 -0
- package/runtime/cli/ops/ops-router.js +83 -0
- package/runtime/cli/ops/show-operator-fallback.d.ts +13 -0
- package/runtime/cli/ops/show-operator-fallback.js +22 -0
- package/runtime/cli/ops/workspace-heartbeat-runner.d.ts +10 -0
- package/runtime/cli/ops/workspace-heartbeat-runner.js +26 -0
- package/runtime/cli/read-models/index.d.ts +11 -2
- package/runtime/cli/read-models/index.js +50 -0
- package/runtime/cli/read-models/operator-explain-map.d.ts +6 -0
- package/runtime/cli/read-models/operator-explain-map.js +10 -0
- package/runtime/cli/read-models/types.d.ts +5 -1
- package/runtime/cli/runtime/runtime-artifact-boundary.d.ts +28 -0
- package/runtime/cli/runtime/runtime-artifact-boundary.js +94 -0
- package/runtime/connectors/base/contract.d.ts +6 -0
- package/runtime/connectors/base/execution-policy.d.ts +47 -0
- package/runtime/connectors/base/execution-policy.js +82 -0
- package/runtime/connectors/base/index.d.ts +2 -0
- package/runtime/connectors/base/index.js +2 -0
- package/runtime/connectors/base/manifest.d.ts +55 -2
- package/runtime/connectors/base/manifest.js +50 -0
- package/runtime/connectors/base/map-life-evidence.d.ts +16 -0
- package/runtime/connectors/base/map-life-evidence.js +79 -0
- package/runtime/connectors/base/policy-layer.d.ts +2 -0
- package/runtime/connectors/base/policy-layer.js +16 -0
- package/runtime/connectors/base/route-planner.js +1 -0
- package/runtime/connectors/index.d.ts +1 -0
- package/runtime/connectors/index.js +1 -0
- package/runtime/connectors/near-real/near-real-connector-smoke.d.ts +19 -0
- package/runtime/connectors/near-real/near-real-connector-smoke.js +152 -0
- package/runtime/core/second-nature/heartbeat/heartbeat-executor.js +2 -0
- package/runtime/core/second-nature/heartbeat/heartbeat-loop.d.ts +37 -16
- package/runtime/core/second-nature/heartbeat/heartbeat-loop.js +95 -29
- package/runtime/core/second-nature/heartbeat/index.d.ts +4 -1
- package/runtime/core/second-nature/heartbeat/index.js +4 -1
- package/runtime/core/second-nature/heartbeat/run-heartbeat-cycle.d.ts +21 -0
- package/runtime/core/second-nature/heartbeat/run-heartbeat-cycle.js +35 -0
- package/runtime/core/second-nature/heartbeat/runtime-snapshot.d.ts +28 -0
- package/runtime/core/second-nature/heartbeat/runtime-snapshot.js +35 -0
- package/runtime/core/second-nature/heartbeat/signal.d.ts +9 -2
- package/runtime/core/second-nature/heartbeat/snapshot-builder.d.ts +19 -1
- package/runtime/core/second-nature/index.d.ts +8 -0
- package/runtime/core/second-nature/index.js +8 -0
- package/runtime/core/second-nature/orchestrator/effect-dispatcher.d.ts +1 -1
- package/runtime/core/second-nature/orchestrator/effect-dispatcher.js +9 -4
- package/runtime/core/second-nature/orchestrator/guard-layer.d.ts +6 -0
- package/runtime/core/second-nature/orchestrator/guard-layer.js +76 -20
- package/runtime/core/second-nature/orchestrator/intent-planner.d.ts +10 -0
- package/runtime/core/second-nature/orchestrator/intent-planner.js +135 -28
- package/runtime/core/second-nature/orchestrator/lease-manager.d.ts +1 -1
- package/runtime/core/second-nature/orchestrator/lease-manager.js +1 -1
- package/runtime/core/second-nature/outreach/build-outreach-draft-request.d.ts +6 -0
- package/runtime/core/second-nature/outreach/build-outreach-draft-request.js +63 -0
- package/runtime/core/second-nature/outreach/delivery-target.d.ts +26 -0
- package/runtime/core/second-nature/outreach/delivery-target.js +70 -0
- package/runtime/core/second-nature/outreach/dispatch-user-outreach.d.ts +38 -0
- package/runtime/core/second-nature/outreach/dispatch-user-outreach.js +119 -0
- package/runtime/core/second-nature/outreach/judge-input-from-snapshot.d.ts +7 -0
- package/runtime/core/second-nature/outreach/judge-input-from-snapshot.js +45 -0
- package/runtime/core/second-nature/outreach/judge-outreach.d.ts +40 -0
- package/runtime/core/second-nature/outreach/judge-outreach.js +121 -0
- package/runtime/core/second-nature/quiet/run-source-backed-quiet.d.ts +21 -0
- package/runtime/core/second-nature/quiet/run-source-backed-quiet.js +123 -0
- package/runtime/core/second-nature/rhythm/planner-rhythm-window.d.ts +15 -0
- package/runtime/core/second-nature/rhythm/planner-rhythm-window.js +52 -0
- package/runtime/core/second-nature/rhythm/policy-bridge.d.ts +19 -0
- package/runtime/core/second-nature/rhythm/policy-bridge.js +34 -0
- package/runtime/core/second-nature/types.d.ts +16 -2
- package/runtime/guidance/draft-outreach-message.d.ts +7 -0
- package/runtime/guidance/draft-outreach-message.js +42 -0
- package/runtime/guidance/evidence-guidance.d.ts +40 -0
- package/runtime/guidance/evidence-guidance.js +52 -0
- package/runtime/guidance/index.d.ts +3 -0
- package/runtime/guidance/index.js +3 -0
- package/runtime/guidance/outreach-draft-schema.d.ts +228 -0
- package/runtime/guidance/outreach-draft-schema.js +80 -0
- package/runtime/observability/audit/append-only-audit-store.d.ts +14 -0
- package/runtime/observability/audit/append-only-audit-store.js +21 -0
- package/runtime/observability/audit/audit-envelope.d.ts +51 -0
- package/runtime/observability/audit/audit-envelope.js +130 -0
- package/runtime/observability/audit/verify-audit-hash-chain.d.ts +23 -0
- package/runtime/observability/audit/verify-audit-hash-chain.js +83 -0
- package/runtime/observability/db/index.js +11 -0
- package/runtime/observability/db/schema/host-capability-reports.d.ts +180 -0
- package/runtime/observability/db/schema/host-capability-reports.js +12 -0
- package/runtime/observability/db/schema/index.d.ts +1 -0
- package/runtime/observability/db/schema/index.js +1 -0
- package/runtime/observability/index.d.ts +7 -0
- package/runtime/observability/index.js +7 -0
- package/runtime/observability/query/explain-query.d.ts +48 -0
- package/runtime/observability/query/explain-query.js +114 -0
- package/runtime/observability/query/export-audit-bundle.d.ts +22 -0
- package/runtime/observability/query/export-audit-bundle.js +27 -0
- package/runtime/observability/services/decision-ledger.d.ts +1 -1
- package/runtime/observability/services/decision-ledger.js +4 -0
- package/runtime/observability/services/governance-audit.d.ts +14 -0
- package/runtime/observability/services/governance-audit.js +25 -1
- package/runtime/observability/services/governance-plane-recorder.d.ts +47 -0
- package/runtime/observability/services/governance-plane-recorder.js +55 -0
- package/runtime/observability/services/lived-experience-audit.d.ts +97 -0
- package/runtime/observability/services/lived-experience-audit.js +162 -0
- package/runtime/storage/bootstrap/native-sqlite-probe.d.ts +7 -0
- package/runtime/storage/bootstrap/native-sqlite-probe.js +28 -0
- package/runtime/storage/bootstrap/repair-gate.d.ts +17 -0
- package/runtime/storage/bootstrap/repair-gate.js +71 -0
- package/runtime/storage/bootstrap/storage-mode-smoke.d.ts +38 -0
- package/runtime/storage/bootstrap/storage-mode-smoke.js +85 -0
- package/runtime/storage/db/index.js +49 -0
- package/runtime/storage/db/schema/delivery-attempts.d.ts +199 -0
- package/runtime/storage/db/schema/delivery-attempts.js +13 -0
- package/runtime/storage/db/schema/index.d.ts +3 -0
- package/runtime/storage/db/schema/index.js +3 -0
- package/runtime/storage/db/schema/life-evidence-index.d.ts +161 -0
- package/runtime/storage/db/schema/life-evidence-index.js +11 -0
- package/runtime/storage/db/schema/operator-fallback-artifacts.d.ts +161 -0
- package/runtime/storage/db/schema/operator-fallback-artifacts.js +11 -0
- package/runtime/storage/db/schema/policies.d.ts +17 -0
- package/runtime/storage/db/schema/policies.js +1 -0
- package/runtime/storage/delivery/query-delivery-attempts.d.ts +3 -0
- package/runtime/storage/delivery/query-delivery-attempts.js +32 -0
- package/runtime/storage/delivery/types.d.ts +27 -0
- package/runtime/storage/delivery/types.js +1 -0
- package/runtime/storage/delivery/write-delivery-attempt.d.ts +6 -0
- package/runtime/storage/delivery/write-delivery-attempt.js +36 -0
- package/runtime/storage/fallback/load-operator-fallback.d.ts +14 -0
- package/runtime/storage/fallback/load-operator-fallback.js +47 -0
- package/runtime/storage/fallback/operator-fallback-types.d.ts +9 -0
- package/runtime/storage/fallback/operator-fallback-types.js +1 -0
- package/runtime/storage/fallback/operator-fallback-view.d.ts +11 -0
- package/runtime/storage/fallback/operator-fallback-view.js +1 -0
- package/runtime/storage/fallback/write-operator-fallback.d.ts +6 -0
- package/runtime/storage/fallback/write-operator-fallback.js +21 -0
- package/runtime/storage/index.d.ts +21 -0
- package/runtime/storage/index.js +14 -0
- package/runtime/storage/life-evidence/append-life-evidence.d.ts +7 -0
- package/runtime/storage/life-evidence/append-life-evidence.js +64 -0
- package/runtime/storage/life-evidence/types.d.ts +45 -0
- package/runtime/storage/life-evidence/types.js +6 -0
- package/runtime/storage/quiet/persist-quiet-artifact.d.ts +7 -0
- package/runtime/storage/quiet/persist-quiet-artifact.js +22 -0
- package/runtime/storage/quiet/quiet-artifact-types.d.ts +18 -0
- package/runtime/storage/quiet/quiet-artifact-types.js +1 -0
- package/runtime/storage/quiet/quiet-artifact-writer.d.ts +15 -0
- package/runtime/storage/quiet/quiet-artifact-writer.js +56 -0
- package/runtime/storage/repositories/credential-repository.js +12 -1
- package/runtime/storage/rhythm/rhythm-policy-snapshot.d.ts +10 -0
- package/runtime/storage/rhythm/rhythm-policy-snapshot.js +34 -0
- package/runtime/storage/services/credential-vault.d.ts +5 -0
- package/runtime/storage/services/credential-vault.js +47 -9
- package/runtime/storage/snapshots/continuity-snapshot.d.ts +9 -0
- package/runtime/storage/snapshots/continuity-snapshot.js +41 -0
- package/runtime/storage/snapshots/life-evidence-snapshot.d.ts +6 -0
- package/runtime/storage/snapshots/life-evidence-snapshot.js +114 -0
- package/runtime/storage/snapshots/types.d.ts +58 -0
- package/runtime/storage/snapshots/types.js +1 -0
- package/runtime/storage/state-api.js +11 -4
- package/runtime/storage/user-interest/load-user-interest-snapshot.d.ts +2 -0
- package/runtime/storage/user-interest/load-user-interest-snapshot.js +150 -0
- package/runtime/storage/user-interest/types.d.ts +25 -0
- package/runtime/storage/user-interest/types.js +1 -0
- package/workspace-ops-bridge.js +78 -0
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HeartbeatRuntimeSnapshot assembly for candidate planner + hard guards (T2.1.3, T2.2.1).
|
|
3
|
+
*/
|
|
4
|
+
import type { ContinuitySnapshot, ControlPlaneSourceRef } from "../types.js";
|
|
5
|
+
import type { RhythmPolicy } from "../rhythm/rhythm-policy.js";
|
|
6
|
+
import { type PlannerRhythmWindowSlice } from "../rhythm/planner-rhythm-window.js";
|
|
7
|
+
import type { SnapshotInputs } from "./snapshot-builder.js";
|
|
8
|
+
export interface PlannerLifeEvidenceSlice {
|
|
9
|
+
evidenceRefs: ControlPlaneSourceRef[];
|
|
10
|
+
platformEventCount: number;
|
|
11
|
+
workEventCount: number;
|
|
12
|
+
emptyReason?: "no_sources" | "state_unavailable" | "redacted_only";
|
|
13
|
+
}
|
|
14
|
+
export declare function isLifeEvidenceSliceEmpty(slice: PlannerLifeEvidenceSlice): boolean;
|
|
15
|
+
export interface HardGuardDeps {
|
|
16
|
+
hasDuplicateIntent: (idempotencyKey: string) => boolean;
|
|
17
|
+
isOutreachCooldownClear: (idempotencyKey: string) => boolean;
|
|
18
|
+
}
|
|
19
|
+
export interface HeartbeatRuntimeSnapshot {
|
|
20
|
+
continuity: ContinuitySnapshot;
|
|
21
|
+
lifeEvidence: PlannerLifeEvidenceSlice;
|
|
22
|
+
rhythmWindow: PlannerRhythmWindowSlice;
|
|
23
|
+
hardGuards: HardGuardDeps;
|
|
24
|
+
}
|
|
25
|
+
export declare function buildLifeEvidenceSliceFromInputs(inputs: SnapshotInputs): PlannerLifeEvidenceSlice;
|
|
26
|
+
export declare function buildHardGuardDeps(continuity: ContinuitySnapshot, inputs: SnapshotInputs): HardGuardDeps;
|
|
27
|
+
export declare function resolveRhythmPolicyForHeartbeat(inputs: SnapshotInputs): RhythmPolicy;
|
|
28
|
+
export declare function buildHeartbeatRuntimeSnapshot(timestamp: string, inputs: SnapshotInputs, continuity: ContinuitySnapshot): HeartbeatRuntimeSnapshot;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { rhythmPolicySnapshotToRhythmPolicy } from "../rhythm/policy-bridge.js";
|
|
2
|
+
import { buildPlannerRhythmWindow } from "../rhythm/planner-rhythm-window.js";
|
|
3
|
+
export function isLifeEvidenceSliceEmpty(slice) {
|
|
4
|
+
return slice.evidenceRefs.length === 0 && slice.platformEventCount === 0 && slice.workEventCount === 0;
|
|
5
|
+
}
|
|
6
|
+
export function buildLifeEvidenceSliceFromInputs(inputs) {
|
|
7
|
+
return {
|
|
8
|
+
evidenceRefs: inputs.lifeEvidenceRefs ?? [],
|
|
9
|
+
platformEventCount: inputs.platformEventCount ?? 0,
|
|
10
|
+
workEventCount: inputs.workEventCount ?? 0,
|
|
11
|
+
emptyReason: inputs.lifeEvidenceEmptyReason,
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
export function buildHardGuardDeps(continuity, inputs) {
|
|
15
|
+
return {
|
|
16
|
+
hasDuplicateIntent: (key) => (inputs.duplicateIntentKeys?.includes(key) ?? false) ||
|
|
17
|
+
continuity.deniedIntents.some((d) => d.reason === "duplicate_intent" && d.intentHash === key),
|
|
18
|
+
isOutreachCooldownClear: (key) => !(inputs.outreachCooldownKeys?.includes(key) ?? false),
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
export function resolveRhythmPolicyForHeartbeat(inputs) {
|
|
22
|
+
if (inputs.rhythmPolicy) {
|
|
23
|
+
return inputs.rhythmPolicy;
|
|
24
|
+
}
|
|
25
|
+
return rhythmPolicySnapshotToRhythmPolicy({
|
|
26
|
+
quietEnabled: inputs.quietEnabledBridge ?? false,
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
export function buildHeartbeatRuntimeSnapshot(timestamp, inputs, continuity) {
|
|
30
|
+
const policy = resolveRhythmPolicyForHeartbeat(inputs);
|
|
31
|
+
const rhythmWindow = buildPlannerRhythmWindow(timestamp, continuity, policy);
|
|
32
|
+
const lifeEvidence = buildLifeEvidenceSliceFromInputs(inputs);
|
|
33
|
+
const hardGuards = buildHardGuardDeps(continuity, inputs);
|
|
34
|
+
return { continuity, lifeEvidence, rhythmWindow, hardGuards };
|
|
35
|
+
}
|
|
@@ -7,7 +7,11 @@
|
|
|
7
7
|
*/
|
|
8
8
|
export type RuntimeScope = "rhythm" | "user_task" | "user_reply";
|
|
9
9
|
export type RuntimeTrigger = "heartbeat_bridge" | "user_task" | "user_reply" | "interrupt" | "resume";
|
|
10
|
-
export type HeartbeatCycleStatus = "heartbeat_ok" | "intent_selected" | "deferred" | "denied"
|
|
10
|
+
export type HeartbeatCycleStatus = "heartbeat_ok" | "intent_selected" | "deferred" | "denied"
|
|
11
|
+
/** Delivery port returned failed / host dropped; operator fallback written (T2.3.2 / ADR-007). */
|
|
12
|
+
| "delivery_unavailable"
|
|
13
|
+
/** Host-safe packaged carrier: no lived-experience loop (ADR-005 / control-plane L0). */
|
|
14
|
+
| "runtime_carrier_only";
|
|
11
15
|
export interface HeartbeatSignal {
|
|
12
16
|
trigger: RuntimeTrigger;
|
|
13
17
|
scopeHint?: RuntimeScope;
|
|
@@ -23,10 +27,13 @@ export interface ScopedRuntimeInput {
|
|
|
23
27
|
payload: Record<string, unknown>;
|
|
24
28
|
}
|
|
25
29
|
export interface HeartbeatCycleResult {
|
|
26
|
-
scope:
|
|
30
|
+
scope: RuntimeScope;
|
|
27
31
|
status: HeartbeatCycleStatus;
|
|
28
32
|
selectedIntentId?: string;
|
|
29
33
|
reasons: string[];
|
|
34
|
+
decisionId?: string;
|
|
35
|
+
deliveryAttemptId?: string;
|
|
36
|
+
fallbackRef?: string;
|
|
30
37
|
}
|
|
31
38
|
export interface ScopeRouteResult {
|
|
32
39
|
scope: RuntimeScope;
|
|
@@ -6,7 +6,10 @@
|
|
|
6
6
|
*
|
|
7
7
|
* Per design doc §4.2: SnapshotBuilder prepares inputs for the Rhythm Engine.
|
|
8
8
|
*/
|
|
9
|
-
import type { ContinuitySnapshot, TopLevelMode } from "../types.js";
|
|
9
|
+
import type { ContinuitySnapshot, ControlPlaneSourceRef, TopLevelMode } from "../types.js";
|
|
10
|
+
import type { RhythmPolicy } from "../rhythm/rhythm-policy.js";
|
|
11
|
+
import type { DeliveryCapabilitySnapshot } from "../outreach/delivery-target.js";
|
|
12
|
+
import type { UserInterestSnapshot } from "../../../storage/user-interest/types.js";
|
|
10
13
|
export interface SnapshotInputs {
|
|
11
14
|
mode: TopLevelMode;
|
|
12
15
|
currentWindowId: string;
|
|
@@ -23,6 +26,21 @@ export interface SnapshotInputs {
|
|
|
23
26
|
};
|
|
24
27
|
awaitingUserInput?: boolean;
|
|
25
28
|
riskSuppressed?: boolean;
|
|
29
|
+
/** Evidence refs for source-backed planner/guards (T2.1.3 / T2.2.1). */
|
|
30
|
+
lifeEvidenceRefs?: ControlPlaneSourceRef[];
|
|
31
|
+
platformEventCount?: number;
|
|
32
|
+
workEventCount?: number;
|
|
33
|
+
lifeEvidenceEmptyReason?: "no_sources" | "state_unavailable" | "redacted_only";
|
|
34
|
+
/** Optional explicit rhythm geometry; otherwise `quietEnabledBridge` drives policy-bridge default. */
|
|
35
|
+
rhythmPolicy?: RhythmPolicy;
|
|
36
|
+
/** Passed to `rhythmPolicySnapshotToRhythmPolicy` when `rhythmPolicy` is absent. */
|
|
37
|
+
quietEnabledBridge?: boolean;
|
|
38
|
+
duplicateIntentKeys?: string[];
|
|
39
|
+
outreachCooldownKeys?: string[];
|
|
40
|
+
/** When present, outreach judgment uses this delivery snapshot (ADR-007). */
|
|
41
|
+
deliveryCapability?: DeliveryCapabilitySnapshot;
|
|
42
|
+
/** When present, outreach judgment uses this user-interest read model (T4.2.2). */
|
|
43
|
+
userInterestSnapshot?: UserInterestSnapshot;
|
|
26
44
|
}
|
|
27
45
|
/**
|
|
28
46
|
* Build a ContinuitySnapshot from loaded inputs.
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
export * from "./types.js";
|
|
2
2
|
export * from "./rhythm/rhythm-policy.js";
|
|
3
3
|
export * from "./rhythm/select-window.js";
|
|
4
|
+
export * from "./rhythm/policy-bridge.js";
|
|
4
5
|
export * from "./orchestrator/intent-planner.js";
|
|
5
6
|
export * from "./orchestrator/guard-layer.js";
|
|
7
|
+
export * from "./heartbeat/runtime-snapshot.js";
|
|
6
8
|
export * from "./orchestrator/lease-manager.js";
|
|
7
9
|
export * from "./orchestrator/effect-dispatcher.js";
|
|
8
10
|
export * from "./orchestrator/resume-from-checkpoint.js";
|
|
@@ -10,5 +12,11 @@ export * from "./quiet/quiet-pipeline.js";
|
|
|
10
12
|
export * from "./reflection/run-narrative-reflection.js";
|
|
11
13
|
export * from "./outreach/evaluate-outreach.js";
|
|
12
14
|
export * from "./outreach/build-message.js";
|
|
15
|
+
export * from "./outreach/delivery-target.js";
|
|
16
|
+
export * from "./outreach/judge-outreach.js";
|
|
17
|
+
export * from "./outreach/build-outreach-draft-request.js";
|
|
18
|
+
export * from "./outreach/dispatch-user-outreach.js";
|
|
19
|
+
export * from "./outreach/judge-input-from-snapshot.js";
|
|
20
|
+
export * from "./quiet/run-source-backed-quiet.js";
|
|
13
21
|
export * from "./guidance/request-guidance.js";
|
|
14
22
|
export * from "./guidance/apply-guidance.js";
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
export * from "./types.js";
|
|
2
2
|
export * from "./rhythm/rhythm-policy.js";
|
|
3
3
|
export * from "./rhythm/select-window.js";
|
|
4
|
+
export * from "./rhythm/policy-bridge.js";
|
|
4
5
|
export * from "./orchestrator/intent-planner.js";
|
|
5
6
|
export * from "./orchestrator/guard-layer.js";
|
|
7
|
+
export * from "./heartbeat/runtime-snapshot.js";
|
|
6
8
|
export * from "./orchestrator/lease-manager.js";
|
|
7
9
|
export * from "./orchestrator/effect-dispatcher.js";
|
|
8
10
|
export * from "./orchestrator/resume-from-checkpoint.js";
|
|
@@ -10,5 +12,11 @@ export * from "./quiet/quiet-pipeline.js";
|
|
|
10
12
|
export * from "./reflection/run-narrative-reflection.js";
|
|
11
13
|
export * from "./outreach/evaluate-outreach.js";
|
|
12
14
|
export * from "./outreach/build-message.js";
|
|
15
|
+
export * from "./outreach/delivery-target.js";
|
|
16
|
+
export * from "./outreach/judge-outreach.js";
|
|
17
|
+
export * from "./outreach/build-outreach-draft-request.js";
|
|
18
|
+
export * from "./outreach/dispatch-user-outreach.js";
|
|
19
|
+
export * from "./outreach/judge-input-from-snapshot.js";
|
|
20
|
+
export * from "./quiet/run-source-backed-quiet.js";
|
|
13
21
|
export * from "./guidance/request-guidance.js";
|
|
14
22
|
export * from "./guidance/apply-guidance.js";
|
|
@@ -2,7 +2,7 @@ import type { ConnectorResult, CapabilityIntent } from "../../../connectors/base
|
|
|
2
2
|
import { LeaseManager, type EffectClass } from "./lease-manager.js";
|
|
3
3
|
export interface AllowedIntent {
|
|
4
4
|
id: string;
|
|
5
|
-
kind: "work" | "exploration" | "social" | "reflection" | "outreach" | "maintenance";
|
|
5
|
+
kind: "work" | "exploration" | "social" | "quiet" | "reflection" | "outreach" | "maintenance";
|
|
6
6
|
summary: string;
|
|
7
7
|
effectClass: EffectClass;
|
|
8
8
|
platformId?: string;
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import * as crypto from "crypto";
|
|
2
2
|
function needsLease(effectClass) {
|
|
3
|
-
return effectClass === "external_platform_action" || effectClass === "user_outreach";
|
|
3
|
+
return effectClass === "external_platform_action" || effectClass === "connector_action" || effectClass === "user_outreach";
|
|
4
4
|
}
|
|
5
5
|
function needsCheckpoint(effectClass) {
|
|
6
|
-
return effectClass !== "maintenance";
|
|
6
|
+
return effectClass !== "maintenance" && effectClass !== "no_effect";
|
|
7
|
+
}
|
|
8
|
+
function isConnectorEffect(effectClass) {
|
|
9
|
+
return effectClass === "external_platform_action" || effectClass === "connector_action";
|
|
7
10
|
}
|
|
8
11
|
function toCapabilityIntent(intent) {
|
|
9
12
|
if (intent.kind === "work")
|
|
@@ -14,6 +17,8 @@ function toCapabilityIntent(intent) {
|
|
|
14
17
|
return "comment.reply";
|
|
15
18
|
if (intent.kind === "outreach")
|
|
16
19
|
return "message.send";
|
|
20
|
+
if (intent.kind === "quiet")
|
|
21
|
+
return "feed.read";
|
|
17
22
|
return "feed.read";
|
|
18
23
|
}
|
|
19
24
|
export class EffectDispatcher {
|
|
@@ -43,7 +48,7 @@ export class EffectDispatcher {
|
|
|
43
48
|
id: decision.checkpointId,
|
|
44
49
|
tickId: decision.tickId,
|
|
45
50
|
intentId: decision.intentId,
|
|
46
|
-
phase: intent.effectClass
|
|
51
|
+
phase: isConnectorEffect(intent.effectClass) ? "before_effect" : "before_quiet_write",
|
|
47
52
|
snapshotRef: decision.traceId,
|
|
48
53
|
});
|
|
49
54
|
}
|
|
@@ -54,7 +59,7 @@ export class EffectDispatcher {
|
|
|
54
59
|
state: "planned",
|
|
55
60
|
});
|
|
56
61
|
try {
|
|
57
|
-
if (intent.effectClass
|
|
62
|
+
if (isConnectorEffect(intent.effectClass)) {
|
|
58
63
|
await this.commitPort.advanceIntentCommitState(commit.id, "dispatched");
|
|
59
64
|
const result = await this.connectorExecutor.executeEffect({
|
|
60
65
|
platformId: intent.platformId ?? "unknown",
|
|
@@ -1,2 +1,8 @@
|
|
|
1
1
|
import type { CandidateIntent, ContinuitySnapshot, GuardEvaluation } from "../types.js";
|
|
2
|
+
import type { HeartbeatRuntimeSnapshot } from "../heartbeat/runtime-snapshot.js";
|
|
3
|
+
/**
|
|
4
|
+
* Hard guard evaluation (T2.1.3): source, dedupe, cooldown, quiet bias, budget, risk, awaiting user.
|
|
5
|
+
*/
|
|
6
|
+
export declare function evaluateHardGuards(intent: CandidateIntent, runtime: HeartbeatRuntimeSnapshot): GuardEvaluation;
|
|
7
|
+
/** Continuity-only guard path for legacy call sites; builds a minimal runtime snapshot. */
|
|
2
8
|
export declare function evaluateGuards(intent: CandidateIntent, snapshot: ContinuitySnapshot): GuardEvaluation;
|
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
const hash = stableIntentHash(intent);
|
|
6
|
-
return snapshot.deniedIntents.some((item) => item.intentHash === hash && item.reason === "duplicate_intent");
|
|
1
|
+
import { buildHeartbeatRuntimeSnapshot } from "../heartbeat/runtime-snapshot.js";
|
|
2
|
+
const QUIET_DENY_KINDS = ["outreach", "social"];
|
|
3
|
+
function intentFingerprint(intent) {
|
|
4
|
+
return intent.idempotencyKey ?? `${intent.kind}:${intent.summary}`;
|
|
7
5
|
}
|
|
8
6
|
function isBudgetExceeded(intent, snapshot) {
|
|
9
7
|
if (intent.kind !== "social")
|
|
@@ -12,43 +10,101 @@ function isBudgetExceeded(intent, snapshot) {
|
|
|
12
10
|
return false;
|
|
13
11
|
return snapshot.budgets.socialUsed >= snapshot.budgets.socialLimit;
|
|
14
12
|
}
|
|
15
|
-
function isQuietSuppressed(intent,
|
|
16
|
-
if (
|
|
17
|
-
return false;
|
|
18
|
-
if (intent.effectClass === "maintenance" || intent.effectClass === "memory_curation" || intent.effectClass === "narrative_reflection") {
|
|
13
|
+
function isQuietSuppressed(intent, runtime) {
|
|
14
|
+
if (!runtime.rhythmWindow.quietBias)
|
|
19
15
|
return false;
|
|
16
|
+
if (QUIET_DENY_KINDS.includes(intent.kind)) {
|
|
17
|
+
return true;
|
|
18
|
+
}
|
|
19
|
+
if (intent.effectClass === "connector_action" || intent.effectClass === "external_platform_action") {
|
|
20
|
+
return true;
|
|
20
21
|
}
|
|
21
|
-
return
|
|
22
|
+
return false;
|
|
22
23
|
}
|
|
23
|
-
|
|
24
|
+
function isSourceBacked(intent) {
|
|
25
|
+
if (intent.sourceRefs.length > 0)
|
|
26
|
+
return true;
|
|
27
|
+
if (intent.effectClass === "maintenance" || intent.effectClass === "no_effect")
|
|
28
|
+
return true;
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
function isRiskBlocked(intent, snapshot) {
|
|
32
|
+
if (!snapshot.riskSuppressed)
|
|
33
|
+
return false;
|
|
34
|
+
return intent.kind === "exploration" || intent.kind === "social" || intent.kind === "outreach";
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Hard guard evaluation (T2.1.3): source, dedupe, cooldown, quiet bias, budget, risk, awaiting user.
|
|
38
|
+
*/
|
|
39
|
+
export function evaluateHardGuards(intent, runtime) {
|
|
40
|
+
const snapshot = runtime.continuity;
|
|
24
41
|
const reasons = [];
|
|
25
|
-
if (
|
|
42
|
+
if (!isSourceBacked(intent)) {
|
|
43
|
+
reasons.push("missing_source_refs");
|
|
44
|
+
}
|
|
45
|
+
const key = intentFingerprint(intent);
|
|
46
|
+
if (runtime.hardGuards.hasDuplicateIntent(key)) {
|
|
26
47
|
reasons.push("duplicate_intent");
|
|
27
48
|
}
|
|
49
|
+
if (intent.effectClass === "user_outreach" && !runtime.hardGuards.isOutreachCooldownClear(key)) {
|
|
50
|
+
reasons.push("outreach_cooldown");
|
|
51
|
+
}
|
|
52
|
+
if (isQuietSuppressed(intent, runtime)) {
|
|
53
|
+
reasons.push("quiet_window_suppression");
|
|
54
|
+
}
|
|
28
55
|
if (isBudgetExceeded(intent, snapshot)) {
|
|
29
56
|
reasons.push("budget_exceeded");
|
|
30
57
|
}
|
|
31
|
-
if (isQuietSuppressed(intent, snapshot)) {
|
|
32
|
-
reasons.push("quiet_window");
|
|
33
|
-
}
|
|
34
58
|
if (snapshot.awaitingUserInput) {
|
|
35
59
|
reasons.push("awaiting_user");
|
|
36
60
|
}
|
|
61
|
+
if (isRiskBlocked(intent, snapshot)) {
|
|
62
|
+
reasons.push("risk_suppressed");
|
|
63
|
+
}
|
|
37
64
|
if (reasons.length === 0) {
|
|
38
65
|
return {
|
|
39
66
|
verdict: "allow",
|
|
40
|
-
reasons,
|
|
67
|
+
reasons: [],
|
|
41
68
|
quietSuppressed: false,
|
|
42
|
-
leaseRequired: intent.effectClass === "external_platform_action" ||
|
|
43
|
-
|
|
69
|
+
leaseRequired: intent.effectClass === "external_platform_action" ||
|
|
70
|
+
intent.effectClass === "connector_action" ||
|
|
71
|
+
intent.effectClass === "user_outreach",
|
|
72
|
+
requiresCheckpoint: intent.effectClass !== "maintenance" && intent.effectClass !== "no_effect",
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
const duplicate = reasons.includes("duplicate_intent");
|
|
76
|
+
const cooldown = reasons.includes("outreach_cooldown");
|
|
77
|
+
if (duplicate || cooldown) {
|
|
78
|
+
return {
|
|
79
|
+
verdict: "defer",
|
|
80
|
+
reasons,
|
|
81
|
+
quietSuppressed: reasons.includes("quiet_window_suppression"),
|
|
82
|
+
leaseRequired: false,
|
|
83
|
+
requiresCheckpoint: false,
|
|
44
84
|
};
|
|
45
85
|
}
|
|
46
86
|
const escalated = reasons.includes("awaiting_user") && intent.kind === "outreach";
|
|
47
87
|
return {
|
|
48
88
|
verdict: escalated ? "escalate" : "deny",
|
|
49
89
|
reasons,
|
|
50
|
-
quietSuppressed: reasons.includes("
|
|
90
|
+
quietSuppressed: reasons.includes("quiet_window_suppression"),
|
|
51
91
|
leaseRequired: false,
|
|
52
92
|
requiresCheckpoint: false,
|
|
53
93
|
};
|
|
54
94
|
}
|
|
95
|
+
/** Continuity-only guard path for legacy call sites; builds a minimal runtime snapshot. */
|
|
96
|
+
export function evaluateGuards(intent, snapshot) {
|
|
97
|
+
const inputs = {
|
|
98
|
+
mode: snapshot.mode,
|
|
99
|
+
currentWindowId: snapshot.currentWindowId,
|
|
100
|
+
pendingObligations: snapshot.pendingObligations,
|
|
101
|
+
recentOutreachHashes: snapshot.recentOutreachHashes,
|
|
102
|
+
deniedIntents: snapshot.deniedIntents,
|
|
103
|
+
budgets: snapshot.budgets,
|
|
104
|
+
awaitingUserInput: snapshot.awaitingUserInput,
|
|
105
|
+
riskSuppressed: snapshot.riskSuppressed,
|
|
106
|
+
quietEnabledBridge: snapshot.mode === "quiet",
|
|
107
|
+
};
|
|
108
|
+
const runtime = buildHeartbeatRuntimeSnapshot("2026-03-25T12:00:00.000Z", inputs, snapshot);
|
|
109
|
+
return evaluateHardGuards(intent, runtime);
|
|
110
|
+
}
|
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Candidate intent planner (T2.1.3): window-biased planning + priority cap.
|
|
3
|
+
* `planCandidateIntents` is the contract name; `planIntent` bridges legacy continuity-only tests.
|
|
4
|
+
*/
|
|
1
5
|
import type { CandidateIntent, ContinuitySnapshot, DecisionBasis } from "../types.js";
|
|
6
|
+
import type { HeartbeatRuntimeSnapshot } from "../heartbeat/runtime-snapshot.js";
|
|
7
|
+
/**
|
|
8
|
+
* Plan ordered candidates for one heartbeat turn using rhythm window + life evidence slice.
|
|
9
|
+
*/
|
|
10
|
+
export declare function planCandidateIntents(runtime: HeartbeatRuntimeSnapshot): CandidateIntent[];
|
|
11
|
+
/** @deprecated Continuity-only helper for tests; prefer `planCandidateIntents` + `buildHeartbeatRuntimeSnapshot`. */
|
|
2
12
|
export declare function planIntent(snapshot: ContinuitySnapshot): CandidateIntent[];
|
|
3
13
|
export declare function decideDecisionBasis(intent: CandidateIntent): DecisionBasis;
|
|
@@ -1,16 +1,45 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import { isLifeEvidenceSliceEmpty } from "../heartbeat/runtime-snapshot.js";
|
|
2
|
+
import { buildHeartbeatRuntimeSnapshot } from "../heartbeat/runtime-snapshot.js";
|
|
3
|
+
const MAX_CANDIDATE_INTENTS = 6;
|
|
4
|
+
const OBLIGATION_SOURCE = [
|
|
5
|
+
{ id: "obligation-anchor", kind: "workspace_artifact", uri: "workspace://obligations/pending" },
|
|
6
|
+
];
|
|
7
|
+
function evidenceRefsForConnector(runtime) {
|
|
8
|
+
if (!isLifeEvidenceSliceEmpty(runtime.lifeEvidence) && runtime.lifeEvidence.evidenceRefs.length > 0) {
|
|
9
|
+
return runtime.lifeEvidence.evidenceRefs.slice(0, 8);
|
|
10
|
+
}
|
|
11
|
+
if (!isLifeEvidenceSliceEmpty(runtime.lifeEvidence)) {
|
|
12
|
+
return [
|
|
13
|
+
{
|
|
14
|
+
id: "life-evidence-summary",
|
|
15
|
+
kind: "connector_result",
|
|
16
|
+
uri: `workspace://life-evidence/counts/${runtime.lifeEvidence.platformEventCount}/${runtime.lifeEvidence.workEventCount}`,
|
|
17
|
+
},
|
|
18
|
+
];
|
|
19
|
+
}
|
|
20
|
+
return [];
|
|
21
|
+
}
|
|
22
|
+
function isAllowedKind(kind, runtime) {
|
|
23
|
+
return runtime.rhythmWindow.allowedIntentKinds.includes(kind);
|
|
24
|
+
}
|
|
25
|
+
function planWorkIntents(runtime) {
|
|
26
|
+
if (!isAllowedKind("work", runtime))
|
|
27
|
+
return [];
|
|
28
|
+
return runtime.continuity.pendingObligations.map((obligation, index) => ({
|
|
4
29
|
id: `intent-obligation-${index}`,
|
|
5
30
|
kind: "work",
|
|
6
31
|
priority: 100 - index,
|
|
7
32
|
source: "obligation",
|
|
8
33
|
summary: `fulfill obligation: ${obligation}`,
|
|
9
|
-
effectClass: "
|
|
34
|
+
effectClass: "connector_action",
|
|
35
|
+
sourceRefs: [...OBLIGATION_SOURCE],
|
|
36
|
+
idempotencyKey: `obligation:${obligation}:${index}`,
|
|
10
37
|
}));
|
|
11
38
|
}
|
|
12
|
-
function
|
|
13
|
-
|
|
39
|
+
function planExplorationIntents(runtime) {
|
|
40
|
+
if (!isAllowedKind("exploration", runtime))
|
|
41
|
+
return [];
|
|
42
|
+
const refs = evidenceRefsForConnector(runtime);
|
|
14
43
|
return [
|
|
15
44
|
{
|
|
16
45
|
id: "intent-exploration",
|
|
@@ -18,45 +47,80 @@ function planPlatformIntents(snapshot) {
|
|
|
18
47
|
priority: 70,
|
|
19
48
|
source: "tick",
|
|
20
49
|
summary: "scan platform opportunities",
|
|
21
|
-
effectClass: "
|
|
50
|
+
effectClass: "connector_action",
|
|
51
|
+
sourceRefs: refs,
|
|
52
|
+
idempotencyKey: "exploration:scan platform opportunities",
|
|
22
53
|
},
|
|
54
|
+
];
|
|
55
|
+
}
|
|
56
|
+
function planSocialIntents(runtime) {
|
|
57
|
+
if (!isAllowedKind("social", runtime))
|
|
58
|
+
return [];
|
|
59
|
+
const refs = evidenceRefsForConnector(runtime);
|
|
60
|
+
return [
|
|
23
61
|
{
|
|
24
62
|
id: "intent-social",
|
|
25
63
|
kind: "social",
|
|
26
|
-
priority:
|
|
64
|
+
priority: runtime.continuity.budgets && runtime.continuity.budgets.socialUsed >= runtime.continuity.budgets.socialLimit ? 10 : 60,
|
|
27
65
|
source: "tick",
|
|
28
66
|
summary: "engage social platforms",
|
|
29
|
-
effectClass: "
|
|
67
|
+
effectClass: "connector_action",
|
|
68
|
+
sourceRefs: refs,
|
|
69
|
+
idempotencyKey: "social:engage social platforms",
|
|
30
70
|
},
|
|
31
71
|
];
|
|
32
72
|
}
|
|
33
|
-
function
|
|
34
|
-
if (
|
|
73
|
+
function planQuietReflectionIntents(runtime) {
|
|
74
|
+
if (!runtime.rhythmWindow.quietBias && runtime.continuity.mode !== "quiet") {
|
|
35
75
|
return [];
|
|
36
76
|
}
|
|
37
|
-
|
|
38
|
-
|
|
77
|
+
const out = [];
|
|
78
|
+
if (isAllowedKind("quiet", runtime)) {
|
|
79
|
+
out.push({
|
|
80
|
+
id: "intent-quiet",
|
|
81
|
+
kind: "quiet",
|
|
82
|
+
priority: 55,
|
|
83
|
+
source: "quiet_plan",
|
|
84
|
+
summary: "quiet window bookkeeping",
|
|
85
|
+
effectClass: "no_effect",
|
|
86
|
+
sourceRefs: [],
|
|
87
|
+
idempotencyKey: "quiet:bookkeeping",
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
if (isAllowedKind("maintenance", runtime)) {
|
|
91
|
+
out.push({
|
|
39
92
|
id: "intent-maintenance",
|
|
40
93
|
kind: "maintenance",
|
|
41
|
-
priority:
|
|
94
|
+
priority: 50,
|
|
42
95
|
source: "quiet_plan",
|
|
43
96
|
summary: "run maintenance checks",
|
|
44
97
|
effectClass: "maintenance",
|
|
45
|
-
|
|
46
|
-
|
|
98
|
+
sourceRefs: [],
|
|
99
|
+
idempotencyKey: "maintenance:checks",
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
if (isAllowedKind("reflection", runtime)) {
|
|
103
|
+
const refs = evidenceRefsForConnector(runtime);
|
|
104
|
+
out.push({
|
|
47
105
|
id: "intent-reflection",
|
|
48
106
|
kind: "reflection",
|
|
49
|
-
priority:
|
|
107
|
+
priority: 45,
|
|
50
108
|
source: "quiet_plan",
|
|
51
109
|
summary: "run narrative reflection",
|
|
52
110
|
effectClass: "narrative_reflection",
|
|
53
|
-
|
|
54
|
-
|
|
111
|
+
sourceRefs: refs,
|
|
112
|
+
idempotencyKey: "reflection:narrative",
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
return out;
|
|
55
116
|
}
|
|
56
|
-
function planOutreachIntents(
|
|
57
|
-
if (
|
|
117
|
+
function planOutreachIntents(runtime) {
|
|
118
|
+
if (!isAllowedKind("outreach", runtime))
|
|
119
|
+
return [];
|
|
120
|
+
if (runtime.continuity.recentOutreachHashes.length > 3) {
|
|
58
121
|
return [];
|
|
59
122
|
}
|
|
123
|
+
const refs = evidenceRefsForConnector(runtime);
|
|
60
124
|
return [
|
|
61
125
|
{
|
|
62
126
|
id: "intent-outreach",
|
|
@@ -65,24 +129,67 @@ function planOutreachIntents(snapshot) {
|
|
|
65
129
|
source: "tick",
|
|
66
130
|
summary: "consider proactive user outreach",
|
|
67
131
|
effectClass: "user_outreach",
|
|
132
|
+
sourceRefs: refs,
|
|
133
|
+
idempotencyKey: "outreach:consider proactive user outreach",
|
|
68
134
|
},
|
|
69
135
|
];
|
|
70
136
|
}
|
|
71
|
-
|
|
137
|
+
/**
|
|
138
|
+
* Plan ordered candidates for one heartbeat turn using rhythm window + life evidence slice.
|
|
139
|
+
*/
|
|
140
|
+
export function planCandidateIntents(runtime) {
|
|
141
|
+
if (runtime.continuity.mode === "paused_for_interrupt") {
|
|
142
|
+
const pausedMaintenance = [
|
|
143
|
+
{
|
|
144
|
+
id: "intent-maintenance",
|
|
145
|
+
kind: "maintenance",
|
|
146
|
+
priority: 40,
|
|
147
|
+
source: "tick",
|
|
148
|
+
summary: "run maintenance checks",
|
|
149
|
+
effectClass: "maintenance",
|
|
150
|
+
sourceRefs: [],
|
|
151
|
+
idempotencyKey: "maintenance:checks",
|
|
152
|
+
},
|
|
153
|
+
];
|
|
154
|
+
return pausedMaintenance
|
|
155
|
+
.filter((intent) => runtime.rhythmWindow.allowedIntentKinds.includes(intent.kind))
|
|
156
|
+
.slice(0, MAX_CANDIDATE_INTENTS);
|
|
157
|
+
}
|
|
158
|
+
if (runtime.continuity.mode === "maintenance_only") {
|
|
159
|
+
return planWorkIntents(runtime).sort((a, b) => b.priority - a.priority).slice(0, MAX_CANDIDATE_INTENTS);
|
|
160
|
+
}
|
|
72
161
|
const intents = [
|
|
73
|
-
...
|
|
74
|
-
...
|
|
75
|
-
...
|
|
76
|
-
...
|
|
162
|
+
...planWorkIntents(runtime),
|
|
163
|
+
...planExplorationIntents(runtime),
|
|
164
|
+
...planSocialIntents(runtime),
|
|
165
|
+
...planQuietReflectionIntents(runtime),
|
|
166
|
+
...planOutreachIntents(runtime),
|
|
77
167
|
];
|
|
78
168
|
return intents
|
|
169
|
+
.filter((intent) => runtime.rhythmWindow.allowedIntentKinds.includes(intent.kind))
|
|
79
170
|
.sort((a, b) => b.priority - a.priority)
|
|
80
|
-
.slice(0,
|
|
171
|
+
.slice(0, MAX_CANDIDATE_INTENTS);
|
|
172
|
+
}
|
|
173
|
+
/** @deprecated Continuity-only helper for tests; prefer `planCandidateIntents` + `buildHeartbeatRuntimeSnapshot`. */
|
|
174
|
+
export function planIntent(snapshot) {
|
|
175
|
+
const inputs = {
|
|
176
|
+
mode: snapshot.mode,
|
|
177
|
+
currentWindowId: snapshot.currentWindowId,
|
|
178
|
+
pendingObligations: snapshot.pendingObligations,
|
|
179
|
+
recentOutreachHashes: snapshot.recentOutreachHashes,
|
|
180
|
+
deniedIntents: snapshot.deniedIntents,
|
|
181
|
+
budgets: snapshot.budgets,
|
|
182
|
+
awaitingUserInput: snapshot.awaitingUserInput,
|
|
183
|
+
riskSuppressed: snapshot.riskSuppressed,
|
|
184
|
+
quietEnabledBridge: snapshot.mode === "quiet",
|
|
185
|
+
};
|
|
186
|
+
const runtime = buildHeartbeatRuntimeSnapshot("2026-03-25T12:00:00.000Z", inputs, snapshot);
|
|
187
|
+
return planCandidateIntents(runtime);
|
|
81
188
|
}
|
|
82
189
|
export function decideDecisionBasis(intent) {
|
|
83
190
|
if (intent.source === "obligation")
|
|
84
191
|
return "rule_only";
|
|
85
|
-
if (intent.
|
|
192
|
+
if (intent.effectClass === "maintenance" || intent.effectClass === "no_effect")
|
|
86
193
|
return "rule_only";
|
|
87
194
|
if (intent.kind === "outreach" || intent.kind === "reflection")
|
|
88
195
|
return "model_assisted";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type EffectClass = "external_platform_action" | "memory_curation" | "narrative_reflection" | "user_outreach" | "maintenance";
|
|
1
|
+
export type EffectClass = "external_platform_action" | "connector_action" | "memory_curation" | "narrative_reflection" | "user_outreach" | "maintenance" | "no_effect";
|
|
2
2
|
export interface LeaseHandle {
|
|
3
3
|
id: string;
|
|
4
4
|
granted: boolean;
|
|
@@ -50,7 +50,7 @@ export class LeaseManager {
|
|
|
50
50
|
};
|
|
51
51
|
}
|
|
52
52
|
resolveScope(effectClass, scopeHint) {
|
|
53
|
-
if (effectClass === "external_platform_action" || effectClass === "user_outreach") {
|
|
53
|
+
if (effectClass === "external_platform_action" || effectClass === "connector_action" || effectClass === "user_outreach") {
|
|
54
54
|
return scopeHint && scopeHint.length > 0 ? `${GLOBAL_SCOPE}:${scopeHint}` : GLOBAL_SCOPE;
|
|
55
55
|
}
|
|
56
56
|
return null;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { OutreachDraftRequest } from "../../../guidance/outreach-draft-schema.js";
|
|
2
|
+
import type { CandidateIntent } from "../types.js";
|
|
3
|
+
import type { HeartbeatRuntimeSnapshot } from "../heartbeat/runtime-snapshot.js";
|
|
4
|
+
import type { OutreachJudgment } from "./judge-outreach.js";
|
|
5
|
+
import type { DeliveryTargetResolution } from "./delivery-target.js";
|
|
6
|
+
export declare function buildOutreachDraftRequest(candidate: CandidateIntent, judgment: OutreachJudgment, snapshot: HeartbeatRuntimeSnapshot, delivery: DeliveryTargetResolution): OutreachDraftRequest;
|