@haaaiawd/second-nature 0.1.8 → 0.1.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (185) hide show
  1. package/index.js +281 -69
  2. package/openclaw.plugin.json +1 -1
  3. package/package.json +2 -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 +162 -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/repositories/credential-repository.js +12 -1
  170. package/runtime/storage/rhythm/rhythm-policy-snapshot.d.ts +10 -0
  171. package/runtime/storage/rhythm/rhythm-policy-snapshot.js +34 -0
  172. package/runtime/storage/services/credential-vault.d.ts +5 -0
  173. package/runtime/storage/services/credential-vault.js +47 -9
  174. package/runtime/storage/snapshots/continuity-snapshot.d.ts +9 -0
  175. package/runtime/storage/snapshots/continuity-snapshot.js +41 -0
  176. package/runtime/storage/snapshots/life-evidence-snapshot.d.ts +6 -0
  177. package/runtime/storage/snapshots/life-evidence-snapshot.js +114 -0
  178. package/runtime/storage/snapshots/types.d.ts +58 -0
  179. package/runtime/storage/snapshots/types.js +1 -0
  180. package/runtime/storage/state-api.js +11 -4
  181. package/runtime/storage/user-interest/load-user-interest-snapshot.d.ts +2 -0
  182. package/runtime/storage/user-interest/load-user-interest-snapshot.js +150 -0
  183. package/runtime/storage/user-interest/types.d.ts +25 -0
  184. package/runtime/storage/user-interest/types.js +1 -0
  185. package/workspace-ops-bridge.js +78 -0
@@ -0,0 +1,161 @@
1
+ export declare const operatorFallbackArtifacts: import("drizzle-orm/sqlite-core").SQLiteTableWithColumns<{
2
+ name: "operator_fallback_artifacts";
3
+ schema: undefined;
4
+ columns: {
5
+ fallbackRef: import("drizzle-orm/sqlite-core").SQLiteColumn<{
6
+ name: "fallback_ref";
7
+ tableName: "operator_fallback_artifacts";
8
+ dataType: "string";
9
+ columnType: "SQLiteText";
10
+ data: string;
11
+ driverParam: string;
12
+ notNull: true;
13
+ hasDefault: false;
14
+ isPrimaryKey: true;
15
+ isAutoincrement: false;
16
+ hasRuntimeDefault: false;
17
+ enumValues: [string, ...string[]];
18
+ baseColumn: never;
19
+ identity: undefined;
20
+ generated: undefined;
21
+ }, {}, {
22
+ length: number | undefined;
23
+ }>;
24
+ decisionId: import("drizzle-orm/sqlite-core").SQLiteColumn<{
25
+ name: "decision_id";
26
+ tableName: "operator_fallback_artifacts";
27
+ dataType: "string";
28
+ columnType: "SQLiteText";
29
+ data: string;
30
+ driverParam: string;
31
+ notNull: true;
32
+ hasDefault: false;
33
+ isPrimaryKey: false;
34
+ isAutoincrement: false;
35
+ hasRuntimeDefault: false;
36
+ enumValues: [string, ...string[]];
37
+ baseColumn: never;
38
+ identity: undefined;
39
+ generated: undefined;
40
+ }, {}, {
41
+ length: number | undefined;
42
+ }>;
43
+ status: import("drizzle-orm/sqlite-core").SQLiteColumn<{
44
+ name: "status";
45
+ tableName: "operator_fallback_artifacts";
46
+ dataType: "string";
47
+ columnType: "SQLiteText";
48
+ data: string;
49
+ driverParam: string;
50
+ notNull: true;
51
+ hasDefault: false;
52
+ isPrimaryKey: false;
53
+ isAutoincrement: false;
54
+ hasRuntimeDefault: false;
55
+ enumValues: [string, ...string[]];
56
+ baseColumn: never;
57
+ identity: undefined;
58
+ generated: undefined;
59
+ }, {}, {
60
+ length: number | undefined;
61
+ }>;
62
+ reason: import("drizzle-orm/sqlite-core").SQLiteColumn<{
63
+ name: "reason";
64
+ tableName: "operator_fallback_artifacts";
65
+ dataType: "string";
66
+ columnType: "SQLiteText";
67
+ data: string;
68
+ driverParam: string;
69
+ notNull: true;
70
+ hasDefault: false;
71
+ isPrimaryKey: false;
72
+ isAutoincrement: false;
73
+ hasRuntimeDefault: false;
74
+ enumValues: [string, ...string[]];
75
+ baseColumn: never;
76
+ identity: undefined;
77
+ generated: undefined;
78
+ }, {}, {
79
+ length: number | undefined;
80
+ }>;
81
+ sourceRefsJson: import("drizzle-orm/sqlite-core").SQLiteColumn<{
82
+ name: "source_refs_json";
83
+ tableName: "operator_fallback_artifacts";
84
+ dataType: "string";
85
+ columnType: "SQLiteText";
86
+ data: string;
87
+ driverParam: string;
88
+ notNull: true;
89
+ hasDefault: false;
90
+ isPrimaryKey: false;
91
+ isAutoincrement: false;
92
+ hasRuntimeDefault: false;
93
+ enumValues: [string, ...string[]];
94
+ baseColumn: never;
95
+ identity: undefined;
96
+ generated: undefined;
97
+ }, {}, {
98
+ length: number | undefined;
99
+ }>;
100
+ candidateMessage: import("drizzle-orm/sqlite-core").SQLiteColumn<{
101
+ name: "candidate_message";
102
+ tableName: "operator_fallback_artifacts";
103
+ dataType: "string";
104
+ columnType: "SQLiteText";
105
+ data: string;
106
+ driverParam: string;
107
+ notNull: false;
108
+ hasDefault: false;
109
+ isPrimaryKey: false;
110
+ isAutoincrement: false;
111
+ hasRuntimeDefault: false;
112
+ enumValues: [string, ...string[]];
113
+ baseColumn: never;
114
+ identity: undefined;
115
+ generated: undefined;
116
+ }, {}, {
117
+ length: number | undefined;
118
+ }>;
119
+ nextStep: import("drizzle-orm/sqlite-core").SQLiteColumn<{
120
+ name: "next_step";
121
+ tableName: "operator_fallback_artifacts";
122
+ dataType: "string";
123
+ columnType: "SQLiteText";
124
+ data: string;
125
+ driverParam: string;
126
+ notNull: true;
127
+ hasDefault: false;
128
+ isPrimaryKey: false;
129
+ isAutoincrement: false;
130
+ hasRuntimeDefault: false;
131
+ enumValues: [string, ...string[]];
132
+ baseColumn: never;
133
+ identity: undefined;
134
+ generated: undefined;
135
+ }, {}, {
136
+ length: number | undefined;
137
+ }>;
138
+ createdAt: import("drizzle-orm/sqlite-core").SQLiteColumn<{
139
+ name: "created_at";
140
+ tableName: "operator_fallback_artifacts";
141
+ dataType: "string";
142
+ columnType: "SQLiteText";
143
+ data: string;
144
+ driverParam: string;
145
+ notNull: true;
146
+ hasDefault: false;
147
+ isPrimaryKey: false;
148
+ isAutoincrement: false;
149
+ hasRuntimeDefault: false;
150
+ enumValues: [string, ...string[]];
151
+ baseColumn: never;
152
+ identity: undefined;
153
+ generated: undefined;
154
+ }, {}, {
155
+ length: number | undefined;
156
+ }>;
157
+ };
158
+ dialect: "sqlite";
159
+ }>;
160
+ export type OperatorFallbackRow = typeof operatorFallbackArtifacts.$inferSelect;
161
+ export type NewOperatorFallbackRow = typeof operatorFallbackArtifacts.$inferInsert;
@@ -0,0 +1,11 @@
1
+ import { index, sqliteTable, text } from "drizzle-orm/sqlite-core";
2
+ export const operatorFallbackArtifacts = sqliteTable("operator_fallback_artifacts", {
3
+ fallbackRef: text("fallback_ref").primaryKey(),
4
+ decisionId: text("decision_id").notNull(),
5
+ status: text("status").notNull(),
6
+ reason: text("reason").notNull(),
7
+ sourceRefsJson: text("source_refs_json").notNull(),
8
+ candidateMessage: text("candidate_message"),
9
+ nextStep: text("next_step").notNull(),
10
+ createdAt: text("created_at").notNull(),
11
+ }, (table) => [index("operator_fallback_decision_idx").on(table.decisionId)]);
@@ -55,6 +55,23 @@ export declare const policyRecords: import("drizzle-orm/sqlite-core").SQLiteTabl
55
55
  identity: undefined;
56
56
  generated: undefined;
57
57
  }, {}, {}>;
58
+ outreachDailyBudget: import("drizzle-orm/sqlite-core").SQLiteColumn<{
59
+ name: "outreach_daily_budget";
60
+ tableName: "policy_records";
61
+ dataType: "number";
62
+ columnType: "SQLiteInteger";
63
+ data: number;
64
+ driverParam: number;
65
+ notNull: true;
66
+ hasDefault: true;
67
+ isPrimaryKey: false;
68
+ isAutoincrement: false;
69
+ hasRuntimeDefault: false;
70
+ enumValues: undefined;
71
+ baseColumn: never;
72
+ identity: undefined;
73
+ generated: undefined;
74
+ }, {}, {}>;
58
75
  updatedAt: import("drizzle-orm/sqlite-core").SQLiteColumn<{
59
76
  name: "updated_at";
60
77
  tableName: "policy_records";
@@ -3,5 +3,6 @@ export const policyRecords = sqliteTable("policy_records", {
3
3
  platformId: text("platform_id").primaryKey(),
4
4
  socialDailyLimit: integer("social_daily_limit").notNull(),
5
5
  quietEnabled: integer("quiet_enabled", { mode: "boolean" }).notNull(),
6
+ outreachDailyBudget: integer("outreach_daily_budget").notNull().default(2),
6
7
  updatedAt: text("updated_at").notNull(),
7
8
  });
@@ -0,0 +1,3 @@
1
+ import type { StateDatabase } from "../db/index.js";
2
+ import type { DeliveryAttemptRecord } from "./types.js";
3
+ export declare function listDeliveryAttemptsByDecisionId(state: StateDatabase, decisionId: string): Promise<DeliveryAttemptRecord[]>;
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Read models for delivery attempts by decisionId (T4.3.1).
3
+ */
4
+ import { eq } from "drizzle-orm";
5
+ import { deliveryAttempts } from "../db/schema/delivery-attempts.js";
6
+ function rowToRecord(row) {
7
+ let hostProofRef;
8
+ if (row.hostProofRefJson) {
9
+ try {
10
+ hostProofRef = JSON.parse(row.hostProofRefJson);
11
+ }
12
+ catch {
13
+ hostProofRef = undefined;
14
+ }
15
+ }
16
+ return {
17
+ attemptId: row.attemptId,
18
+ decisionId: row.decisionId,
19
+ target: row.target ?? undefined,
20
+ channel: row.channel ?? undefined,
21
+ status: row.status,
22
+ messageId: row.messageId ?? undefined,
23
+ hostProofRef,
24
+ errorClass: row.errorClass ?? undefined,
25
+ fallbackRef: row.fallbackRef ?? undefined,
26
+ createdAt: row.createdAt,
27
+ };
28
+ }
29
+ export async function listDeliveryAttemptsByDecisionId(state, decisionId) {
30
+ const rows = await state.db.select().from(deliveryAttempts).where(eq(deliveryAttempts.decisionId, decisionId));
31
+ return rows.map(rowToRecord);
32
+ }
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Delivery attempt persistence (state-system v5 / T4.3.1).
3
+ *
4
+ * Boundaries: validates proof fields before index write; hostProofRef uses SourceRef JSON.
5
+ * Test coverage: tests/unit/storage/delivery-attempt.test.ts
6
+ */
7
+ import type { SourceRef } from "../life-evidence/types.js";
8
+ export type DeliveryAttemptStatus = "sent" | "failed" | "dropped_by_host_policy";
9
+ export interface DeliveryAttemptWrite {
10
+ attemptId: string;
11
+ decisionId: string;
12
+ target?: "none" | "last" | "explicit";
13
+ channel?: string;
14
+ status: DeliveryAttemptStatus;
15
+ messageId?: string;
16
+ hostProofRef?: SourceRef;
17
+ errorClass?: string;
18
+ fallbackRef?: string;
19
+ }
20
+ export interface DeliveryAttemptRecord extends DeliveryAttemptWrite {
21
+ createdAt: string;
22
+ }
23
+ export interface DeliveryAttemptAck {
24
+ attemptId: string;
25
+ status: DeliveryAttemptStatus;
26
+ fallbackRef?: string;
27
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Persists delivery attempts with state-system validation (T4.3.1).
3
+ */
4
+ import type { StateDatabase } from "../db/index.js";
5
+ import type { DeliveryAttemptAck, DeliveryAttemptWrite } from "./types.js";
6
+ export declare function writeDeliveryAttempt(state: StateDatabase, attempt: DeliveryAttemptWrite): Promise<DeliveryAttemptAck>;
@@ -0,0 +1,36 @@
1
+ import { deliveryAttempts } from "../db/schema/delivery-attempts.js";
2
+ function assertDeliveryAttemptValid(attempt) {
3
+ if (attempt.status === "sent") {
4
+ const hasProof = Boolean(attempt.messageId?.trim()) || Boolean(attempt.hostProofRef);
5
+ if (!hasProof) {
6
+ throw new Error("delivery_attempt_sent_requires_message_id_or_host_proof_ref");
7
+ }
8
+ }
9
+ if (attempt.status === "failed" || attempt.status === "dropped_by_host_policy") {
10
+ const hasDiag = Boolean(attempt.errorClass?.trim()) || Boolean(attempt.fallbackRef?.trim());
11
+ if (!hasDiag) {
12
+ throw new Error("delivery_attempt_failed_requires_error_class_or_fallback_ref");
13
+ }
14
+ }
15
+ }
16
+ export async function writeDeliveryAttempt(state, attempt) {
17
+ assertDeliveryAttemptValid(attempt);
18
+ const createdAt = new Date().toISOString();
19
+ await state.db.insert(deliveryAttempts).values({
20
+ attemptId: attempt.attemptId,
21
+ decisionId: attempt.decisionId,
22
+ target: attempt.target ?? null,
23
+ channel: attempt.channel ?? null,
24
+ status: attempt.status,
25
+ messageId: attempt.messageId ?? null,
26
+ hostProofRefJson: attempt.hostProofRef ? JSON.stringify(attempt.hostProofRef) : null,
27
+ errorClass: attempt.errorClass ?? null,
28
+ fallbackRef: attempt.fallbackRef ?? null,
29
+ createdAt,
30
+ });
31
+ return {
32
+ attemptId: attempt.attemptId,
33
+ status: attempt.status,
34
+ fallbackRef: attempt.fallbackRef,
35
+ };
36
+ }
@@ -0,0 +1,14 @@
1
+ import type { StateDatabase } from "../db/index.js";
2
+ import type { SourceRef } from "../life-evidence/types.js";
3
+ import type { OperatorFallbackView } from "./operator-fallback-view.js";
4
+ export declare function normalizeFallbackRef(ref: string): string;
5
+ /** Loads persisted operator fallback row; does not coerce status (use `toOperatorFallbackView`). */
6
+ export declare function loadOperatorFallbackRow(state: StateDatabase, fallbackRef: string): Promise<{
7
+ fallbackRef: string;
8
+ reason: string;
9
+ status: string;
10
+ sourceRefs: SourceRef[];
11
+ candidateMessage?: string;
12
+ nextStep: string;
13
+ } | null>;
14
+ export declare function toOperatorFallbackView(row: NonNullable<Awaited<ReturnType<typeof loadOperatorFallbackRow>>>): OperatorFallbackView;
@@ -0,0 +1,47 @@
1
+ import { eq } from "drizzle-orm";
2
+ import { operatorFallbackArtifacts } from "../db/schema/operator-fallback-artifacts.js";
3
+ const REASONS = new Set(["target_none", "channel_missing", "host_unsupported", "delivery_failed"]);
4
+ export function normalizeFallbackRef(ref) {
5
+ const t = ref.trim();
6
+ if (!t)
7
+ return t;
8
+ return t.startsWith("fallback:") ? t : `fallback:${t}`;
9
+ }
10
+ function parseSourceRefs(json) {
11
+ try {
12
+ const parsed = JSON.parse(json);
13
+ return Array.isArray(parsed) ? parsed : [];
14
+ }
15
+ catch {
16
+ return [];
17
+ }
18
+ }
19
+ /** Loads persisted operator fallback row; does not coerce status (use `toOperatorFallbackView`). */
20
+ export async function loadOperatorFallbackRow(state, fallbackRef) {
21
+ const key = normalizeFallbackRef(fallbackRef);
22
+ if (!key)
23
+ return null;
24
+ const rows = await state.db.select().from(operatorFallbackArtifacts).where(eq(operatorFallbackArtifacts.fallbackRef, key)).limit(1);
25
+ const row = rows[0];
26
+ if (!row)
27
+ return null;
28
+ return {
29
+ fallbackRef: row.fallbackRef,
30
+ reason: row.reason,
31
+ status: row.status,
32
+ sourceRefs: parseSourceRefs(row.sourceRefsJson),
33
+ candidateMessage: row.candidateMessage ?? undefined,
34
+ nextStep: row.nextStep,
35
+ };
36
+ }
37
+ export function toOperatorFallbackView(row) {
38
+ const reason = REASONS.has(row.reason) ? row.reason : row.reason;
39
+ return {
40
+ fallbackRef: row.fallbackRef,
41
+ reason,
42
+ status: "not_sent",
43
+ sourceRefs: row.sourceRefs,
44
+ candidateMessage: row.candidateMessage,
45
+ nextStep: row.nextStep,
46
+ };
47
+ }
@@ -0,0 +1,9 @@
1
+ import type { SourceRef } from "../life-evidence/types.js";
2
+ export type OperatorFallbackReason = "target_none" | "channel_missing" | "host_unsupported" | "delivery_failed";
3
+ export interface OperatorFallbackWrite {
4
+ reason: OperatorFallbackReason;
5
+ decisionId: string;
6
+ sourceRefs: SourceRef[];
7
+ candidateMessage?: string;
8
+ nextStep: string;
9
+ }
@@ -0,0 +1,11 @@
1
+ import type { SourceRef } from "../life-evidence/types.js";
2
+ import type { OperatorFallbackReason } from "./operator-fallback-types.js";
3
+ /** Operator-facing delivery fallback (T1.2.2 / cli-system v5). Status is always not_sent — never sent/delivered. */
4
+ export interface OperatorFallbackView {
5
+ fallbackRef: string;
6
+ reason: OperatorFallbackReason | string;
7
+ status: "not_sent";
8
+ sourceRefs: SourceRef[];
9
+ candidateMessage?: string;
10
+ nextStep: string;
11
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,6 @@
1
+ import type { StateDatabase } from "../db/index.js";
2
+ import type { OperatorFallbackWrite } from "./operator-fallback-types.js";
3
+ export interface OperatorFallbackAck {
4
+ fallbackRef: string;
5
+ }
6
+ export declare function writeOperatorFallback(state: StateDatabase, input: OperatorFallbackWrite): Promise<OperatorFallbackAck>;
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Persists operator-visible delivery fallback artifacts (T2.3.2 / state-system v5).
3
+ * status is always not_sent per ADR-007.
4
+ */
5
+ import * as crypto from "node:crypto";
6
+ import { operatorFallbackArtifacts } from "../db/schema/operator-fallback-artifacts.js";
7
+ export async function writeOperatorFallback(state, input) {
8
+ const fallbackRef = `fallback:${crypto.randomUUID()}`;
9
+ const createdAt = new Date().toISOString();
10
+ await state.db.insert(operatorFallbackArtifacts).values({
11
+ fallbackRef,
12
+ decisionId: input.decisionId,
13
+ status: "not_sent",
14
+ reason: input.reason,
15
+ sourceRefsJson: JSON.stringify(input.sourceRefs),
16
+ candidateMessage: input.candidateMessage ?? null,
17
+ nextStep: input.nextStep,
18
+ createdAt,
19
+ });
20
+ return { fallbackRef };
21
+ }
@@ -13,4 +13,25 @@ export { createGovernanceLayer, type GovernanceLayer, type AnchorWriteProposal,
13
13
  export { createProvenanceService, type ProvenanceService, type ProvenanceTrace, type ProvenanceDetail } from "./services/provenance-service.js";
14
14
  export { createRepairAndBackupService, type RepairAndBackupService, type RepairAndBackupOptions, type RepairAndBackupResult, } from "./services/repair-and-backup.js";
15
15
  export { runStartupRepairAndBackup } from "./bootstrap/repair.js";
16
+ export { probeNativeSqliteLoad } from "./bootstrap/native-sqlite-probe.js";
17
+ export { runStorageModeSmoke, type StorageModeSmokeReport, type RunStorageModeSmokeOptions, } from "./bootstrap/storage-mode-smoke.js";
18
+ export { repairStateIndexes, type RepairSummary, type RepairStateIndexesOptions, type RepairGateStatus, } from "./bootstrap/repair-gate.js";
16
19
  export { createStateAPI, type StateAPI, type MemoryReadPort, type MemoryWritePort, type CredentialContextPort, type IntentCommitPort, type ProvenancePort } from "./state-api.js";
20
+ export type { LifeEvidence, LifeEvidenceCandidate, LifeEvidenceType, LifeEvidenceWriteAck, Sensitivity, SourceRef, } from "./life-evidence/types.js";
21
+ export { appendLifeEvidence, type AppendLifeEvidenceOptions } from "./life-evidence/append-life-evidence.js";
22
+ export { loadRhythmPolicySnapshot, type RhythmPolicySnapshot } from "./rhythm/rhythm-policy-snapshot.js";
23
+ export type { LifeEvidenceQuery, LifeEvidenceSnapshot, LifeEvidenceReadModel, ContinuitySnapshot, SourceCoverage, } from "./snapshots/types.js";
24
+ export { loadLifeEvidenceSnapshot, type LoadLifeEvidenceSnapshotOptions } from "./snapshots/life-evidence-snapshot.js";
25
+ export { loadContinuitySnapshot, type LoadContinuitySnapshotParams } from "./snapshots/continuity-snapshot.js";
26
+ export type { UserInterestSnapshot, UserInterestSignal, UserInterestStaleness } from "./user-interest/types.js";
27
+ export { loadUserInterestSnapshot } from "./user-interest/load-user-interest-snapshot.js";
28
+ export type { DeliveryAttemptWrite, DeliveryAttemptRecord, DeliveryAttemptAck } from "./delivery/types.js";
29
+ export { writeDeliveryAttempt } from "./delivery/write-delivery-attempt.js";
30
+ export { listDeliveryAttemptsByDecisionId } from "./delivery/query-delivery-attempts.js";
31
+ export type { OperatorFallbackWrite, OperatorFallbackReason } from "./fallback/operator-fallback-types.js";
32
+ export type { OperatorFallbackView } from "./fallback/operator-fallback-view.js";
33
+ export { writeOperatorFallback, type OperatorFallbackAck } from "./fallback/write-operator-fallback.js";
34
+ export { loadOperatorFallbackRow, normalizeFallbackRef, toOperatorFallbackView, } from "./fallback/load-operator-fallback.js";
35
+ export type { QuietArtifactWrite, QuietClaim, QuietArtifactKind } from "./quiet/quiet-artifact-types.js";
36
+ export { writeQuietArtifact, calculateQuietSourceCoverage, evidenceGroundingRatio, type QuietArtifactAck, } from "./quiet/quiet-artifact-writer.js";
37
+ export { persistQuietArtifactToWorkspace, type PersistQuietArtifactResult } from "./quiet/persist-quiet-artifact.js";
@@ -13,4 +13,18 @@ export { createGovernanceLayer } from "./services/governance-layer.js";
13
13
  export { createProvenanceService } from "./services/provenance-service.js";
14
14
  export { createRepairAndBackupService, } from "./services/repair-and-backup.js";
15
15
  export { runStartupRepairAndBackup } from "./bootstrap/repair.js";
16
+ export { probeNativeSqliteLoad } from "./bootstrap/native-sqlite-probe.js";
17
+ export { runStorageModeSmoke, } from "./bootstrap/storage-mode-smoke.js";
18
+ export { repairStateIndexes, } from "./bootstrap/repair-gate.js";
16
19
  export { createStateAPI } from "./state-api.js";
20
+ export { appendLifeEvidence } from "./life-evidence/append-life-evidence.js";
21
+ export { loadRhythmPolicySnapshot } from "./rhythm/rhythm-policy-snapshot.js";
22
+ export { loadLifeEvidenceSnapshot } from "./snapshots/life-evidence-snapshot.js";
23
+ export { loadContinuitySnapshot } from "./snapshots/continuity-snapshot.js";
24
+ export { loadUserInterestSnapshot } from "./user-interest/load-user-interest-snapshot.js";
25
+ export { writeDeliveryAttempt } from "./delivery/write-delivery-attempt.js";
26
+ export { listDeliveryAttemptsByDecisionId } from "./delivery/query-delivery-attempts.js";
27
+ export { writeOperatorFallback } from "./fallback/write-operator-fallback.js";
28
+ export { loadOperatorFallbackRow, normalizeFallbackRef, toOperatorFallbackView, } from "./fallback/load-operator-fallback.js";
29
+ export { writeQuietArtifact, calculateQuietSourceCoverage, evidenceGroundingRatio, } from "./quiet/quiet-artifact-writer.js";
30
+ export { persistQuietArtifactToWorkspace } from "./quiet/persist-quiet-artifact.js";
@@ -0,0 +1,7 @@
1
+ import type { StateDatabase } from "../db/index.js";
2
+ import type { ProvenanceRepository } from "../repositories/provenance-repository.js";
3
+ import type { LifeEvidenceCandidate, LifeEvidenceWriteAck } from "./types.js";
4
+ export interface AppendLifeEvidenceOptions {
5
+ provenance?: ProvenanceRepository;
6
+ }
7
+ export declare function appendLifeEvidence(state: StateDatabase, workspaceRoot: string, candidate: LifeEvidenceCandidate, options?: AppendLifeEvidenceOptions): Promise<LifeEvidenceWriteAck>;
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Append canonical LifeEvidence artifacts and SQLite index rows (state-system T4.1.1).
3
+ *
4
+ * Core logic: reject missing source refs and credential sensitivity; write JSON artifact;
5
+ * insert life_evidence_index; bump snapshot epoch file for downstream snapshot invalidation.
6
+ *
7
+ * Dependencies: StateDatabase drizzle + optional ProvenanceRepository for source edges.
8
+ *
9
+ * Boundaries: does not run connector normalization; caller supplies validated candidates.
10
+ *
11
+ * Test coverage: tests/unit/storage/life-evidence.test.ts
12
+ */
13
+ import * as crypto from "node:crypto";
14
+ import fs from "node:fs";
15
+ import path from "node:path";
16
+ import { lifeEvidenceIndex } from "../db/schema/life-evidence-index.js";
17
+ export async function appendLifeEvidence(state, workspaceRoot, candidate, options) {
18
+ if (!candidate.sourceRefs || candidate.sourceRefs.length === 0) {
19
+ throw new Error("life_evidence_missing_source_refs");
20
+ }
21
+ if (candidate.sensitivity === "credential") {
22
+ throw new Error("life_evidence_credential_rejected");
23
+ }
24
+ const evidenceId = candidate.id ?? `lev_${crypto.randomUUID()}`;
25
+ const artifactRel = path.join(".second-nature", "evidence", `${evidenceId}.json`);
26
+ const artifactAbs = path.join(workspaceRoot, artifactRel);
27
+ const artifactRef = {
28
+ id: `artifact:${evidenceId}`,
29
+ kind: "workspace_artifact",
30
+ uri: artifactRel.replace(/\\/g, "/"),
31
+ };
32
+ const life = {
33
+ id: evidenceId,
34
+ timestamp: candidate.timestamp,
35
+ evidenceType: candidate.evidenceType,
36
+ platformId: candidate.platformId,
37
+ summary: candidate.summary,
38
+ rawContentRef: candidate.rawContentRef,
39
+ sourceRefs: candidate.sourceRefs,
40
+ sensitivity: candidate.sensitivity,
41
+ confidence: candidate.confidence ?? 1,
42
+ tags: candidate.tags ?? [],
43
+ producer: candidate.producer,
44
+ artifactRef,
45
+ };
46
+ fs.mkdirSync(path.dirname(artifactAbs), { recursive: true });
47
+ fs.writeFileSync(artifactAbs, JSON.stringify(life, null, 2), "utf-8");
48
+ const epochPath = path.join(workspaceRoot, ".second-nature", "evidence", ".snapshot_epoch");
49
+ fs.writeFileSync(epochPath, `${Date.now()}\n`, "utf-8");
50
+ await state.db.insert(lifeEvidenceIndex).values({
51
+ id: evidenceId,
52
+ timestamp: candidate.timestamp,
53
+ evidenceType: candidate.evidenceType,
54
+ sensitivity: candidate.sensitivity,
55
+ producer: candidate.producer,
56
+ artifactPath: artifactRel.replace(/\\/g, "/"),
57
+ platformId: candidate.platformId ?? null,
58
+ sourceRefsJson: JSON.stringify(candidate.sourceRefs),
59
+ });
60
+ if (options?.provenance) {
61
+ await options.provenance.linkEntrySources(evidenceId, candidate.sourceRefs.map((ref) => ref.id));
62
+ }
63
+ return { evidenceId, artifactRef };
64
+ }
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Life evidence contract types (state-system v5 subset for ingest port).
3
+ *
4
+ * Test coverage: tests/unit/storage/life-evidence.test.ts
5
+ */
6
+ export type LifeEvidenceType = "platform_browse" | "platform_interaction" | "work_progress" | "task_discovery" | "user_interaction" | "quiet_reflection" | "delivery_fallback";
7
+ export type Sensitivity = "public" | "private" | "credential" | "sensitive";
8
+ export interface SourceRef {
9
+ id: string;
10
+ kind: "platform_item" | "workspace_artifact" | "decision_record" | "user_anchor" | "connector_result" | "host_report" | "fallback_artifact";
11
+ uri: string;
12
+ excerptHash?: string;
13
+ observedAt?: string;
14
+ }
15
+ export interface LifeEvidenceCandidate {
16
+ id?: string;
17
+ timestamp: string;
18
+ evidenceType: LifeEvidenceType;
19
+ platformId?: string;
20
+ summary: string;
21
+ rawContentRef?: string;
22
+ sourceRefs: SourceRef[];
23
+ sensitivity: Sensitivity;
24
+ confidence?: number;
25
+ tags?: string[];
26
+ producer: "connector-system" | "control-plane-system" | "observability-system" | "state-system";
27
+ }
28
+ export interface LifeEvidence {
29
+ id: string;
30
+ timestamp: string;
31
+ evidenceType: LifeEvidenceType;
32
+ platformId?: string;
33
+ summary: string;
34
+ rawContentRef?: string;
35
+ sourceRefs: SourceRef[];
36
+ sensitivity: Sensitivity;
37
+ confidence: number;
38
+ tags: string[];
39
+ producer: string;
40
+ artifactRef: SourceRef;
41
+ }
42
+ export interface LifeEvidenceWriteAck {
43
+ evidenceId: string;
44
+ artifactRef: SourceRef;
45
+ }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Life evidence contract types (state-system v5 subset for ingest port).
3
+ *
4
+ * Test coverage: tests/unit/storage/life-evidence.test.ts
5
+ */
6
+ export {};
@@ -0,0 +1,7 @@
1
+ import type { QuietArtifactWrite } from "./quiet-artifact-types.js";
2
+ import type { QuietArtifactAck } from "./quiet-artifact-writer.js";
3
+ export interface PersistQuietArtifactResult {
4
+ relativePath: string;
5
+ absolutePath: string;
6
+ }
7
+ export declare function persistQuietArtifactToWorkspace(workspaceRoot: string, ack: QuietArtifactAck, input: QuietArtifactWrite): Promise<PersistQuietArtifactResult>;
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Writes validated Quiet artifact JSON under workspace `.second-nature/quiet/{day}/` (CR-M3 / T2.3.3).
3
+ */
4
+ import * as fs from "node:fs/promises";
5
+ import * as path from "node:path";
6
+ export async function persistQuietArtifactToWorkspace(workspaceRoot, ack, input) {
7
+ const dir = path.join(workspaceRoot, ".second-nature", "quiet", input.day);
8
+ await fs.mkdir(dir, { recursive: true });
9
+ const file = path.join(dir, `${ack.artifactId}.json`);
10
+ const payload = {
11
+ artifactId: ack.artifactId,
12
+ artifactRef: ack.artifactRef,
13
+ sourceCoverage: ack.sourceCoverage,
14
+ write: input,
15
+ persistedAt: new Date().toISOString(),
16
+ };
17
+ await fs.writeFile(file, JSON.stringify(payload, null, 2), "utf8");
18
+ return {
19
+ relativePath: path.relative(workspaceRoot, file),
20
+ absolutePath: file,
21
+ };
22
+ }