@haaaiawd/second-nature 0.1.8 → 0.1.9

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 (183) hide show
  1. package/index.js +73 -1
  2. package/openclaw.plugin.json +1 -1
  3. package/package.json +1 -1
  4. package/runtime/cli/commands/index.d.ts +2 -0
  5. package/runtime/cli/commands/index.js +61 -6
  6. package/runtime/cli/explain/explain-surface-subject.d.ts +8 -0
  7. package/runtime/cli/explain/explain-surface-subject.js +9 -0
  8. package/runtime/cli/explain/format-explanation.d.ts +2 -0
  9. package/runtime/cli/explain/format-explanation.js +2 -0
  10. package/runtime/cli/explain/resolve-subject.js +15 -0
  11. package/runtime/cli/host-capability/classify-delivery.d.ts +14 -0
  12. package/runtime/cli/host-capability/classify-delivery.js +20 -0
  13. package/runtime/cli/host-capability/probe-host-capability.d.ts +2 -0
  14. package/runtime/cli/host-capability/probe-host-capability.js +58 -0
  15. package/runtime/cli/host-capability/record-host-capability.d.ts +6 -0
  16. package/runtime/cli/host-capability/record-host-capability.js +14 -0
  17. package/runtime/cli/host-capability/types.d.ts +71 -0
  18. package/runtime/cli/host-capability/types.js +6 -0
  19. package/runtime/cli/host-smoke/run-host-smoke.d.ts +2 -0
  20. package/runtime/cli/host-smoke/run-host-smoke.js +40 -0
  21. package/runtime/cli/host-smoke/types.d.ts +35 -0
  22. package/runtime/cli/host-smoke/types.js +6 -0
  23. package/runtime/cli/index.js +18 -0
  24. package/runtime/cli/ops/heartbeat-surface.d.ts +35 -0
  25. package/runtime/cli/ops/heartbeat-surface.js +71 -0
  26. package/runtime/cli/ops/ops-router.d.ts +16 -0
  27. package/runtime/cli/ops/ops-router.js +83 -0
  28. package/runtime/cli/ops/show-operator-fallback.d.ts +13 -0
  29. package/runtime/cli/ops/show-operator-fallback.js +22 -0
  30. package/runtime/cli/ops/workspace-heartbeat-runner.d.ts +10 -0
  31. package/runtime/cli/ops/workspace-heartbeat-runner.js +26 -0
  32. package/runtime/cli/read-models/index.d.ts +11 -2
  33. package/runtime/cli/read-models/index.js +50 -0
  34. package/runtime/cli/read-models/operator-explain-map.d.ts +6 -0
  35. package/runtime/cli/read-models/operator-explain-map.js +10 -0
  36. package/runtime/cli/read-models/types.d.ts +5 -1
  37. package/runtime/cli/runtime/runtime-artifact-boundary.d.ts +28 -0
  38. package/runtime/cli/runtime/runtime-artifact-boundary.js +94 -0
  39. package/runtime/connectors/base/contract.d.ts +6 -0
  40. package/runtime/connectors/base/execution-policy.d.ts +47 -0
  41. package/runtime/connectors/base/execution-policy.js +82 -0
  42. package/runtime/connectors/base/index.d.ts +2 -0
  43. package/runtime/connectors/base/index.js +2 -0
  44. package/runtime/connectors/base/manifest.d.ts +55 -2
  45. package/runtime/connectors/base/manifest.js +50 -0
  46. package/runtime/connectors/base/map-life-evidence.d.ts +16 -0
  47. package/runtime/connectors/base/map-life-evidence.js +79 -0
  48. package/runtime/connectors/base/policy-layer.d.ts +2 -0
  49. package/runtime/connectors/base/policy-layer.js +16 -0
  50. package/runtime/connectors/base/route-planner.js +1 -0
  51. package/runtime/connectors/index.d.ts +1 -0
  52. package/runtime/connectors/index.js +1 -0
  53. package/runtime/connectors/near-real/near-real-connector-smoke.d.ts +19 -0
  54. package/runtime/connectors/near-real/near-real-connector-smoke.js +152 -0
  55. package/runtime/core/second-nature/heartbeat/heartbeat-executor.js +2 -0
  56. package/runtime/core/second-nature/heartbeat/heartbeat-loop.d.ts +37 -16
  57. package/runtime/core/second-nature/heartbeat/heartbeat-loop.js +95 -29
  58. package/runtime/core/second-nature/heartbeat/index.d.ts +4 -1
  59. package/runtime/core/second-nature/heartbeat/index.js +4 -1
  60. package/runtime/core/second-nature/heartbeat/run-heartbeat-cycle.d.ts +21 -0
  61. package/runtime/core/second-nature/heartbeat/run-heartbeat-cycle.js +35 -0
  62. package/runtime/core/second-nature/heartbeat/runtime-snapshot.d.ts +28 -0
  63. package/runtime/core/second-nature/heartbeat/runtime-snapshot.js +35 -0
  64. package/runtime/core/second-nature/heartbeat/signal.d.ts +9 -2
  65. package/runtime/core/second-nature/heartbeat/snapshot-builder.d.ts +19 -1
  66. package/runtime/core/second-nature/index.d.ts +8 -0
  67. package/runtime/core/second-nature/index.js +8 -0
  68. package/runtime/core/second-nature/orchestrator/effect-dispatcher.d.ts +1 -1
  69. package/runtime/core/second-nature/orchestrator/effect-dispatcher.js +9 -4
  70. package/runtime/core/second-nature/orchestrator/guard-layer.d.ts +6 -0
  71. package/runtime/core/second-nature/orchestrator/guard-layer.js +76 -20
  72. package/runtime/core/second-nature/orchestrator/intent-planner.d.ts +10 -0
  73. package/runtime/core/second-nature/orchestrator/intent-planner.js +135 -28
  74. package/runtime/core/second-nature/orchestrator/lease-manager.d.ts +1 -1
  75. package/runtime/core/second-nature/orchestrator/lease-manager.js +1 -1
  76. package/runtime/core/second-nature/outreach/build-outreach-draft-request.d.ts +6 -0
  77. package/runtime/core/second-nature/outreach/build-outreach-draft-request.js +63 -0
  78. package/runtime/core/second-nature/outreach/delivery-target.d.ts +26 -0
  79. package/runtime/core/second-nature/outreach/delivery-target.js +70 -0
  80. package/runtime/core/second-nature/outreach/dispatch-user-outreach.d.ts +38 -0
  81. package/runtime/core/second-nature/outreach/dispatch-user-outreach.js +119 -0
  82. package/runtime/core/second-nature/outreach/judge-input-from-snapshot.d.ts +7 -0
  83. package/runtime/core/second-nature/outreach/judge-input-from-snapshot.js +45 -0
  84. package/runtime/core/second-nature/outreach/judge-outreach.d.ts +40 -0
  85. package/runtime/core/second-nature/outreach/judge-outreach.js +121 -0
  86. package/runtime/core/second-nature/quiet/run-source-backed-quiet.d.ts +21 -0
  87. package/runtime/core/second-nature/quiet/run-source-backed-quiet.js +123 -0
  88. package/runtime/core/second-nature/rhythm/planner-rhythm-window.d.ts +15 -0
  89. package/runtime/core/second-nature/rhythm/planner-rhythm-window.js +52 -0
  90. package/runtime/core/second-nature/rhythm/policy-bridge.d.ts +19 -0
  91. package/runtime/core/second-nature/rhythm/policy-bridge.js +34 -0
  92. package/runtime/core/second-nature/types.d.ts +16 -2
  93. package/runtime/guidance/draft-outreach-message.d.ts +7 -0
  94. package/runtime/guidance/draft-outreach-message.js +42 -0
  95. package/runtime/guidance/evidence-guidance.d.ts +40 -0
  96. package/runtime/guidance/evidence-guidance.js +52 -0
  97. package/runtime/guidance/index.d.ts +3 -0
  98. package/runtime/guidance/index.js +3 -0
  99. package/runtime/guidance/outreach-draft-schema.d.ts +228 -0
  100. package/runtime/guidance/outreach-draft-schema.js +80 -0
  101. package/runtime/observability/audit/append-only-audit-store.d.ts +14 -0
  102. package/runtime/observability/audit/append-only-audit-store.js +21 -0
  103. package/runtime/observability/audit/audit-envelope.d.ts +51 -0
  104. package/runtime/observability/audit/audit-envelope.js +130 -0
  105. package/runtime/observability/audit/verify-audit-hash-chain.d.ts +23 -0
  106. package/runtime/observability/audit/verify-audit-hash-chain.js +83 -0
  107. package/runtime/observability/db/index.js +11 -0
  108. package/runtime/observability/db/schema/host-capability-reports.d.ts +180 -0
  109. package/runtime/observability/db/schema/host-capability-reports.js +12 -0
  110. package/runtime/observability/db/schema/index.d.ts +1 -0
  111. package/runtime/observability/db/schema/index.js +1 -0
  112. package/runtime/observability/index.d.ts +7 -0
  113. package/runtime/observability/index.js +7 -0
  114. package/runtime/observability/query/explain-query.d.ts +48 -0
  115. package/runtime/observability/query/explain-query.js +114 -0
  116. package/runtime/observability/query/export-audit-bundle.d.ts +22 -0
  117. package/runtime/observability/query/export-audit-bundle.js +27 -0
  118. package/runtime/observability/services/decision-ledger.d.ts +1 -1
  119. package/runtime/observability/services/decision-ledger.js +4 -0
  120. package/runtime/observability/services/governance-audit.d.ts +14 -0
  121. package/runtime/observability/services/governance-audit.js +25 -1
  122. package/runtime/observability/services/governance-plane-recorder.d.ts +47 -0
  123. package/runtime/observability/services/governance-plane-recorder.js +55 -0
  124. package/runtime/observability/services/lived-experience-audit.d.ts +97 -0
  125. package/runtime/observability/services/lived-experience-audit.js +161 -0
  126. package/runtime/storage/bootstrap/native-sqlite-probe.d.ts +7 -0
  127. package/runtime/storage/bootstrap/native-sqlite-probe.js +28 -0
  128. package/runtime/storage/bootstrap/repair-gate.d.ts +17 -0
  129. package/runtime/storage/bootstrap/repair-gate.js +71 -0
  130. package/runtime/storage/bootstrap/storage-mode-smoke.d.ts +38 -0
  131. package/runtime/storage/bootstrap/storage-mode-smoke.js +85 -0
  132. package/runtime/storage/db/index.js +49 -0
  133. package/runtime/storage/db/schema/delivery-attempts.d.ts +199 -0
  134. package/runtime/storage/db/schema/delivery-attempts.js +13 -0
  135. package/runtime/storage/db/schema/index.d.ts +3 -0
  136. package/runtime/storage/db/schema/index.js +3 -0
  137. package/runtime/storage/db/schema/life-evidence-index.d.ts +161 -0
  138. package/runtime/storage/db/schema/life-evidence-index.js +11 -0
  139. package/runtime/storage/db/schema/operator-fallback-artifacts.d.ts +161 -0
  140. package/runtime/storage/db/schema/operator-fallback-artifacts.js +11 -0
  141. package/runtime/storage/db/schema/policies.d.ts +17 -0
  142. package/runtime/storage/db/schema/policies.js +1 -0
  143. package/runtime/storage/delivery/query-delivery-attempts.d.ts +3 -0
  144. package/runtime/storage/delivery/query-delivery-attempts.js +32 -0
  145. package/runtime/storage/delivery/types.d.ts +27 -0
  146. package/runtime/storage/delivery/types.js +1 -0
  147. package/runtime/storage/delivery/write-delivery-attempt.d.ts +6 -0
  148. package/runtime/storage/delivery/write-delivery-attempt.js +36 -0
  149. package/runtime/storage/fallback/load-operator-fallback.d.ts +14 -0
  150. package/runtime/storage/fallback/load-operator-fallback.js +47 -0
  151. package/runtime/storage/fallback/operator-fallback-types.d.ts +9 -0
  152. package/runtime/storage/fallback/operator-fallback-types.js +1 -0
  153. package/runtime/storage/fallback/operator-fallback-view.d.ts +11 -0
  154. package/runtime/storage/fallback/operator-fallback-view.js +1 -0
  155. package/runtime/storage/fallback/write-operator-fallback.d.ts +6 -0
  156. package/runtime/storage/fallback/write-operator-fallback.js +21 -0
  157. package/runtime/storage/index.d.ts +21 -0
  158. package/runtime/storage/index.js +14 -0
  159. package/runtime/storage/life-evidence/append-life-evidence.d.ts +7 -0
  160. package/runtime/storage/life-evidence/append-life-evidence.js +64 -0
  161. package/runtime/storage/life-evidence/types.d.ts +45 -0
  162. package/runtime/storage/life-evidence/types.js +6 -0
  163. package/runtime/storage/quiet/persist-quiet-artifact.d.ts +7 -0
  164. package/runtime/storage/quiet/persist-quiet-artifact.js +22 -0
  165. package/runtime/storage/quiet/quiet-artifact-types.d.ts +18 -0
  166. package/runtime/storage/quiet/quiet-artifact-types.js +1 -0
  167. package/runtime/storage/quiet/quiet-artifact-writer.d.ts +15 -0
  168. package/runtime/storage/quiet/quiet-artifact-writer.js +56 -0
  169. package/runtime/storage/rhythm/rhythm-policy-snapshot.d.ts +10 -0
  170. package/runtime/storage/rhythm/rhythm-policy-snapshot.js +34 -0
  171. package/runtime/storage/services/credential-vault.d.ts +5 -0
  172. package/runtime/storage/services/credential-vault.js +46 -9
  173. package/runtime/storage/snapshots/continuity-snapshot.d.ts +9 -0
  174. package/runtime/storage/snapshots/continuity-snapshot.js +41 -0
  175. package/runtime/storage/snapshots/life-evidence-snapshot.d.ts +6 -0
  176. package/runtime/storage/snapshots/life-evidence-snapshot.js +114 -0
  177. package/runtime/storage/snapshots/types.d.ts +58 -0
  178. package/runtime/storage/snapshots/types.js +1 -0
  179. package/runtime/storage/state-api.js +11 -4
  180. package/runtime/storage/user-interest/load-user-interest-snapshot.d.ts +2 -0
  181. package/runtime/storage/user-interest/load-user-interest-snapshot.js +150 -0
  182. package/runtime/storage/user-interest/types.d.ts +25 -0
  183. package/runtime/storage/user-interest/types.js +1 -0
@@ -0,0 +1,228 @@
1
+ /**
2
+ * Outreach draft request contracts + zod validation (T6.1.1 / behavioral-guidance-system v5).
3
+ *
4
+ * Core logic: strict schema for control-plane → guidance handoff; GuidanceDraftPort documents async seam.
5
+ * Test coverage: tests/unit/guidance/outreach-draft-schema.test.ts
6
+ */
7
+ import { z } from "zod";
8
+ export declare const guidanceSourceRefSchema: z.ZodObject<{
9
+ id: z.ZodString;
10
+ kind: z.ZodEnum<{
11
+ platform_item: "platform_item";
12
+ workspace_artifact: "workspace_artifact";
13
+ decision_record: "decision_record";
14
+ user_anchor: "user_anchor";
15
+ connector_result: "connector_result";
16
+ host_report: "host_report";
17
+ fallback_artifact: "fallback_artifact";
18
+ }>;
19
+ uri: z.ZodString;
20
+ excerptHash: z.ZodOptional<z.ZodString>;
21
+ observedAt: z.ZodOptional<z.ZodString>;
22
+ }, z.core.$strip>;
23
+ export type GuidanceSourceRef = z.infer<typeof guidanceSourceRefSchema>;
24
+ export declare const deliveryExpressionContextSchema: z.ZodObject<{
25
+ deliveryVerdict: z.ZodEnum<{
26
+ target_none: "target_none";
27
+ channel_missing: "channel_missing";
28
+ host_unsupported: "host_unsupported";
29
+ delivery_failed: "delivery_failed";
30
+ target_available: "target_available";
31
+ }>;
32
+ fallbackRef: z.ZodOptional<z.ZodString>;
33
+ wordingMode: z.ZodEnum<{
34
+ sendable: "sendable";
35
+ not_sent_fallback_candidate: "not_sent_fallback_candidate";
36
+ }>;
37
+ }, z.core.$strip>;
38
+ export declare const sceneGuidanceRequestSchema: z.ZodObject<{
39
+ requestId: z.ZodString;
40
+ sceneType: z.ZodEnum<{
41
+ outreach: "outreach";
42
+ explain: "explain";
43
+ social: "social";
44
+ quiet_reflection: "quiet_reflection";
45
+ user_reply_continuity: "user_reply_continuity";
46
+ fallback_candidate: "fallback_candidate";
47
+ }>;
48
+ runtimeScope: z.ZodEnum<{
49
+ rhythm: "rhythm";
50
+ user_reply: "user_reply";
51
+ user_task: "user_task";
52
+ }>;
53
+ rhythmWindowKind: z.ZodOptional<z.ZodEnum<{
54
+ quiet: "quiet";
55
+ social: "social";
56
+ work: "work";
57
+ exploration: "exploration";
58
+ reflection: "reflection";
59
+ maintenance: "maintenance";
60
+ }>>;
61
+ riskLevel: z.ZodEnum<{
62
+ low: "low";
63
+ medium: "medium";
64
+ high: "high";
65
+ }>;
66
+ sourceRefs: z.ZodArray<z.ZodObject<{
67
+ id: z.ZodString;
68
+ kind: z.ZodEnum<{
69
+ platform_item: "platform_item";
70
+ workspace_artifact: "workspace_artifact";
71
+ decision_record: "decision_record";
72
+ user_anchor: "user_anchor";
73
+ connector_result: "connector_result";
74
+ host_report: "host_report";
75
+ fallback_artifact: "fallback_artifact";
76
+ }>;
77
+ uri: z.ZodString;
78
+ excerptHash: z.ZodOptional<z.ZodString>;
79
+ observedAt: z.ZodOptional<z.ZodString>;
80
+ }, z.core.$strip>>;
81
+ deliveryContext: z.ZodOptional<z.ZodObject<{
82
+ deliveryVerdict: z.ZodEnum<{
83
+ target_none: "target_none";
84
+ channel_missing: "channel_missing";
85
+ host_unsupported: "host_unsupported";
86
+ delivery_failed: "delivery_failed";
87
+ target_available: "target_available";
88
+ }>;
89
+ fallbackRef: z.ZodOptional<z.ZodString>;
90
+ wordingMode: z.ZodEnum<{
91
+ sendable: "sendable";
92
+ not_sent_fallback_candidate: "not_sent_fallback_candidate";
93
+ }>;
94
+ }, z.core.$strip>>;
95
+ language: z.ZodOptional<z.ZodEnum<{
96
+ "en-US": "en-US";
97
+ "zh-CN": "zh-CN";
98
+ }>>;
99
+ }, z.core.$strip>;
100
+ export declare const outreachDraftRequestSchema: z.ZodObject<{
101
+ requestId: z.ZodString;
102
+ runtimeScope: z.ZodEnum<{
103
+ rhythm: "rhythm";
104
+ user_reply: "user_reply";
105
+ user_task: "user_task";
106
+ }>;
107
+ rhythmWindowKind: z.ZodOptional<z.ZodEnum<{
108
+ quiet: "quiet";
109
+ social: "social";
110
+ work: "work";
111
+ exploration: "exploration";
112
+ reflection: "reflection";
113
+ maintenance: "maintenance";
114
+ }>>;
115
+ riskLevel: z.ZodEnum<{
116
+ low: "low";
117
+ medium: "medium";
118
+ high: "high";
119
+ }>;
120
+ sourceRefs: z.ZodArray<z.ZodObject<{
121
+ id: z.ZodString;
122
+ kind: z.ZodEnum<{
123
+ platform_item: "platform_item";
124
+ workspace_artifact: "workspace_artifact";
125
+ decision_record: "decision_record";
126
+ user_anchor: "user_anchor";
127
+ connector_result: "connector_result";
128
+ host_report: "host_report";
129
+ fallback_artifact: "fallback_artifact";
130
+ }>;
131
+ uri: z.ZodString;
132
+ excerptHash: z.ZodOptional<z.ZodString>;
133
+ observedAt: z.ZodOptional<z.ZodString>;
134
+ }, z.core.$strip>>;
135
+ deliveryContext: z.ZodOptional<z.ZodObject<{
136
+ deliveryVerdict: z.ZodEnum<{
137
+ target_none: "target_none";
138
+ channel_missing: "channel_missing";
139
+ host_unsupported: "host_unsupported";
140
+ delivery_failed: "delivery_failed";
141
+ target_available: "target_available";
142
+ }>;
143
+ fallbackRef: z.ZodOptional<z.ZodString>;
144
+ wordingMode: z.ZodEnum<{
145
+ sendable: "sendable";
146
+ not_sent_fallback_candidate: "not_sent_fallback_candidate";
147
+ }>;
148
+ }, z.core.$strip>>;
149
+ language: z.ZodOptional<z.ZodEnum<{
150
+ "en-US": "en-US";
151
+ "zh-CN": "zh-CN";
152
+ }>>;
153
+ sceneType: z.ZodEnum<{
154
+ outreach: "outreach";
155
+ fallback_candidate: "fallback_candidate";
156
+ }>;
157
+ decisionId: z.ZodString;
158
+ candidateId: z.ZodString;
159
+ judgmentVerdict: z.ZodEnum<{
160
+ allow: "allow";
161
+ deny: "deny";
162
+ defer: "defer";
163
+ }>;
164
+ valueScore: z.ZodNumber;
165
+ interestRefs: z.ZodArray<z.ZodObject<{
166
+ id: z.ZodString;
167
+ kind: z.ZodEnum<{
168
+ platform_item: "platform_item";
169
+ workspace_artifact: "workspace_artifact";
170
+ decision_record: "decision_record";
171
+ user_anchor: "user_anchor";
172
+ connector_result: "connector_result";
173
+ host_report: "host_report";
174
+ fallback_artifact: "fallback_artifact";
175
+ }>;
176
+ uri: z.ZodString;
177
+ excerptHash: z.ZodOptional<z.ZodString>;
178
+ observedAt: z.ZodOptional<z.ZodString>;
179
+ }, z.core.$strip>>;
180
+ }, z.core.$strip>;
181
+ export type SceneGuidanceRequest = z.infer<typeof sceneGuidanceRequestSchema>;
182
+ export type OutreachDraftRequest = z.infer<typeof outreachDraftRequestSchema>;
183
+ export type DeliveryExpressionContext = z.infer<typeof deliveryExpressionContextSchema>;
184
+ export declare function parseOutreachDraftRequest(input: unknown): OutreachDraftRequest;
185
+ export declare function safeParseOutreachDraftRequest(input: unknown): z.ZodSafeParseResult<{
186
+ requestId: string;
187
+ runtimeScope: "rhythm" | "user_reply" | "user_task";
188
+ riskLevel: "low" | "medium" | "high";
189
+ sourceRefs: {
190
+ id: string;
191
+ kind: "platform_item" | "workspace_artifact" | "decision_record" | "user_anchor" | "connector_result" | "host_report" | "fallback_artifact";
192
+ uri: string;
193
+ excerptHash?: string | undefined;
194
+ observedAt?: string | undefined;
195
+ }[];
196
+ sceneType: "outreach" | "fallback_candidate";
197
+ decisionId: string;
198
+ candidateId: string;
199
+ judgmentVerdict: "allow" | "deny" | "defer";
200
+ valueScore: number;
201
+ interestRefs: {
202
+ id: string;
203
+ kind: "platform_item" | "workspace_artifact" | "decision_record" | "user_anchor" | "connector_result" | "host_report" | "fallback_artifact";
204
+ uri: string;
205
+ excerptHash?: string | undefined;
206
+ observedAt?: string | undefined;
207
+ }[];
208
+ rhythmWindowKind?: "quiet" | "social" | "work" | "exploration" | "reflection" | "maintenance" | undefined;
209
+ deliveryContext?: {
210
+ deliveryVerdict: "target_none" | "channel_missing" | "host_unsupported" | "delivery_failed" | "target_available";
211
+ wordingMode: "sendable" | "not_sent_fallback_candidate";
212
+ fallbackRef?: string | undefined;
213
+ } | undefined;
214
+ language?: "en-US" | "zh-CN" | undefined;
215
+ }>;
216
+ /** Async seam for generative outreach copy (implementation lives outside control-plane). */
217
+ export interface GuidanceDraftPort {
218
+ draftOutreachMessage(request: OutreachDraftRequest): Promise<{
219
+ status: "ready";
220
+ draft: {
221
+ text: string;
222
+ deliveryWording: DeliveryExpressionContext["wordingMode"];
223
+ };
224
+ } | {
225
+ status: "unavailable";
226
+ reasons: string[];
227
+ }>;
228
+ }
@@ -0,0 +1,80 @@
1
+ /**
2
+ * Outreach draft request contracts + zod validation (T6.1.1 / behavioral-guidance-system v5).
3
+ *
4
+ * Core logic: strict schema for control-plane → guidance handoff; GuidanceDraftPort documents async seam.
5
+ * Test coverage: tests/unit/guidance/outreach-draft-schema.test.ts
6
+ */
7
+ import { z } from "zod";
8
+ const sourceRefKindSchema = z.enum([
9
+ "platform_item",
10
+ "workspace_artifact",
11
+ "decision_record",
12
+ "user_anchor",
13
+ "connector_result",
14
+ "host_report",
15
+ "fallback_artifact",
16
+ ]);
17
+ export const guidanceSourceRefSchema = z.object({
18
+ id: z.string().min(1),
19
+ kind: sourceRefKindSchema,
20
+ uri: z.string().min(1),
21
+ excerptHash: z.string().optional(),
22
+ observedAt: z.string().optional(),
23
+ });
24
+ export const deliveryExpressionContextSchema = z.object({
25
+ deliveryVerdict: z.enum([
26
+ "target_available",
27
+ "target_none",
28
+ "channel_missing",
29
+ "host_unsupported",
30
+ "delivery_failed",
31
+ ]),
32
+ fallbackRef: z.string().optional(),
33
+ wordingMode: z.enum(["sendable", "not_sent_fallback_candidate"]),
34
+ });
35
+ const guidanceSceneTypeSchema = z.enum([
36
+ "outreach",
37
+ "quiet_reflection",
38
+ "social",
39
+ "explain",
40
+ "user_reply_continuity",
41
+ "fallback_candidate",
42
+ ]);
43
+ const runtimeScopeSchema = z.enum(["rhythm", "user_task", "user_reply"]);
44
+ const riskLevelSchema = z.enum(["low", "medium", "high"]);
45
+ export const sceneGuidanceRequestSchema = z.object({
46
+ requestId: z.string().min(1),
47
+ sceneType: guidanceSceneTypeSchema,
48
+ runtimeScope: runtimeScopeSchema,
49
+ rhythmWindowKind: z
50
+ .enum(["work", "exploration", "social", "quiet", "reflection", "maintenance"])
51
+ .optional(),
52
+ riskLevel: riskLevelSchema,
53
+ sourceRefs: z.array(guidanceSourceRefSchema),
54
+ deliveryContext: deliveryExpressionContextSchema.optional(),
55
+ language: z.enum(["zh-CN", "en-US"]).optional(),
56
+ });
57
+ export const outreachDraftRequestSchema = sceneGuidanceRequestSchema
58
+ .extend({
59
+ sceneType: z.enum(["outreach", "fallback_candidate"]),
60
+ decisionId: z.string().min(1),
61
+ candidateId: z.string().min(1),
62
+ judgmentVerdict: z.enum(["allow", "deny", "defer"]),
63
+ valueScore: z.number(),
64
+ interestRefs: z.array(guidanceSourceRefSchema),
65
+ })
66
+ .superRefine((val, ctx) => {
67
+ if (!val.deliveryContext) {
68
+ ctx.addIssue({
69
+ code: "custom",
70
+ message: "outreach_draft_requires_delivery_context",
71
+ path: ["deliveryContext"],
72
+ });
73
+ }
74
+ });
75
+ export function parseOutreachDraftRequest(input) {
76
+ return outreachDraftRequestSchema.parse(input);
77
+ }
78
+ export function safeParseOutreachDraftRequest(input) {
79
+ return outreachDraftRequestSchema.safeParse(input);
80
+ }
@@ -0,0 +1,14 @@
1
+ /**
2
+ * In-memory append-only audit store with hash-chain verification hooks.
3
+ *
4
+ * Core logic: reject broken previousHash links; expose ordered envelopes for tests / local tooling.
5
+ *
6
+ * Test coverage: tests/unit/observability/audit-envelope.test.ts
7
+ */
8
+ import type { AuditEnvelope } from "./audit-envelope.js";
9
+ export declare class AppendOnlyAuditStore {
10
+ private readonly events;
11
+ append<T>(envelope: AuditEnvelope<T>): void;
12
+ list(): readonly AuditEnvelope<unknown>[];
13
+ lastRecordHash(): string | undefined;
14
+ }
@@ -0,0 +1,21 @@
1
+ export class AppendOnlyAuditStore {
2
+ events = [];
3
+ append(envelope) {
4
+ const last = this.events[this.events.length - 1];
5
+ if (last) {
6
+ if (envelope.integrity.previousHash !== last.integrity.recordHash) {
7
+ throw new Error("audit_previous_hash_mismatch");
8
+ }
9
+ }
10
+ else if (envelope.integrity.previousHash !== undefined) {
11
+ throw new Error("audit_genesis_previous_hash");
12
+ }
13
+ this.events.push(envelope);
14
+ }
15
+ list() {
16
+ return this.events;
17
+ }
18
+ lastRecordHash() {
19
+ return this.events[this.events.length - 1]?.integrity.recordHash;
20
+ }
21
+ }
@@ -0,0 +1,51 @@
1
+ import { type RedactionManifest as FieldRedactionManifest } from "../redaction/manifest.js";
2
+ export type AuditPlane = "decision" | "delivery" | "source_coverage" | "governance" | "telemetry";
3
+ export type AuditEventFamily = "heartbeat.decision" | "delivery" | "source_coverage" | "guidance.grounding" | "host_capability" | "connector.attempt" | "state.governance";
4
+ export type AuditEnvelopeSensitivity = "public" | "internal" | "private" | "credential" | "sensitive";
5
+ export interface AuditRedactionManifest {
6
+ manifestId: string;
7
+ maskedPaths: string[];
8
+ erasedPaths: string[];
9
+ hashedPaths: string[];
10
+ contentRefPaths: string[];
11
+ sensitivity: AuditEnvelopeSensitivity;
12
+ }
13
+ export interface AuditIntegrity {
14
+ previousHash?: string;
15
+ recordHash: string;
16
+ schemaVersion: "observability.v5";
17
+ }
18
+ export interface AuditEnvelope<TPayload> {
19
+ eventId: string;
20
+ family: AuditEventFamily;
21
+ plane: AuditPlane;
22
+ traceId: string;
23
+ sequence: number;
24
+ createdAt: string;
25
+ payload: TPayload;
26
+ redaction: AuditRedactionManifest;
27
+ integrity: AuditIntegrity;
28
+ }
29
+ export interface RedactAuditEventResult<TPayload> {
30
+ payload: TPayload;
31
+ redaction: AuditRedactionManifest;
32
+ }
33
+ /**
34
+ * Apply field redaction rules and lift manifests to audit path vocabulary (observability-system.detail §2).
35
+ */
36
+ export declare function redactAuditEvent<TPayload extends object>(payload: TPayload): RedactAuditEventResult<TPayload>;
37
+ export interface BuildAuditEnvelopeInput<TPayload extends object> {
38
+ family: AuditEventFamily;
39
+ plane: AuditPlane;
40
+ traceId: string;
41
+ sequence: number;
42
+ payload: TPayload;
43
+ previousHash?: string;
44
+ eventId?: string;
45
+ createdAt?: string;
46
+ }
47
+ /** Recompute integrity hash for an existing envelope (T5.2.2 / verifyAuditHashChain). */
48
+ export declare function computeAuditRecordHash(envelope: AuditEnvelope<unknown>): string;
49
+ export declare function buildAuditEnvelope<TPayload extends object>(input: BuildAuditEnvelopeInput<TPayload>): AuditEnvelope<TPayload>;
50
+ /** @internal Maps legacy field manifest to audit manifest for persistence helpers. */
51
+ export declare function auditManifestFromFieldManifest(manifest: FieldRedactionManifest): AuditRedactionManifest;
@@ -0,0 +1,130 @@
1
+ /**
2
+ * Audit envelope construction + redaction for observability-system v5.
3
+ *
4
+ * Core logic: redact structured payloads, attach RedactionManifest (L0/L1 contract paths),
5
+ * compute hash-chain fields for append-only ledger rows.
6
+ *
7
+ * Dependencies: observability redactEvent (field-level); maps to envelope redaction paths.
8
+ *
9
+ * Boundaries: persistence is delegated to AppendOnlyAuditStore / DB adapters.
10
+ *
11
+ * Test coverage: tests/unit/observability/audit-envelope.test.ts
12
+ */
13
+ import * as crypto from "node:crypto";
14
+ import { redactEvent } from "../redaction/manifest.js";
15
+ function fieldPathToAuditPath(field) {
16
+ if (field.startsWith("/")) {
17
+ return field;
18
+ }
19
+ return `/payload/${field.replace(/\./g, "/")}`;
20
+ }
21
+ function mapSensitivity(level) {
22
+ switch (level) {
23
+ case "public":
24
+ return "public";
25
+ case "internal":
26
+ return "internal";
27
+ case "confidential":
28
+ return "private";
29
+ case "restricted":
30
+ return "sensitive";
31
+ default:
32
+ return "internal";
33
+ }
34
+ }
35
+ /**
36
+ * Apply field redaction rules and lift manifests to audit path vocabulary (observability-system.detail §2).
37
+ */
38
+ export function redactAuditEvent(payload) {
39
+ const { redacted, manifest } = redactEvent(payload);
40
+ const redaction = {
41
+ manifestId: manifest.id,
42
+ maskedPaths: manifest.maskedFields.map(fieldPathToAuditPath),
43
+ erasedPaths: manifest.erasedFields.map(fieldPathToAuditPath),
44
+ hashedPaths: manifest.hashedFields.map(fieldPathToAuditPath),
45
+ contentRefPaths: [],
46
+ sensitivity: mapSensitivity(manifest.sensitivityLevel),
47
+ };
48
+ return { payload: redacted, redaction };
49
+ }
50
+ function stableStringify(value) {
51
+ if (value === null || typeof value !== "object") {
52
+ return JSON.stringify(value);
53
+ }
54
+ if (Array.isArray(value)) {
55
+ return `[${value.map((v) => stableStringify(v)).join(",")}]`;
56
+ }
57
+ const obj = value;
58
+ const keys = Object.keys(obj).sort();
59
+ return `{${keys.map((k) => `${JSON.stringify(k)}:${stableStringify(obj[k])}`).join(",")}}`;
60
+ }
61
+ function hashRecord(input) {
62
+ const canonical = stableStringify({
63
+ eventId: input.eventId,
64
+ family: input.family,
65
+ plane: input.plane,
66
+ traceId: input.traceId,
67
+ sequence: input.sequence,
68
+ createdAt: input.createdAt,
69
+ payload: input.payload,
70
+ redaction: input.redaction,
71
+ previousHash: input.previousHash ?? null,
72
+ });
73
+ return crypto.createHash("sha256").update(canonical, "utf8").digest("hex");
74
+ }
75
+ /** Recompute integrity hash for an existing envelope (T5.2.2 / verifyAuditHashChain). */
76
+ export function computeAuditRecordHash(envelope) {
77
+ return hashRecord({
78
+ eventId: envelope.eventId,
79
+ family: envelope.family,
80
+ plane: envelope.plane,
81
+ traceId: envelope.traceId,
82
+ sequence: envelope.sequence,
83
+ createdAt: envelope.createdAt,
84
+ payload: envelope.payload,
85
+ redaction: envelope.redaction,
86
+ previousHash: envelope.integrity.previousHash,
87
+ });
88
+ }
89
+ export function buildAuditEnvelope(input) {
90
+ const { payload, redaction } = redactAuditEvent(input.payload);
91
+ const eventId = input.eventId ?? crypto.randomUUID();
92
+ const createdAt = input.createdAt ?? new Date().toISOString();
93
+ const recordHash = hashRecord({
94
+ eventId,
95
+ family: input.family,
96
+ plane: input.plane,
97
+ traceId: input.traceId,
98
+ sequence: input.sequence,
99
+ createdAt,
100
+ payload,
101
+ redaction,
102
+ previousHash: input.previousHash,
103
+ });
104
+ return {
105
+ eventId,
106
+ family: input.family,
107
+ plane: input.plane,
108
+ traceId: input.traceId,
109
+ sequence: input.sequence,
110
+ createdAt,
111
+ payload,
112
+ redaction,
113
+ integrity: {
114
+ previousHash: input.previousHash,
115
+ recordHash,
116
+ schemaVersion: "observability.v5",
117
+ },
118
+ };
119
+ }
120
+ /** @internal Maps legacy field manifest to audit manifest for persistence helpers. */
121
+ export function auditManifestFromFieldManifest(manifest) {
122
+ return {
123
+ manifestId: manifest.id,
124
+ maskedPaths: manifest.maskedFields.map(fieldPathToAuditPath),
125
+ erasedPaths: manifest.erasedFields.map(fieldPathToAuditPath),
126
+ hashedPaths: manifest.hashedFields.map(fieldPathToAuditPath),
127
+ contentRefPaths: [],
128
+ sensitivity: mapSensitivity(manifest.sensitivityLevel),
129
+ };
130
+ }
@@ -0,0 +1,23 @@
1
+ import type { AppendOnlyAuditStore } from "./append-only-audit-store.js";
2
+ import { type AuditEnvelope, type AuditEventFamily } from "./audit-envelope.js";
3
+ export interface AuditExportRange {
4
+ from: string;
5
+ to: string;
6
+ families?: AuditEventFamily[];
7
+ }
8
+ export type AuditHashChainVerificationStatus = "pass" | "broken" | "incomplete";
9
+ export interface AuditHashChainVerificationReport {
10
+ reportId: string;
11
+ generatedAt: string;
12
+ range: AuditExportRange;
13
+ checkedEventCount: number;
14
+ status: AuditHashChainVerificationStatus;
15
+ brokenAtEventIds: string[];
16
+ reasons: string[];
17
+ }
18
+ export interface VerifyAuditHashChainDeps {
19
+ loadRange(from: string, to: string, families?: AuditEventFamily[]): Promise<readonly AuditEnvelope<unknown>[]>;
20
+ }
21
+ export declare function verifyAuditHashChain(range: AuditExportRange, deps: VerifyAuditHashChainDeps): Promise<AuditHashChainVerificationReport>;
22
+ /** In-memory adapter: filter `AppendOnlyAuditStore.list()` by createdAt + optional families. */
23
+ export declare function createAppendOnlyAuditStoreRangeLoader(store: AppendOnlyAuditStore): VerifyAuditHashChainDeps;
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Range-based hash-chain verification for append-only audit rows (T5.2.2 / INT-S3).
3
+ *
4
+ * Core logic: load events in [from, to], order by sequence, recompute recordHash and
5
+ * verify previousHash links between consecutive **loaded** rows only (partial ranges
6
+ * may start mid-chain; parent outside the slice is not validated). Empty or invalid
7
+ * ranges yield incomplete (T5.2.2 / task verification plan).
8
+ *
9
+ * Dependencies: computeAuditRecordHash from audit-envelope; callers supply loadRange via deps.
10
+ *
11
+ * Test coverage: tests/unit/observability/verify-audit-hash-chain.test.ts
12
+ */
13
+ import * as crypto from "node:crypto";
14
+ import { computeAuditRecordHash } from "./audit-envelope.js";
15
+ function unique(ids) {
16
+ return [...new Set(ids)];
17
+ }
18
+ export async function verifyAuditHashChain(range, deps) {
19
+ const generatedAt = new Date().toISOString();
20
+ const reportId = crypto.randomUUID();
21
+ if (range.from > range.to) {
22
+ return {
23
+ reportId,
24
+ generatedAt,
25
+ range,
26
+ checkedEventCount: 0,
27
+ status: "incomplete",
28
+ brokenAtEventIds: [],
29
+ reasons: ["invalid_range_from_after_to"],
30
+ };
31
+ }
32
+ const raw = await deps.loadRange(range.from, range.to, range.families);
33
+ const events = [...raw].sort((a, b) => a.sequence - b.sequence);
34
+ if (events.length === 0) {
35
+ return {
36
+ reportId,
37
+ generatedAt,
38
+ range,
39
+ checkedEventCount: 0,
40
+ status: "incomplete",
41
+ brokenAtEventIds: [],
42
+ reasons: ["range_empty"],
43
+ };
44
+ }
45
+ const brokenAtEventIds = [];
46
+ for (let i = 0; i < events.length; i += 1) {
47
+ const event = events[i];
48
+ const expected = computeAuditRecordHash(event);
49
+ if (event.integrity.recordHash !== expected) {
50
+ brokenAtEventIds.push(event.eventId);
51
+ }
52
+ const prev = events[i - 1];
53
+ if (prev && event.integrity.previousHash !== prev.integrity.recordHash) {
54
+ brokenAtEventIds.push(event.eventId);
55
+ }
56
+ }
57
+ const uniq = unique(brokenAtEventIds);
58
+ const broken = uniq.length > 0;
59
+ return {
60
+ reportId,
61
+ generatedAt,
62
+ range,
63
+ checkedEventCount: events.length,
64
+ status: broken ? "broken" : "pass",
65
+ brokenAtEventIds: uniq,
66
+ reasons: broken ? ["hash_chain_broken"] : ["hash_chain_valid"],
67
+ };
68
+ }
69
+ /** In-memory adapter: filter `AppendOnlyAuditStore.list()` by createdAt + optional families. */
70
+ export function createAppendOnlyAuditStoreRangeLoader(store) {
71
+ return {
72
+ async loadRange(from, to, families) {
73
+ const fams = families?.length ? new Set(families) : undefined;
74
+ return store.list().filter((e) => {
75
+ if (e.createdAt < from || e.createdAt > to)
76
+ return false;
77
+ if (fams && !fams.has(e.family))
78
+ return false;
79
+ return true;
80
+ });
81
+ },
82
+ };
83
+ }
@@ -72,6 +72,17 @@ const OBSERVABILITY_SCHEMA_SQL = `
72
72
  created_at TEXT NOT NULL
73
73
  );
74
74
  CREATE INDEX IF NOT EXISTS redact_event_idx ON redaction_manifest(event_id);
75
+ CREATE TABLE IF NOT EXISTS host_capability_reports (
76
+ report_id TEXT PRIMARY KEY,
77
+ generated_at TEXT NOT NULL,
78
+ host_version TEXT,
79
+ observed_version TEXT,
80
+ doc_checked_at TEXT NOT NULL,
81
+ doc_links_json TEXT NOT NULL,
82
+ delivery_target TEXT NOT NULL,
83
+ conflict_records_json TEXT NOT NULL,
84
+ full_report_json TEXT NOT NULL
85
+ );
75
86
  `;
76
87
  function resolveDbPath(filename) {
77
88
  if (path.isAbsolute(filename) || filename === ":memory:") {