@haaaiawd/second-nature 0.1.16 → 0.1.18

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 -851
  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 +58 -54
  24. package/runtime/cli/ops/heartbeat-surface.d.ts +38 -35
  25. package/runtime/cli/ops/heartbeat-surface.js +73 -71
  26. package/runtime/cli/ops/ops-router.d.ts +19 -16
  27. package/runtime/cli/ops/ops-router.js +89 -87
  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 +19 -10
  31. package/runtime/cli/ops/workspace-heartbeat-runner.js +39 -26
  32. package/runtime/cli/read-models/index.d.ts +29 -29
  33. package/runtime/cli/read-models/index.js +256 -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 +79 -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 +139 -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 +124 -124
  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 -19
  114. package/runtime/observability/index.js +19 -18
  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 -0
  128. package/runtime/observability/services/runtime-decision-recorder.js +94 -0
  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 +154 -154
  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 -80
@@ -1,121 +1,121 @@
1
- /**
2
- * Control-plane outreach judgment (T2.3.1): value / interest / actionability / delivery / dedupe.
3
- *
4
- * Does not call guidance or perform delivery; callers supply guard-derived cooldown/duplicate flags.
5
- * Test coverage: tests/unit/core/outreach-judgment.test.ts
6
- */
7
- import * as crypto from "node:crypto";
8
- import { isDeliveryUnavailableReason, resolveDeliveryTarget, } from "./delivery-target.js";
9
- const OUTREACH_POLICY = {
10
- minValueScore: 0.35,
11
- minUserRelevance: 0.4,
12
- minActionabilityWhenInterestLow: 0.7,
13
- };
14
- function tokenize(text) {
15
- return text
16
- .toLowerCase()
17
- .split(/[^a-z0-9\u4e00-\u9fff]+/g)
18
- .filter((t) => t.length > 1);
19
- }
20
- function signalMatchesSummary(sig, summary) {
21
- const s = summary.toLowerCase();
22
- const t = sig.topic.toLowerCase();
23
- if (t.length > 0 && s.includes(t))
24
- return true;
25
- const wt = tokenize(sig.topic);
26
- const ws = new Set(tokenize(summary));
27
- return wt.some((x) => ws.has(x));
28
- }
29
- function matchInterestRefs(candidate, interest) {
30
- const matched = [];
31
- for (const sig of interest.signals) {
32
- if (signalMatchesSummary(sig, candidate.summary)) {
33
- matched.push(...sig.sourceRefs);
34
- }
35
- }
36
- const byId = new Map();
37
- for (const ref of matched) {
38
- byId.set(ref.id, ref);
39
- }
40
- return [...byId.values()];
41
- }
42
- function scoreOutreachValue(candidate, life) {
43
- if (candidate.sourceRefs.length === 0)
44
- return 0;
45
- const base = 0.35 + Math.min(0.35, candidate.sourceRefs.length * 0.06) + Math.min(0.2, candidate.priority * 0.02);
46
- if (life.empty)
47
- return Math.max(0, base - 0.15);
48
- return Math.min(1, base + Math.min(0.1, life.evidenceRefCount * 0.01));
49
- }
50
- function scoreUserRelevance(candidate, interest) {
51
- if (interest.staleness === "insufficient") {
52
- return Math.min(0.35, interest.confidence);
53
- }
54
- const refs = matchInterestRefs(candidate, interest);
55
- if (refs.length === 0)
56
- return interest.confidence * 0.45;
57
- return Math.min(1, interest.confidence * 0.65 + refs.length * 0.08);
58
- }
59
- function scoreActionability(candidate, interest, matchedInterestRefCount) {
60
- if (candidate.effectClass !== "user_outreach")
61
- return 0.5;
62
- if (interest.staleness === "insufficient" && matchedInterestRefCount === 0)
63
- return 0.55;
64
- return 0.78;
65
- }
66
- function resolveCooldownState(input) {
67
- if (input.duplicateBlocked)
68
- return "duplicate";
69
- if (input.cooldownBlocked)
70
- return "cooling_down";
71
- return "clear";
72
- }
73
- export function judgeOutreach(input) {
74
- const decisionId = `outreach_judgment:${crypto.randomUUID()}`;
75
- const deliveryResolution = resolveDeliveryTarget(input.delivery);
76
- const interestRefs = matchInterestRefs(input.candidate, input.userInterest);
77
- const valueScore = scoreOutreachValue(input.candidate, input.lifeEvidence);
78
- const userRelevance = scoreUserRelevance(input.candidate, input.userInterest);
79
- const actionability = scoreActionability(input.candidate, input.userInterest, interestRefs.length);
80
- const cooldownState = resolveCooldownState(input);
81
- const reasons = [];
82
- if (input.candidate.sourceRefs.length === 0)
83
- reasons.push("missing_source_refs");
84
- if (valueScore < OUTREACH_POLICY.minValueScore)
85
- reasons.push("value_score_too_low");
86
- if (userRelevance < OUTREACH_POLICY.minUserRelevance &&
87
- actionability < OUTREACH_POLICY.minActionabilityWhenInterestLow) {
88
- reasons.push("not_interest_relevant_or_actionable");
89
- }
90
- if (cooldownState === "cooling_down")
91
- reasons.push("cooling_down");
92
- if (cooldownState === "duplicate")
93
- reasons.push("duplicate");
94
- if (deliveryResolution.verdict !== "target_available") {
95
- reasons.push(deliveryResolution.verdict);
96
- }
97
- const blockingReasons = reasons.filter((r) => !isDeliveryUnavailableReason(r));
98
- let verdict;
99
- if (blockingReasons.length === 0) {
100
- verdict = "allow";
101
- }
102
- else if (blockingReasons.includes("cooling_down") || blockingReasons.includes("duplicate")) {
103
- verdict = "defer";
104
- }
105
- else {
106
- verdict = "deny";
107
- }
108
- return {
109
- decisionId,
110
- candidateId: input.candidate.id,
111
- verdict,
112
- valueScore,
113
- userRelevance,
114
- actionability,
115
- interestRefs,
116
- sourceRefs: input.candidate.sourceRefs,
117
- cooldownState,
118
- deliveryVerdict: deliveryResolution.verdict,
119
- reasons: reasons.length === 0 ? ["outreach_allowed"] : reasons,
120
- };
121
- }
1
+ /**
2
+ * Control-plane outreach judgment (T2.3.1): value / interest / actionability / delivery / dedupe.
3
+ *
4
+ * Does not call guidance or perform delivery; callers supply guard-derived cooldown/duplicate flags.
5
+ * Test coverage: tests/unit/core/outreach-judgment.test.ts
6
+ */
7
+ import * as crypto from "node:crypto";
8
+ import { isDeliveryUnavailableReason, resolveDeliveryTarget, } from "./delivery-target.js";
9
+ const OUTREACH_POLICY = {
10
+ minValueScore: 0.35,
11
+ minUserRelevance: 0.4,
12
+ minActionabilityWhenInterestLow: 0.7,
13
+ };
14
+ function tokenize(text) {
15
+ return text
16
+ .toLowerCase()
17
+ .split(/[^a-z0-9\u4e00-\u9fff]+/g)
18
+ .filter((t) => t.length > 1);
19
+ }
20
+ function signalMatchesSummary(sig, summary) {
21
+ const s = summary.toLowerCase();
22
+ const t = sig.topic.toLowerCase();
23
+ if (t.length > 0 && s.includes(t))
24
+ return true;
25
+ const wt = tokenize(sig.topic);
26
+ const ws = new Set(tokenize(summary));
27
+ return wt.some((x) => ws.has(x));
28
+ }
29
+ function matchInterestRefs(candidate, interest) {
30
+ const matched = [];
31
+ for (const sig of interest.signals) {
32
+ if (signalMatchesSummary(sig, candidate.summary)) {
33
+ matched.push(...sig.sourceRefs);
34
+ }
35
+ }
36
+ const byId = new Map();
37
+ for (const ref of matched) {
38
+ byId.set(ref.id, ref);
39
+ }
40
+ return [...byId.values()];
41
+ }
42
+ function scoreOutreachValue(candidate, life) {
43
+ if (candidate.sourceRefs.length === 0)
44
+ return 0;
45
+ const base = 0.35 + Math.min(0.35, candidate.sourceRefs.length * 0.06) + Math.min(0.2, candidate.priority * 0.02);
46
+ if (life.empty)
47
+ return Math.max(0, base - 0.15);
48
+ return Math.min(1, base + Math.min(0.1, life.evidenceRefCount * 0.01));
49
+ }
50
+ function scoreUserRelevance(candidate, interest) {
51
+ if (interest.staleness === "insufficient") {
52
+ return Math.min(0.35, interest.confidence);
53
+ }
54
+ const refs = matchInterestRefs(candidate, interest);
55
+ if (refs.length === 0)
56
+ return interest.confidence * 0.45;
57
+ return Math.min(1, interest.confidence * 0.65 + refs.length * 0.08);
58
+ }
59
+ function scoreActionability(candidate, interest, matchedInterestRefCount) {
60
+ if (candidate.effectClass !== "user_outreach")
61
+ return 0.5;
62
+ if (interest.staleness === "insufficient" && matchedInterestRefCount === 0)
63
+ return 0.55;
64
+ return 0.78;
65
+ }
66
+ function resolveCooldownState(input) {
67
+ if (input.duplicateBlocked)
68
+ return "duplicate";
69
+ if (input.cooldownBlocked)
70
+ return "cooling_down";
71
+ return "clear";
72
+ }
73
+ export function judgeOutreach(input) {
74
+ const decisionId = `outreach_judgment:${crypto.randomUUID()}`;
75
+ const deliveryResolution = resolveDeliveryTarget(input.delivery);
76
+ const interestRefs = matchInterestRefs(input.candidate, input.userInterest);
77
+ const valueScore = scoreOutreachValue(input.candidate, input.lifeEvidence);
78
+ const userRelevance = scoreUserRelevance(input.candidate, input.userInterest);
79
+ const actionability = scoreActionability(input.candidate, input.userInterest, interestRefs.length);
80
+ const cooldownState = resolveCooldownState(input);
81
+ const reasons = [];
82
+ if (input.candidate.sourceRefs.length === 0)
83
+ reasons.push("missing_source_refs");
84
+ if (valueScore < OUTREACH_POLICY.minValueScore)
85
+ reasons.push("value_score_too_low");
86
+ if (userRelevance < OUTREACH_POLICY.minUserRelevance &&
87
+ actionability < OUTREACH_POLICY.minActionabilityWhenInterestLow) {
88
+ reasons.push("not_interest_relevant_or_actionable");
89
+ }
90
+ if (cooldownState === "cooling_down")
91
+ reasons.push("cooling_down");
92
+ if (cooldownState === "duplicate")
93
+ reasons.push("duplicate");
94
+ if (deliveryResolution.verdict !== "target_available") {
95
+ reasons.push(deliveryResolution.verdict);
96
+ }
97
+ const blockingReasons = reasons.filter((r) => !isDeliveryUnavailableReason(r));
98
+ let verdict;
99
+ if (blockingReasons.length === 0) {
100
+ verdict = "allow";
101
+ }
102
+ else if (blockingReasons.includes("cooling_down") || blockingReasons.includes("duplicate")) {
103
+ verdict = "defer";
104
+ }
105
+ else {
106
+ verdict = "deny";
107
+ }
108
+ return {
109
+ decisionId,
110
+ candidateId: input.candidate.id,
111
+ verdict,
112
+ valueScore,
113
+ userRelevance,
114
+ actionability,
115
+ interestRefs,
116
+ sourceRefs: input.candidate.sourceRefs,
117
+ cooldownState,
118
+ deliveryVerdict: deliveryResolution.verdict,
119
+ reasons: reasons.length === 0 ? ["outreach_allowed"] : reasons,
120
+ };
121
+ }
@@ -1,21 +1,21 @@
1
- /**
2
- * Quiet / reflection orchestration: empty evidence → empty_state; otherwise coverage-gated artifact (T2.3.3).
3
- */
4
- import type { CandidateIntent } from "../types.js";
5
- import type { HeartbeatRuntimeSnapshot } from "../heartbeat/runtime-snapshot.js";
6
- import type { HeartbeatCycleResult } from "../heartbeat/signal.js";
7
- import { type QuietArtifactAck } from "../../../storage/quiet/quiet-artifact-writer.js";
8
- import type { UserInterestSnapshot } from "../../../storage/user-interest/types.js";
9
- export interface RunSourceBackedQuietParams {
10
- candidate: CandidateIntent;
11
- runtime: HeartbeatRuntimeSnapshot;
12
- day: string;
13
- userInterestSnapshot?: UserInterestSnapshot;
14
- workspaceRoot?: string;
15
- }
16
- export interface RunSourceBackedQuietResult {
17
- result: HeartbeatCycleResult;
18
- artifactAck?: QuietArtifactAck;
19
- persistedRelativePath?: string;
20
- }
21
- export declare function runSourceBackedQuiet(params: RunSourceBackedQuietParams): Promise<RunSourceBackedQuietResult>;
1
+ /**
2
+ * Quiet / reflection orchestration: empty evidence → empty_state; otherwise coverage-gated artifact (T2.3.3).
3
+ */
4
+ import type { CandidateIntent } from "../types.js";
5
+ import type { HeartbeatRuntimeSnapshot } from "../heartbeat/runtime-snapshot.js";
6
+ import type { HeartbeatCycleResult } from "../heartbeat/signal.js";
7
+ import { type QuietArtifactAck } from "../../../storage/quiet/quiet-artifact-writer.js";
8
+ import type { UserInterestSnapshot } from "../../../storage/user-interest/types.js";
9
+ export interface RunSourceBackedQuietParams {
10
+ candidate: CandidateIntent;
11
+ runtime: HeartbeatRuntimeSnapshot;
12
+ day: string;
13
+ userInterestSnapshot?: UserInterestSnapshot;
14
+ workspaceRoot?: string;
15
+ }
16
+ export interface RunSourceBackedQuietResult {
17
+ result: HeartbeatCycleResult;
18
+ artifactAck?: QuietArtifactAck;
19
+ persistedRelativePath?: string;
20
+ }
21
+ export declare function runSourceBackedQuiet(params: RunSourceBackedQuietParams): Promise<RunSourceBackedQuietResult>;
@@ -1,123 +1,123 @@
1
- import { isLifeEvidenceSliceEmpty } from "../heartbeat/runtime-snapshot.js";
2
- import { writeQuietArtifact } from "../../../storage/quiet/quiet-artifact-writer.js";
3
- import { persistQuietArtifactToWorkspace } from "../../../storage/quiet/persist-quiet-artifact.js";
4
- import { buildEvidencePack, buildQuietNarrativeGuidance, selectInterestBasis } from "../../../guidance/evidence-guidance.js";
5
- function toSourceRefFromControlPlane(r) {
6
- return {
7
- id: r.id,
8
- kind: r.kind,
9
- uri: r.uri,
10
- excerptHash: r.excerptHash,
11
- observedAt: r.observedAt,
12
- };
13
- }
14
- function toGuidanceRef(r) {
15
- return {
16
- id: r.id,
17
- kind: r.kind,
18
- uri: r.uri,
19
- excerptHash: r.excerptHash,
20
- observedAt: r.observedAt,
21
- };
22
- }
23
- export async function runSourceBackedQuiet(params) {
24
- const { candidate, runtime, day, userInterestSnapshot, workspaceRoot } = params;
25
- const empty = isLifeEvidenceSliceEmpty(runtime.lifeEvidence);
26
- if (empty) {
27
- const input = {
28
- day,
29
- kind: "empty_state",
30
- title: "Quiet — no life evidence",
31
- body: "No source-backed life evidence in window; narrative reflection is skipped.",
32
- claims: [],
33
- sourceRefs: [],
34
- };
35
- const ack = writeQuietArtifact(input);
36
- let persistedRelativePath;
37
- if (workspaceRoot) {
38
- const p = await persistQuietArtifactToWorkspace(workspaceRoot, ack, input);
39
- persistedRelativePath = p.relativePath;
40
- }
41
- return {
42
- result: {
43
- scope: "rhythm",
44
- status: "intent_selected",
45
- selectedIntentId: candidate.id,
46
- reasons: ["quiet_empty_state", "no_fictional_narrative"],
47
- },
48
- artifactAck: ack,
49
- persistedRelativePath,
50
- };
51
- }
52
- const bundleRefs = runtime.lifeEvidence.evidenceRefs.map(toSourceRefFromControlPlane);
53
- const guidanceRefs = runtime.lifeEvidence.evidenceRefs.map(toGuidanceRef);
54
- const ep = buildEvidencePack(guidanceRefs);
55
- if (!ep.ok) {
56
- return {
57
- result: {
58
- scope: "rhythm",
59
- status: "denied",
60
- selectedIntentId: candidate.id,
61
- reasons: ep.reasons,
62
- },
63
- };
64
- }
65
- const basis = selectInterestBasis({
66
- staleness: userInterestSnapshot?.staleness ?? "insufficient",
67
- confidence: userInterestSnapshot?.confidence ?? 0,
68
- signalCount: userInterestSnapshot?.signals.length ?? 0,
69
- });
70
- const claims = ep.pack.groundedRefs.map((g, i) => ({
71
- id: `fact:${g.id}`,
72
- text: `Evidence-backed note ${i + 1}`,
73
- claimType: "fact",
74
- sourceRefs: [
75
- {
76
- id: g.id,
77
- kind: g.kind,
78
- uri: g.uri,
79
- excerptHash: g.excerptHash,
80
- observedAt: g.observedAt,
81
- },
82
- ],
83
- }));
84
- const reportWrite = {
85
- day,
86
- kind: "daily_report",
87
- title: "Quiet daily report",
88
- body: `Source-backed quiet summary (${bundleRefs.length} refs).`,
89
- claims,
90
- sourceRefs: bundleRefs,
91
- };
92
- const ack = writeQuietArtifact(reportWrite);
93
- const gq = buildQuietNarrativeGuidance({
94
- interestBasis: basis,
95
- sourceCoverage: ack.sourceCoverage,
96
- outline: claims.map((c) => c.text),
97
- });
98
- if (gq.status === "unavailable") {
99
- return {
100
- result: {
101
- scope: "rhythm",
102
- status: "denied",
103
- selectedIntentId: candidate.id,
104
- reasons: gq.reasons,
105
- },
106
- };
107
- }
108
- let persistedRelativePath;
109
- if (workspaceRoot) {
110
- const p = await persistQuietArtifactToWorkspace(workspaceRoot, ack, reportWrite);
111
- persistedRelativePath = p.relativePath;
112
- }
113
- return {
114
- result: {
115
- scope: "rhythm",
116
- status: "intent_selected",
117
- selectedIntentId: candidate.id,
118
- reasons: ["quiet_artifact_written", ...gq.hints.slice(0, 2)],
119
- },
120
- artifactAck: ack,
121
- persistedRelativePath,
122
- };
123
- }
1
+ import { isLifeEvidenceSliceEmpty } from "../heartbeat/runtime-snapshot.js";
2
+ import { writeQuietArtifact } from "../../../storage/quiet/quiet-artifact-writer.js";
3
+ import { persistQuietArtifactToWorkspace } from "../../../storage/quiet/persist-quiet-artifact.js";
4
+ import { buildEvidencePack, buildQuietNarrativeGuidance, selectInterestBasis } from "../../../guidance/evidence-guidance.js";
5
+ function toSourceRefFromControlPlane(r) {
6
+ return {
7
+ id: r.id,
8
+ kind: r.kind,
9
+ uri: r.uri,
10
+ excerptHash: r.excerptHash,
11
+ observedAt: r.observedAt,
12
+ };
13
+ }
14
+ function toGuidanceRef(r) {
15
+ return {
16
+ id: r.id,
17
+ kind: r.kind,
18
+ uri: r.uri,
19
+ excerptHash: r.excerptHash,
20
+ observedAt: r.observedAt,
21
+ };
22
+ }
23
+ export async function runSourceBackedQuiet(params) {
24
+ const { candidate, runtime, day, userInterestSnapshot, workspaceRoot } = params;
25
+ const empty = isLifeEvidenceSliceEmpty(runtime.lifeEvidence);
26
+ if (empty) {
27
+ const input = {
28
+ day,
29
+ kind: "empty_state",
30
+ title: "Quiet — no life evidence",
31
+ body: "No source-backed life evidence in window; narrative reflection is skipped.",
32
+ claims: [],
33
+ sourceRefs: [],
34
+ };
35
+ const ack = writeQuietArtifact(input);
36
+ let persistedRelativePath;
37
+ if (workspaceRoot) {
38
+ const p = await persistQuietArtifactToWorkspace(workspaceRoot, ack, input);
39
+ persistedRelativePath = p.relativePath;
40
+ }
41
+ return {
42
+ result: {
43
+ scope: "rhythm",
44
+ status: "intent_selected",
45
+ selectedIntentId: candidate.id,
46
+ reasons: ["quiet_empty_state", "no_fictional_narrative"],
47
+ },
48
+ artifactAck: ack,
49
+ persistedRelativePath,
50
+ };
51
+ }
52
+ const bundleRefs = runtime.lifeEvidence.evidenceRefs.map(toSourceRefFromControlPlane);
53
+ const guidanceRefs = runtime.lifeEvidence.evidenceRefs.map(toGuidanceRef);
54
+ const ep = buildEvidencePack(guidanceRefs);
55
+ if (!ep.ok) {
56
+ return {
57
+ result: {
58
+ scope: "rhythm",
59
+ status: "denied",
60
+ selectedIntentId: candidate.id,
61
+ reasons: ep.reasons,
62
+ },
63
+ };
64
+ }
65
+ const basis = selectInterestBasis({
66
+ staleness: userInterestSnapshot?.staleness ?? "insufficient",
67
+ confidence: userInterestSnapshot?.confidence ?? 0,
68
+ signalCount: userInterestSnapshot?.signals.length ?? 0,
69
+ });
70
+ const claims = ep.pack.groundedRefs.map((g, i) => ({
71
+ id: `fact:${g.id}`,
72
+ text: `Evidence-backed note ${i + 1}`,
73
+ claimType: "fact",
74
+ sourceRefs: [
75
+ {
76
+ id: g.id,
77
+ kind: g.kind,
78
+ uri: g.uri,
79
+ excerptHash: g.excerptHash,
80
+ observedAt: g.observedAt,
81
+ },
82
+ ],
83
+ }));
84
+ const reportWrite = {
85
+ day,
86
+ kind: "daily_report",
87
+ title: "Quiet daily report",
88
+ body: `Source-backed quiet summary (${bundleRefs.length} refs).`,
89
+ claims,
90
+ sourceRefs: bundleRefs,
91
+ };
92
+ const ack = writeQuietArtifact(reportWrite);
93
+ const gq = buildQuietNarrativeGuidance({
94
+ interestBasis: basis,
95
+ sourceCoverage: ack.sourceCoverage,
96
+ outline: claims.map((c) => c.text),
97
+ });
98
+ if (gq.status === "unavailable") {
99
+ return {
100
+ result: {
101
+ scope: "rhythm",
102
+ status: "denied",
103
+ selectedIntentId: candidate.id,
104
+ reasons: gq.reasons,
105
+ },
106
+ };
107
+ }
108
+ let persistedRelativePath;
109
+ if (workspaceRoot) {
110
+ const p = await persistQuietArtifactToWorkspace(workspaceRoot, ack, reportWrite);
111
+ persistedRelativePath = p.relativePath;
112
+ }
113
+ return {
114
+ result: {
115
+ scope: "rhythm",
116
+ status: "intent_selected",
117
+ selectedIntentId: candidate.id,
118
+ reasons: ["quiet_artifact_written", ...gq.hints.slice(0, 2)],
119
+ },
120
+ artifactAck: ack,
121
+ persistedRelativePath,
122
+ };
123
+ }
@@ -1,15 +1,15 @@
1
- /**
2
- * Maps calendar rhythm policy + continuity into planner-facing window slice (T2.1.3).
3
- * Control-plane owns allowedIntentKinds; state never emits them (T2.1.2 boundary).
4
- */
5
- import type { ContinuitySnapshot, IntentKind } from "../types.js";
6
- import type { RhythmPolicy } from "./rhythm-policy.js";
7
- export interface PlannerRhythmWindowSlice {
8
- windowId: string;
9
- allowedIntentKinds: IntentKind[];
10
- quietBias: boolean;
11
- }
12
- /**
13
- * Derive allowed intent kinds and quiet bias for candidate planning.
14
- */
15
- export declare function buildPlannerRhythmWindow(now: string, continuity: ContinuitySnapshot, policy: RhythmPolicy): PlannerRhythmWindowSlice;
1
+ /**
2
+ * Maps calendar rhythm policy + continuity into planner-facing window slice (T2.1.3).
3
+ * Control-plane owns allowedIntentKinds; state never emits them (T2.1.2 boundary).
4
+ */
5
+ import type { ContinuitySnapshot, IntentKind } from "../types.js";
6
+ import type { RhythmPolicy } from "./rhythm-policy.js";
7
+ export interface PlannerRhythmWindowSlice {
8
+ windowId: string;
9
+ allowedIntentKinds: IntentKind[];
10
+ quietBias: boolean;
11
+ }
12
+ /**
13
+ * Derive allowed intent kinds and quiet bias for candidate planning.
14
+ */
15
+ export declare function buildPlannerRhythmWindow(now: string, continuity: ContinuitySnapshot, policy: RhythmPolicy): PlannerRhythmWindowSlice;