@haaaiawd/second-nature 0.1.18 → 0.1.19

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.
Files changed (188) hide show
  1. package/index.js +855 -855
  2. package/openclaw.plugin.json +29 -29
  3. package/package.json +52 -52
  4. package/runtime/cli/commands/index.d.ts +14 -14
  5. package/runtime/cli/commands/index.js +193 -193
  6. package/runtime/cli/explain/explain-surface-subject.d.ts +8 -8
  7. package/runtime/cli/explain/explain-surface-subject.js +9 -9
  8. package/runtime/cli/explain/format-explanation.d.ts +12 -12
  9. package/runtime/cli/explain/format-explanation.js +12 -12
  10. package/runtime/cli/explain/resolve-subject.js +41 -41
  11. package/runtime/cli/host-capability/classify-delivery.d.ts +14 -14
  12. package/runtime/cli/host-capability/classify-delivery.js +20 -20
  13. package/runtime/cli/host-capability/probe-host-capability.d.ts +2 -2
  14. package/runtime/cli/host-capability/probe-host-capability.js +58 -58
  15. package/runtime/cli/host-capability/record-host-capability.d.ts +6 -6
  16. package/runtime/cli/host-capability/record-host-capability.js +14 -14
  17. package/runtime/cli/host-capability/types.d.ts +71 -71
  18. package/runtime/cli/host-capability/types.js +6 -6
  19. package/runtime/cli/host-smoke/run-host-smoke.d.ts +2 -2
  20. package/runtime/cli/host-smoke/run-host-smoke.js +40 -40
  21. package/runtime/cli/host-smoke/types.d.ts +35 -35
  22. package/runtime/cli/host-smoke/types.js +6 -6
  23. package/runtime/cli/index.js +65 -58
  24. package/runtime/cli/ops/heartbeat-surface.d.ts +45 -38
  25. package/runtime/cli/ops/heartbeat-surface.js +79 -73
  26. package/runtime/cli/ops/ops-router.d.ts +26 -19
  27. package/runtime/cli/ops/ops-router.js +102 -89
  28. package/runtime/cli/ops/show-operator-fallback.d.ts +13 -13
  29. package/runtime/cli/ops/show-operator-fallback.js +22 -22
  30. package/runtime/cli/ops/workspace-heartbeat-runner.d.ts +40 -19
  31. package/runtime/cli/ops/workspace-heartbeat-runner.js +93 -39
  32. package/runtime/cli/read-models/index.d.ts +35 -29
  33. package/runtime/cli/read-models/index.js +365 -256
  34. package/runtime/cli/read-models/operator-explain-map.d.ts +6 -6
  35. package/runtime/cli/read-models/operator-explain-map.js +10 -10
  36. package/runtime/cli/read-models/types.d.ts +112 -79
  37. package/runtime/cli/runtime/runtime-artifact-boundary.d.ts +28 -28
  38. package/runtime/cli/runtime/runtime-artifact-boundary.js +94 -94
  39. package/runtime/connectors/base/contract.d.ts +87 -87
  40. package/runtime/connectors/base/execution-policy.d.ts +47 -47
  41. package/runtime/connectors/base/execution-policy.js +82 -82
  42. package/runtime/connectors/base/index.d.ts +8 -8
  43. package/runtime/connectors/base/index.js +8 -8
  44. package/runtime/connectors/base/manifest.d.ts +64 -64
  45. package/runtime/connectors/base/manifest.js +86 -86
  46. package/runtime/connectors/base/map-life-evidence.d.ts +16 -16
  47. package/runtime/connectors/base/map-life-evidence.js +79 -79
  48. package/runtime/connectors/base/policy-layer.d.ts +29 -29
  49. package/runtime/connectors/base/policy-layer.js +198 -198
  50. package/runtime/connectors/base/route-planner.js +99 -99
  51. package/runtime/connectors/index.d.ts +5 -5
  52. package/runtime/connectors/index.js +5 -5
  53. package/runtime/connectors/near-real/near-real-connector-smoke.d.ts +19 -19
  54. package/runtime/connectors/near-real/near-real-connector-smoke.js +152 -152
  55. package/runtime/core/second-nature/heartbeat/heartbeat-executor.js +114 -114
  56. package/runtime/core/second-nature/heartbeat/heartbeat-loop.d.ts +63 -63
  57. package/runtime/core/second-nature/heartbeat/heartbeat-loop.js +162 -139
  58. package/runtime/core/second-nature/heartbeat/index.d.ts +8 -8
  59. package/runtime/core/second-nature/heartbeat/index.js +7 -7
  60. package/runtime/core/second-nature/heartbeat/run-heartbeat-cycle.d.ts +21 -21
  61. package/runtime/core/second-nature/heartbeat/run-heartbeat-cycle.js +35 -35
  62. package/runtime/core/second-nature/heartbeat/runtime-snapshot.d.ts +28 -28
  63. package/runtime/core/second-nature/heartbeat/runtime-snapshot.js +35 -35
  64. package/runtime/core/second-nature/heartbeat/signal.d.ts +42 -42
  65. package/runtime/core/second-nature/heartbeat/snapshot-builder.d.ts +51 -51
  66. package/runtime/core/second-nature/index.d.ts +22 -22
  67. package/runtime/core/second-nature/index.js +22 -22
  68. package/runtime/core/second-nature/orchestrator/effect-dispatcher.d.ts +100 -100
  69. package/runtime/core/second-nature/orchestrator/effect-dispatcher.js +144 -144
  70. package/runtime/core/second-nature/orchestrator/guard-layer.d.ts +8 -8
  71. package/runtime/core/second-nature/orchestrator/guard-layer.js +110 -110
  72. package/runtime/core/second-nature/orchestrator/intent-planner.d.ts +13 -13
  73. package/runtime/core/second-nature/orchestrator/intent-planner.js +199 -199
  74. package/runtime/core/second-nature/orchestrator/lease-manager.d.ts +14 -14
  75. package/runtime/core/second-nature/orchestrator/lease-manager.js +58 -58
  76. package/runtime/core/second-nature/outreach/build-outreach-draft-request.d.ts +6 -6
  77. package/runtime/core/second-nature/outreach/build-outreach-draft-request.js +63 -63
  78. package/runtime/core/second-nature/outreach/delivery-target.d.ts +26 -26
  79. package/runtime/core/second-nature/outreach/delivery-target.js +70 -70
  80. package/runtime/core/second-nature/outreach/dispatch-user-outreach.d.ts +38 -38
  81. package/runtime/core/second-nature/outreach/dispatch-user-outreach.js +119 -119
  82. package/runtime/core/second-nature/outreach/judge-input-from-snapshot.d.ts +7 -7
  83. package/runtime/core/second-nature/outreach/judge-input-from-snapshot.js +45 -45
  84. package/runtime/core/second-nature/outreach/judge-outreach.d.ts +40 -40
  85. package/runtime/core/second-nature/outreach/judge-outreach.js +121 -121
  86. package/runtime/core/second-nature/quiet/run-source-backed-quiet.d.ts +21 -21
  87. package/runtime/core/second-nature/quiet/run-source-backed-quiet.js +123 -123
  88. package/runtime/core/second-nature/rhythm/planner-rhythm-window.d.ts +15 -15
  89. package/runtime/core/second-nature/rhythm/planner-rhythm-window.js +52 -52
  90. package/runtime/core/second-nature/rhythm/policy-bridge.d.ts +19 -19
  91. package/runtime/core/second-nature/rhythm/policy-bridge.js +34 -34
  92. package/runtime/core/second-nature/runtime/service-entry.js +45 -45
  93. package/runtime/core/second-nature/types.d.ts +51 -51
  94. package/runtime/guidance/draft-outreach-message.d.ts +7 -7
  95. package/runtime/guidance/draft-outreach-message.js +42 -42
  96. package/runtime/guidance/evidence-guidance.d.ts +40 -40
  97. package/runtime/guidance/evidence-guidance.js +52 -52
  98. package/runtime/guidance/index.d.ts +11 -11
  99. package/runtime/guidance/index.js +11 -11
  100. package/runtime/guidance/outreach-draft-schema.d.ts +228 -228
  101. package/runtime/guidance/outreach-draft-schema.js +80 -80
  102. package/runtime/observability/audit/append-only-audit-store.d.ts +14 -14
  103. package/runtime/observability/audit/append-only-audit-store.js +21 -21
  104. package/runtime/observability/audit/audit-envelope.d.ts +51 -51
  105. package/runtime/observability/audit/audit-envelope.js +130 -130
  106. package/runtime/observability/audit/verify-audit-hash-chain.d.ts +23 -23
  107. package/runtime/observability/audit/verify-audit-hash-chain.js +83 -83
  108. package/runtime/observability/db/index.js +47 -47
  109. package/runtime/observability/db/schema/host-capability-reports.d.ts +180 -180
  110. package/runtime/observability/db/schema/host-capability-reports.js +12 -12
  111. package/runtime/observability/db/schema/index.d.ts +947 -947
  112. package/runtime/observability/db/schema/index.js +71 -71
  113. package/runtime/observability/index.d.ts +20 -20
  114. package/runtime/observability/index.js +19 -19
  115. package/runtime/observability/query/explain-query.d.ts +48 -48
  116. package/runtime/observability/query/explain-query.js +114 -114
  117. package/runtime/observability/query/export-audit-bundle.d.ts +22 -22
  118. package/runtime/observability/query/export-audit-bundle.js +27 -27
  119. package/runtime/observability/services/decision-ledger.d.ts +46 -46
  120. package/runtime/observability/services/decision-ledger.js +161 -161
  121. package/runtime/observability/services/governance-audit.d.ts +41 -41
  122. package/runtime/observability/services/governance-audit.js +163 -163
  123. package/runtime/observability/services/governance-plane-recorder.d.ts +47 -47
  124. package/runtime/observability/services/governance-plane-recorder.js +55 -55
  125. package/runtime/observability/services/lived-experience-audit.d.ts +97 -97
  126. package/runtime/observability/services/lived-experience-audit.js +162 -162
  127. package/runtime/observability/services/runtime-decision-recorder.d.ts +29 -29
  128. package/runtime/observability/services/runtime-decision-recorder.js +94 -94
  129. package/runtime/storage/bootstrap/native-sqlite-probe.d.ts +7 -7
  130. package/runtime/storage/bootstrap/native-sqlite-probe.js +28 -28
  131. package/runtime/storage/bootstrap/repair-gate.d.ts +17 -17
  132. package/runtime/storage/bootstrap/repair-gate.js +71 -71
  133. package/runtime/storage/bootstrap/storage-mode-smoke.d.ts +38 -38
  134. package/runtime/storage/bootstrap/storage-mode-smoke.js +85 -85
  135. package/runtime/storage/db/index.js +61 -61
  136. package/runtime/storage/db/schema/delivery-attempts.d.ts +199 -199
  137. package/runtime/storage/db/schema/delivery-attempts.js +13 -13
  138. package/runtime/storage/db/schema/index.d.ts +9 -9
  139. package/runtime/storage/db/schema/index.js +9 -9
  140. package/runtime/storage/db/schema/life-evidence-index.d.ts +161 -161
  141. package/runtime/storage/db/schema/life-evidence-index.js +11 -11
  142. package/runtime/storage/db/schema/operator-fallback-artifacts.d.ts +161 -161
  143. package/runtime/storage/db/schema/operator-fallback-artifacts.js +11 -11
  144. package/runtime/storage/db/schema/policies.d.ts +98 -98
  145. package/runtime/storage/db/schema/policies.js +8 -8
  146. package/runtime/storage/delivery/query-delivery-attempts.d.ts +3 -3
  147. package/runtime/storage/delivery/query-delivery-attempts.js +32 -32
  148. package/runtime/storage/delivery/types.d.ts +27 -27
  149. package/runtime/storage/delivery/types.js +1 -1
  150. package/runtime/storage/delivery/write-delivery-attempt.d.ts +6 -6
  151. package/runtime/storage/delivery/write-delivery-attempt.js +36 -36
  152. package/runtime/storage/fallback/load-operator-fallback.d.ts +14 -14
  153. package/runtime/storage/fallback/load-operator-fallback.js +47 -47
  154. package/runtime/storage/fallback/operator-fallback-types.d.ts +9 -9
  155. package/runtime/storage/fallback/operator-fallback-types.js +1 -1
  156. package/runtime/storage/fallback/operator-fallback-view.d.ts +11 -11
  157. package/runtime/storage/fallback/operator-fallback-view.js +1 -1
  158. package/runtime/storage/fallback/write-operator-fallback.d.ts +6 -6
  159. package/runtime/storage/fallback/write-operator-fallback.js +21 -21
  160. package/runtime/storage/index.d.ts +37 -37
  161. package/runtime/storage/index.js +30 -30
  162. package/runtime/storage/life-evidence/append-life-evidence.d.ts +7 -7
  163. package/runtime/storage/life-evidence/append-life-evidence.js +64 -64
  164. package/runtime/storage/life-evidence/types.d.ts +45 -45
  165. package/runtime/storage/life-evidence/types.js +6 -6
  166. package/runtime/storage/quiet/persist-quiet-artifact.d.ts +7 -7
  167. package/runtime/storage/quiet/persist-quiet-artifact.js +22 -22
  168. package/runtime/storage/quiet/quiet-artifact-types.d.ts +18 -18
  169. package/runtime/storage/quiet/quiet-artifact-types.js +1 -1
  170. package/runtime/storage/quiet/quiet-artifact-writer.d.ts +15 -15
  171. package/runtime/storage/quiet/quiet-artifact-writer.js +56 -56
  172. package/runtime/storage/repositories/credential-repository.js +30 -30
  173. package/runtime/storage/rhythm/rhythm-policy-snapshot.d.ts +10 -10
  174. package/runtime/storage/rhythm/rhythm-policy-snapshot.js +34 -34
  175. package/runtime/storage/services/credential-vault.d.ts +13 -13
  176. package/runtime/storage/services/credential-vault.js +116 -116
  177. package/runtime/storage/snapshots/continuity-snapshot.d.ts +9 -9
  178. package/runtime/storage/snapshots/continuity-snapshot.js +41 -41
  179. package/runtime/storage/snapshots/life-evidence-snapshot.d.ts +6 -6
  180. package/runtime/storage/snapshots/life-evidence-snapshot.js +114 -114
  181. package/runtime/storage/snapshots/types.d.ts +58 -58
  182. package/runtime/storage/snapshots/types.js +1 -1
  183. package/runtime/storage/state-api.js +104 -104
  184. package/runtime/storage/user-interest/load-user-interest-snapshot.d.ts +2 -2
  185. package/runtime/storage/user-interest/load-user-interest-snapshot.js +150 -150
  186. package/runtime/storage/user-interest/types.d.ts +25 -25
  187. package/runtime/storage/user-interest/types.js +1 -1
  188. package/workspace-ops-bridge.js +81 -81
@@ -1,199 +1,199 @@
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) => ({
29
- id: `intent-obligation-${index}`,
30
- kind: "work",
31
- priority: 100 - index,
32
- source: "obligation",
33
- summary: `fulfill obligation: ${obligation}`,
34
- effectClass: "connector_action",
35
- sourceRefs: [...OBLIGATION_SOURCE],
36
- idempotencyKey: `obligation:${obligation}:${index}`,
37
- }));
38
- }
39
- function planExplorationIntents(runtime) {
40
- if (!isAllowedKind("exploration", runtime))
41
- return [];
42
- const refs = evidenceRefsForConnector(runtime);
43
- return [
44
- {
45
- id: "intent-exploration",
46
- kind: "exploration",
47
- priority: 70,
48
- source: "tick",
49
- summary: "scan platform opportunities",
50
- effectClass: "connector_action",
51
- sourceRefs: refs,
52
- idempotencyKey: "exploration:scan platform opportunities",
53
- },
54
- ];
55
- }
56
- function planSocialIntents(runtime) {
57
- if (!isAllowedKind("social", runtime))
58
- return [];
59
- const refs = evidenceRefsForConnector(runtime);
60
- return [
61
- {
62
- id: "intent-social",
63
- kind: "social",
64
- priority: runtime.continuity.budgets && runtime.continuity.budgets.socialUsed >= runtime.continuity.budgets.socialLimit ? 10 : 60,
65
- source: "tick",
66
- summary: "engage social platforms",
67
- effectClass: "connector_action",
68
- sourceRefs: refs,
69
- idempotencyKey: "social:engage social platforms",
70
- },
71
- ];
72
- }
73
- function planQuietReflectionIntents(runtime) {
74
- if (!runtime.rhythmWindow.quietBias && runtime.continuity.mode !== "quiet") {
75
- return [];
76
- }
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({
92
- id: "intent-maintenance",
93
- kind: "maintenance",
94
- priority: 50,
95
- source: "quiet_plan",
96
- summary: "run maintenance checks",
97
- effectClass: "maintenance",
98
- sourceRefs: [],
99
- idempotencyKey: "maintenance:checks",
100
- });
101
- }
102
- if (isAllowedKind("reflection", runtime)) {
103
- const refs = evidenceRefsForConnector(runtime);
104
- out.push({
105
- id: "intent-reflection",
106
- kind: "reflection",
107
- priority: 45,
108
- source: "quiet_plan",
109
- summary: "run narrative reflection",
110
- effectClass: "narrative_reflection",
111
- sourceRefs: refs,
112
- idempotencyKey: "reflection:narrative",
113
- });
114
- }
115
- return out;
116
- }
117
- function planOutreachIntents(runtime) {
118
- if (!isAllowedKind("outreach", runtime))
119
- return [];
120
- if (runtime.continuity.recentOutreachHashes.length > 3) {
121
- return [];
122
- }
123
- const refs = evidenceRefsForConnector(runtime);
124
- return [
125
- {
126
- id: "intent-outreach",
127
- kind: "outreach",
128
- priority: 40,
129
- source: "tick",
130
- summary: "consider proactive user outreach",
131
- effectClass: "user_outreach",
132
- sourceRefs: refs,
133
- idempotencyKey: "outreach:consider proactive user outreach",
134
- },
135
- ];
136
- }
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
- }
161
- const intents = [
162
- ...planWorkIntents(runtime),
163
- ...planExplorationIntents(runtime),
164
- ...planSocialIntents(runtime),
165
- ...planQuietReflectionIntents(runtime),
166
- ...planOutreachIntents(runtime),
167
- ];
168
- return intents
169
- .filter((intent) => runtime.rhythmWindow.allowedIntentKinds.includes(intent.kind))
170
- .sort((a, b) => b.priority - a.priority)
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);
188
- }
189
- export function decideDecisionBasis(intent) {
190
- if (intent.source === "obligation")
191
- return "rule_only";
192
- if (intent.effectClass === "maintenance" || intent.effectClass === "no_effect")
193
- return "rule_only";
194
- if (intent.kind === "outreach" || intent.kind === "reflection")
195
- return "model_assisted";
196
- if (intent.kind === "exploration" || intent.kind === "social" || intent.kind === "work")
197
- return "score_based";
198
- return "rule_only";
199
- }
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) => ({
29
+ id: `intent-obligation-${index}`,
30
+ kind: "work",
31
+ priority: 100 - index,
32
+ source: "obligation",
33
+ summary: `fulfill obligation: ${obligation}`,
34
+ effectClass: "connector_action",
35
+ sourceRefs: [...OBLIGATION_SOURCE],
36
+ idempotencyKey: `obligation:${obligation}:${index}`,
37
+ }));
38
+ }
39
+ function planExplorationIntents(runtime) {
40
+ if (!isAllowedKind("exploration", runtime))
41
+ return [];
42
+ const refs = evidenceRefsForConnector(runtime);
43
+ return [
44
+ {
45
+ id: "intent-exploration",
46
+ kind: "exploration",
47
+ priority: 70,
48
+ source: "tick",
49
+ summary: "scan platform opportunities",
50
+ effectClass: "connector_action",
51
+ sourceRefs: refs,
52
+ idempotencyKey: "exploration:scan platform opportunities",
53
+ },
54
+ ];
55
+ }
56
+ function planSocialIntents(runtime) {
57
+ if (!isAllowedKind("social", runtime))
58
+ return [];
59
+ const refs = evidenceRefsForConnector(runtime);
60
+ return [
61
+ {
62
+ id: "intent-social",
63
+ kind: "social",
64
+ priority: runtime.continuity.budgets && runtime.continuity.budgets.socialUsed >= runtime.continuity.budgets.socialLimit ? 10 : 60,
65
+ source: "tick",
66
+ summary: "engage social platforms",
67
+ effectClass: "connector_action",
68
+ sourceRefs: refs,
69
+ idempotencyKey: "social:engage social platforms",
70
+ },
71
+ ];
72
+ }
73
+ function planQuietReflectionIntents(runtime) {
74
+ if (!runtime.rhythmWindow.quietBias && runtime.continuity.mode !== "quiet") {
75
+ return [];
76
+ }
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({
92
+ id: "intent-maintenance",
93
+ kind: "maintenance",
94
+ priority: 50,
95
+ source: "quiet_plan",
96
+ summary: "run maintenance checks",
97
+ effectClass: "maintenance",
98
+ sourceRefs: [],
99
+ idempotencyKey: "maintenance:checks",
100
+ });
101
+ }
102
+ if (isAllowedKind("reflection", runtime)) {
103
+ const refs = evidenceRefsForConnector(runtime);
104
+ out.push({
105
+ id: "intent-reflection",
106
+ kind: "reflection",
107
+ priority: 45,
108
+ source: "quiet_plan",
109
+ summary: "run narrative reflection",
110
+ effectClass: "narrative_reflection",
111
+ sourceRefs: refs,
112
+ idempotencyKey: "reflection:narrative",
113
+ });
114
+ }
115
+ return out;
116
+ }
117
+ function planOutreachIntents(runtime) {
118
+ if (!isAllowedKind("outreach", runtime))
119
+ return [];
120
+ if (runtime.continuity.recentOutreachHashes.length > 3) {
121
+ return [];
122
+ }
123
+ const refs = evidenceRefsForConnector(runtime);
124
+ return [
125
+ {
126
+ id: "intent-outreach",
127
+ kind: "outreach",
128
+ priority: 40,
129
+ source: "tick",
130
+ summary: "consider proactive user outreach",
131
+ effectClass: "user_outreach",
132
+ sourceRefs: refs,
133
+ idempotencyKey: "outreach:consider proactive user outreach",
134
+ },
135
+ ];
136
+ }
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
+ }
161
+ const intents = [
162
+ ...planWorkIntents(runtime),
163
+ ...planExplorationIntents(runtime),
164
+ ...planSocialIntents(runtime),
165
+ ...planQuietReflectionIntents(runtime),
166
+ ...planOutreachIntents(runtime),
167
+ ];
168
+ return intents
169
+ .filter((intent) => runtime.rhythmWindow.allowedIntentKinds.includes(intent.kind))
170
+ .sort((a, b) => b.priority - a.priority)
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);
188
+ }
189
+ export function decideDecisionBasis(intent) {
190
+ if (intent.source === "obligation")
191
+ return "rule_only";
192
+ if (intent.effectClass === "maintenance" || intent.effectClass === "no_effect")
193
+ return "rule_only";
194
+ if (intent.kind === "outreach" || intent.kind === "reflection")
195
+ return "model_assisted";
196
+ if (intent.kind === "exploration" || intent.kind === "social" || intent.kind === "work")
197
+ return "score_based";
198
+ return "rule_only";
199
+ }
@@ -1,14 +1,14 @@
1
- export type EffectClass = "external_platform_action" | "connector_action" | "memory_curation" | "narrative_reflection" | "user_outreach" | "maintenance" | "no_effect";
2
- export interface LeaseHandle {
3
- id: string;
4
- granted: boolean;
5
- scope: string;
6
- release(): Promise<void>;
7
- }
8
- export declare class LeaseManager {
9
- private readonly ttlMs;
10
- private readonly leases;
11
- constructor(ttlMs?: number);
12
- acquire(effectClass: EffectClass, scopeHint?: string): Promise<LeaseHandle>;
13
- private resolveScope;
14
- }
1
+ export type EffectClass = "external_platform_action" | "connector_action" | "memory_curation" | "narrative_reflection" | "user_outreach" | "maintenance" | "no_effect";
2
+ export interface LeaseHandle {
3
+ id: string;
4
+ granted: boolean;
5
+ scope: string;
6
+ release(): Promise<void>;
7
+ }
8
+ export declare class LeaseManager {
9
+ private readonly ttlMs;
10
+ private readonly leases;
11
+ constructor(ttlMs?: number);
12
+ acquire(effectClass: EffectClass, scopeHint?: string): Promise<LeaseHandle>;
13
+ private resolveScope;
14
+ }
@@ -1,58 +1,58 @@
1
- import * as crypto from "crypto";
2
- const GLOBAL_SCOPE = "global-control-plane-flight";
3
- const DEFAULT_TTL_MS = 90_000;
4
- export class LeaseManager {
5
- ttlMs;
6
- leases = new Map();
7
- constructor(ttlMs = DEFAULT_TTL_MS) {
8
- this.ttlMs = ttlMs;
9
- }
10
- async acquire(effectClass, scopeHint) {
11
- const scope = this.resolveScope(effectClass, scopeHint);
12
- if (!scope) {
13
- return {
14
- id: "no-lease-required",
15
- granted: true,
16
- scope: "none",
17
- async release() {
18
- return;
19
- },
20
- };
21
- }
22
- const now = Date.now();
23
- const existing = this.leases.get(scope);
24
- if (existing && existing.expiresAt > now) {
25
- return {
26
- id: existing.id,
27
- granted: false,
28
- scope,
29
- async release() {
30
- return;
31
- },
32
- };
33
- }
34
- const record = {
35
- id: crypto.randomUUID(),
36
- scope,
37
- expiresAt: now + this.ttlMs,
38
- };
39
- this.leases.set(scope, record);
40
- return {
41
- id: record.id,
42
- granted: true,
43
- scope,
44
- release: async () => {
45
- const current = this.leases.get(scope);
46
- if (current && current.id === record.id) {
47
- this.leases.delete(scope);
48
- }
49
- },
50
- };
51
- }
52
- resolveScope(effectClass, scopeHint) {
53
- if (effectClass === "external_platform_action" || effectClass === "connector_action" || effectClass === "user_outreach") {
54
- return scopeHint && scopeHint.length > 0 ? `${GLOBAL_SCOPE}:${scopeHint}` : GLOBAL_SCOPE;
55
- }
56
- return null;
57
- }
58
- }
1
+ import * as crypto from "crypto";
2
+ const GLOBAL_SCOPE = "global-control-plane-flight";
3
+ const DEFAULT_TTL_MS = 90_000;
4
+ export class LeaseManager {
5
+ ttlMs;
6
+ leases = new Map();
7
+ constructor(ttlMs = DEFAULT_TTL_MS) {
8
+ this.ttlMs = ttlMs;
9
+ }
10
+ async acquire(effectClass, scopeHint) {
11
+ const scope = this.resolveScope(effectClass, scopeHint);
12
+ if (!scope) {
13
+ return {
14
+ id: "no-lease-required",
15
+ granted: true,
16
+ scope: "none",
17
+ async release() {
18
+ return;
19
+ },
20
+ };
21
+ }
22
+ const now = Date.now();
23
+ const existing = this.leases.get(scope);
24
+ if (existing && existing.expiresAt > now) {
25
+ return {
26
+ id: existing.id,
27
+ granted: false,
28
+ scope,
29
+ async release() {
30
+ return;
31
+ },
32
+ };
33
+ }
34
+ const record = {
35
+ id: crypto.randomUUID(),
36
+ scope,
37
+ expiresAt: now + this.ttlMs,
38
+ };
39
+ this.leases.set(scope, record);
40
+ return {
41
+ id: record.id,
42
+ granted: true,
43
+ scope,
44
+ release: async () => {
45
+ const current = this.leases.get(scope);
46
+ if (current && current.id === record.id) {
47
+ this.leases.delete(scope);
48
+ }
49
+ },
50
+ };
51
+ }
52
+ resolveScope(effectClass, scopeHint) {
53
+ if (effectClass === "external_platform_action" || effectClass === "connector_action" || effectClass === "user_outreach") {
54
+ return scopeHint && scopeHint.length > 0 ? `${GLOBAL_SCOPE}:${scopeHint}` : GLOBAL_SCOPE;
55
+ }
56
+ return null;
57
+ }
58
+ }
@@ -1,6 +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;
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;