@haaaiawd/second-nature 0.1.18 → 0.1.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (188) hide show
  1. package/index.js +855 -855
  2. package/openclaw.plugin.json +29 -29
  3. package/package.json +52 -52
  4. package/runtime/cli/commands/index.d.ts +14 -14
  5. package/runtime/cli/commands/index.js +193 -193
  6. package/runtime/cli/explain/explain-surface-subject.d.ts +8 -8
  7. package/runtime/cli/explain/explain-surface-subject.js +9 -9
  8. package/runtime/cli/explain/format-explanation.d.ts +12 -12
  9. package/runtime/cli/explain/format-explanation.js +12 -12
  10. package/runtime/cli/explain/resolve-subject.js +41 -41
  11. package/runtime/cli/host-capability/classify-delivery.d.ts +14 -14
  12. package/runtime/cli/host-capability/classify-delivery.js +20 -20
  13. package/runtime/cli/host-capability/probe-host-capability.d.ts +2 -2
  14. package/runtime/cli/host-capability/probe-host-capability.js +58 -58
  15. package/runtime/cli/host-capability/record-host-capability.d.ts +6 -6
  16. package/runtime/cli/host-capability/record-host-capability.js +14 -14
  17. package/runtime/cli/host-capability/types.d.ts +71 -71
  18. package/runtime/cli/host-capability/types.js +6 -6
  19. package/runtime/cli/host-smoke/run-host-smoke.d.ts +2 -2
  20. package/runtime/cli/host-smoke/run-host-smoke.js +40 -40
  21. package/runtime/cli/host-smoke/types.d.ts +35 -35
  22. package/runtime/cli/host-smoke/types.js +6 -6
  23. package/runtime/cli/index.js +65 -58
  24. package/runtime/cli/ops/heartbeat-surface.d.ts +45 -38
  25. package/runtime/cli/ops/heartbeat-surface.js +79 -73
  26. package/runtime/cli/ops/ops-router.d.ts +26 -19
  27. package/runtime/cli/ops/ops-router.js +102 -89
  28. package/runtime/cli/ops/show-operator-fallback.d.ts +13 -13
  29. package/runtime/cli/ops/show-operator-fallback.js +22 -22
  30. package/runtime/cli/ops/workspace-heartbeat-runner.d.ts +40 -19
  31. package/runtime/cli/ops/workspace-heartbeat-runner.js +93 -39
  32. package/runtime/cli/read-models/index.d.ts +35 -29
  33. package/runtime/cli/read-models/index.js +365 -256
  34. package/runtime/cli/read-models/operator-explain-map.d.ts +6 -6
  35. package/runtime/cli/read-models/operator-explain-map.js +10 -10
  36. package/runtime/cli/read-models/types.d.ts +112 -79
  37. package/runtime/cli/runtime/runtime-artifact-boundary.d.ts +28 -28
  38. package/runtime/cli/runtime/runtime-artifact-boundary.js +94 -94
  39. package/runtime/connectors/base/contract.d.ts +87 -87
  40. package/runtime/connectors/base/execution-policy.d.ts +47 -47
  41. package/runtime/connectors/base/execution-policy.js +82 -82
  42. package/runtime/connectors/base/index.d.ts +8 -8
  43. package/runtime/connectors/base/index.js +8 -8
  44. package/runtime/connectors/base/manifest.d.ts +64 -64
  45. package/runtime/connectors/base/manifest.js +86 -86
  46. package/runtime/connectors/base/map-life-evidence.d.ts +16 -16
  47. package/runtime/connectors/base/map-life-evidence.js +79 -79
  48. package/runtime/connectors/base/policy-layer.d.ts +29 -29
  49. package/runtime/connectors/base/policy-layer.js +198 -198
  50. package/runtime/connectors/base/route-planner.js +99 -99
  51. package/runtime/connectors/index.d.ts +5 -5
  52. package/runtime/connectors/index.js +5 -5
  53. package/runtime/connectors/near-real/near-real-connector-smoke.d.ts +19 -19
  54. package/runtime/connectors/near-real/near-real-connector-smoke.js +152 -152
  55. package/runtime/core/second-nature/heartbeat/heartbeat-executor.js +114 -114
  56. package/runtime/core/second-nature/heartbeat/heartbeat-loop.d.ts +63 -63
  57. package/runtime/core/second-nature/heartbeat/heartbeat-loop.js +162 -139
  58. package/runtime/core/second-nature/heartbeat/index.d.ts +8 -8
  59. package/runtime/core/second-nature/heartbeat/index.js +7 -7
  60. package/runtime/core/second-nature/heartbeat/run-heartbeat-cycle.d.ts +21 -21
  61. package/runtime/core/second-nature/heartbeat/run-heartbeat-cycle.js +35 -35
  62. package/runtime/core/second-nature/heartbeat/runtime-snapshot.d.ts +28 -28
  63. package/runtime/core/second-nature/heartbeat/runtime-snapshot.js +35 -35
  64. package/runtime/core/second-nature/heartbeat/signal.d.ts +42 -42
  65. package/runtime/core/second-nature/heartbeat/snapshot-builder.d.ts +51 -51
  66. package/runtime/core/second-nature/index.d.ts +22 -22
  67. package/runtime/core/second-nature/index.js +22 -22
  68. package/runtime/core/second-nature/orchestrator/effect-dispatcher.d.ts +100 -100
  69. package/runtime/core/second-nature/orchestrator/effect-dispatcher.js +144 -144
  70. package/runtime/core/second-nature/orchestrator/guard-layer.d.ts +8 -8
  71. package/runtime/core/second-nature/orchestrator/guard-layer.js +110 -110
  72. package/runtime/core/second-nature/orchestrator/intent-planner.d.ts +13 -13
  73. package/runtime/core/second-nature/orchestrator/intent-planner.js +199 -199
  74. package/runtime/core/second-nature/orchestrator/lease-manager.d.ts +14 -14
  75. package/runtime/core/second-nature/orchestrator/lease-manager.js +58 -58
  76. package/runtime/core/second-nature/outreach/build-outreach-draft-request.d.ts +6 -6
  77. package/runtime/core/second-nature/outreach/build-outreach-draft-request.js +63 -63
  78. package/runtime/core/second-nature/outreach/delivery-target.d.ts +26 -26
  79. package/runtime/core/second-nature/outreach/delivery-target.js +70 -70
  80. package/runtime/core/second-nature/outreach/dispatch-user-outreach.d.ts +38 -38
  81. package/runtime/core/second-nature/outreach/dispatch-user-outreach.js +119 -119
  82. package/runtime/core/second-nature/outreach/judge-input-from-snapshot.d.ts +7 -7
  83. package/runtime/core/second-nature/outreach/judge-input-from-snapshot.js +45 -45
  84. package/runtime/core/second-nature/outreach/judge-outreach.d.ts +40 -40
  85. package/runtime/core/second-nature/outreach/judge-outreach.js +121 -121
  86. package/runtime/core/second-nature/quiet/run-source-backed-quiet.d.ts +21 -21
  87. package/runtime/core/second-nature/quiet/run-source-backed-quiet.js +123 -123
  88. package/runtime/core/second-nature/rhythm/planner-rhythm-window.d.ts +15 -15
  89. package/runtime/core/second-nature/rhythm/planner-rhythm-window.js +52 -52
  90. package/runtime/core/second-nature/rhythm/policy-bridge.d.ts +19 -19
  91. package/runtime/core/second-nature/rhythm/policy-bridge.js +34 -34
  92. package/runtime/core/second-nature/runtime/service-entry.js +45 -45
  93. package/runtime/core/second-nature/types.d.ts +51 -51
  94. package/runtime/guidance/draft-outreach-message.d.ts +7 -7
  95. package/runtime/guidance/draft-outreach-message.js +42 -42
  96. package/runtime/guidance/evidence-guidance.d.ts +40 -40
  97. package/runtime/guidance/evidence-guidance.js +52 -52
  98. package/runtime/guidance/index.d.ts +11 -11
  99. package/runtime/guidance/index.js +11 -11
  100. package/runtime/guidance/outreach-draft-schema.d.ts +228 -228
  101. package/runtime/guidance/outreach-draft-schema.js +80 -80
  102. package/runtime/observability/audit/append-only-audit-store.d.ts +14 -14
  103. package/runtime/observability/audit/append-only-audit-store.js +21 -21
  104. package/runtime/observability/audit/audit-envelope.d.ts +51 -51
  105. package/runtime/observability/audit/audit-envelope.js +130 -130
  106. package/runtime/observability/audit/verify-audit-hash-chain.d.ts +23 -23
  107. package/runtime/observability/audit/verify-audit-hash-chain.js +83 -83
  108. package/runtime/observability/db/index.js +47 -47
  109. package/runtime/observability/db/schema/host-capability-reports.d.ts +180 -180
  110. package/runtime/observability/db/schema/host-capability-reports.js +12 -12
  111. package/runtime/observability/db/schema/index.d.ts +947 -947
  112. package/runtime/observability/db/schema/index.js +71 -71
  113. package/runtime/observability/index.d.ts +20 -20
  114. package/runtime/observability/index.js +19 -19
  115. package/runtime/observability/query/explain-query.d.ts +48 -48
  116. package/runtime/observability/query/explain-query.js +114 -114
  117. package/runtime/observability/query/export-audit-bundle.d.ts +22 -22
  118. package/runtime/observability/query/export-audit-bundle.js +27 -27
  119. package/runtime/observability/services/decision-ledger.d.ts +46 -46
  120. package/runtime/observability/services/decision-ledger.js +161 -161
  121. package/runtime/observability/services/governance-audit.d.ts +41 -41
  122. package/runtime/observability/services/governance-audit.js +163 -163
  123. package/runtime/observability/services/governance-plane-recorder.d.ts +47 -47
  124. package/runtime/observability/services/governance-plane-recorder.js +55 -55
  125. package/runtime/observability/services/lived-experience-audit.d.ts +97 -97
  126. package/runtime/observability/services/lived-experience-audit.js +162 -162
  127. package/runtime/observability/services/runtime-decision-recorder.d.ts +29 -29
  128. package/runtime/observability/services/runtime-decision-recorder.js +94 -94
  129. package/runtime/storage/bootstrap/native-sqlite-probe.d.ts +7 -7
  130. package/runtime/storage/bootstrap/native-sqlite-probe.js +28 -28
  131. package/runtime/storage/bootstrap/repair-gate.d.ts +17 -17
  132. package/runtime/storage/bootstrap/repair-gate.js +71 -71
  133. package/runtime/storage/bootstrap/storage-mode-smoke.d.ts +38 -38
  134. package/runtime/storage/bootstrap/storage-mode-smoke.js +85 -85
  135. package/runtime/storage/db/index.js +61 -61
  136. package/runtime/storage/db/schema/delivery-attempts.d.ts +199 -199
  137. package/runtime/storage/db/schema/delivery-attempts.js +13 -13
  138. package/runtime/storage/db/schema/index.d.ts +9 -9
  139. package/runtime/storage/db/schema/index.js +9 -9
  140. package/runtime/storage/db/schema/life-evidence-index.d.ts +161 -161
  141. package/runtime/storage/db/schema/life-evidence-index.js +11 -11
  142. package/runtime/storage/db/schema/operator-fallback-artifacts.d.ts +161 -161
  143. package/runtime/storage/db/schema/operator-fallback-artifacts.js +11 -11
  144. package/runtime/storage/db/schema/policies.d.ts +98 -98
  145. package/runtime/storage/db/schema/policies.js +8 -8
  146. package/runtime/storage/delivery/query-delivery-attempts.d.ts +3 -3
  147. package/runtime/storage/delivery/query-delivery-attempts.js +32 -32
  148. package/runtime/storage/delivery/types.d.ts +27 -27
  149. package/runtime/storage/delivery/types.js +1 -1
  150. package/runtime/storage/delivery/write-delivery-attempt.d.ts +6 -6
  151. package/runtime/storage/delivery/write-delivery-attempt.js +36 -36
  152. package/runtime/storage/fallback/load-operator-fallback.d.ts +14 -14
  153. package/runtime/storage/fallback/load-operator-fallback.js +47 -47
  154. package/runtime/storage/fallback/operator-fallback-types.d.ts +9 -9
  155. package/runtime/storage/fallback/operator-fallback-types.js +1 -1
  156. package/runtime/storage/fallback/operator-fallback-view.d.ts +11 -11
  157. package/runtime/storage/fallback/operator-fallback-view.js +1 -1
  158. package/runtime/storage/fallback/write-operator-fallback.d.ts +6 -6
  159. package/runtime/storage/fallback/write-operator-fallback.js +21 -21
  160. package/runtime/storage/index.d.ts +37 -37
  161. package/runtime/storage/index.js +30 -30
  162. package/runtime/storage/life-evidence/append-life-evidence.d.ts +7 -7
  163. package/runtime/storage/life-evidence/append-life-evidence.js +64 -64
  164. package/runtime/storage/life-evidence/types.d.ts +45 -45
  165. package/runtime/storage/life-evidence/types.js +6 -6
  166. package/runtime/storage/quiet/persist-quiet-artifact.d.ts +7 -7
  167. package/runtime/storage/quiet/persist-quiet-artifact.js +22 -22
  168. package/runtime/storage/quiet/quiet-artifact-types.d.ts +18 -18
  169. package/runtime/storage/quiet/quiet-artifact-types.js +1 -1
  170. package/runtime/storage/quiet/quiet-artifact-writer.d.ts +15 -15
  171. package/runtime/storage/quiet/quiet-artifact-writer.js +56 -56
  172. package/runtime/storage/repositories/credential-repository.js +30 -30
  173. package/runtime/storage/rhythm/rhythm-policy-snapshot.d.ts +10 -10
  174. package/runtime/storage/rhythm/rhythm-policy-snapshot.js +34 -34
  175. package/runtime/storage/services/credential-vault.d.ts +13 -13
  176. package/runtime/storage/services/credential-vault.js +116 -116
  177. package/runtime/storage/snapshots/continuity-snapshot.d.ts +9 -9
  178. package/runtime/storage/snapshots/continuity-snapshot.js +41 -41
  179. package/runtime/storage/snapshots/life-evidence-snapshot.d.ts +6 -6
  180. package/runtime/storage/snapshots/life-evidence-snapshot.js +114 -114
  181. package/runtime/storage/snapshots/types.d.ts +58 -58
  182. package/runtime/storage/snapshots/types.js +1 -1
  183. package/runtime/storage/state-api.js +104 -104
  184. package/runtime/storage/user-interest/load-user-interest-snapshot.d.ts +2 -2
  185. package/runtime/storage/user-interest/load-user-interest-snapshot.js +150 -150
  186. package/runtime/storage/user-interest/types.d.ts +25 -25
  187. package/runtime/storage/user-interest/types.js +1 -1
  188. package/workspace-ops-bridge.js +81 -81
@@ -1,94 +1,94 @@
1
- /**
2
- * Runtime Decision Recorder (T1.2.3).
3
- *
4
- * Core logic: after a workspace `runHeartbeatCycle` completes, persist two rows that
5
- * `loadStatus` already filters on, so operator status stops returning `unknown` for
6
- * `rhythm.mode` / `runtime.serviceStatus` once the runtime has executed at least once.
7
- * - `decision_ledger` row via `DecisionLedger.recordHeartbeatDecision()` with
8
- * `traceId` prefix `sn-runtime-` (matches `INTERNAL_RUNTIME_TRACE_PREFIX`).
9
- * - `execution_attempts` row via `ExecutionTelemetry.startAttempt` +
10
- * `completeAttempt` with `platformId === "second-nature-runtime"` (matches
11
- * `INTERNAL_RUNTIME_PLATFORM_ID`).
12
- *
13
- * Boundaries:
14
- * - Recorder failure must NOT break the heartbeat surface response — caller wraps with try/catch.
15
- * - Carrier-only / probe-only / runtime-unavailable paths do NOT invoke this recorder
16
- * (their semantics intentionally remain "unknown" until a full-runtime turn happens).
17
- * - This is a derived observability writer; it is not the canonical decision producer
18
- * (control-plane keeps that contract). It exists to close the read-side aggregation gap.
19
- */
20
- import { randomUUID } from "node:crypto";
21
- import { DecisionLedger } from "./decision-ledger.js";
22
- import { ExecutionTelemetry } from "./execution-telemetry.js";
23
- export const RUNTIME_DECISION_TRACE_PREFIX = "sn-runtime-";
24
- export const RUNTIME_INTERNAL_PLATFORM_ID = "second-nature-runtime";
25
- const RUNTIME_INTERNAL_CAPABILITY = "runtime.heartbeat";
26
- const RUNTIME_INTERNAL_CHANNEL = "internal";
27
- export function createRuntimeDecisionRecorder(observabilityDb, overrides = {}) {
28
- const ledger = overrides.ledger ?? new DecisionLedger(observabilityDb);
29
- const telemetry = overrides.telemetry ?? new ExecutionTelemetry(observabilityDb);
30
- return {
31
- async recordHeartbeatCycle({ cycle, signal, rhythmMode }) {
32
- const timestamp = typeof signal.payload.timestamp === "string" && signal.payload.timestamp.trim().length > 0
33
- ? signal.payload.timestamp
34
- : new Date().toISOString();
35
- const uniqueId = randomUUID();
36
- const traceId = `${RUNTIME_DECISION_TRACE_PREFIX}${cycle.scope}-${cycle.status}-${uniqueId}`;
37
- const decisionId = `decision-runtime-${uniqueId}`;
38
- const tickId = `tick-runtime-${uniqueId}`;
39
- const event = {
40
- id: decisionId,
41
- tickId,
42
- traceId,
43
- runtimeScope: cycle.scope,
44
- triggerSource: signal.trigger,
45
- decisionStatus: mapCycleStatus(cycle.status),
46
- reasons: cycle.reasons,
47
- intentId: cycle.selectedIntentId,
48
- mode: rhythmMode ?? "active",
49
- createdAt: timestamp,
50
- };
51
- await ledger.recordHeartbeatDecision(event);
52
- const attemptId = await telemetry.startAttempt({
53
- traceId,
54
- decisionId,
55
- intentId: cycle.selectedIntentId ?? `${RUNTIME_INTERNAL_PLATFORM_ID}-tick`,
56
- platformId: RUNTIME_INTERNAL_PLATFORM_ID,
57
- capability: RUNTIME_INTERNAL_CAPABILITY,
58
- channel: RUNTIME_INTERNAL_CHANNEL,
59
- startedAt: timestamp,
60
- });
61
- const status = isFailureCycle(cycle.status) ? "failed" : "succeeded";
62
- const failureClass = status === "failed" ? cycleStatusFailureClass(cycle.status) : undefined;
63
- await telemetry.completeAttempt(traceId, status, undefined, failureClass);
64
- return { traceId, decisionId, attemptId };
65
- },
66
- };
67
- }
68
- function mapCycleStatus(status) {
69
- switch (status) {
70
- case "intent_selected":
71
- return "intent_selected";
72
- case "denied":
73
- return "denied";
74
- case "deferred":
75
- return "deferred";
76
- case "delivery_unavailable":
77
- return "delivery_unavailable";
78
- case "runtime_carrier_only":
79
- return "runtime_carrier_only";
80
- case "heartbeat_ok":
81
- default:
82
- return "heartbeat_ok";
83
- }
84
- }
85
- function isFailureCycle(status) {
86
- return status === "delivery_unavailable" || status === "denied";
87
- }
88
- function cycleStatusFailureClass(status) {
89
- if (status === "delivery_unavailable")
90
- return "delivery_unavailable";
91
- if (status === "denied")
92
- return "decision_denied";
93
- return undefined;
94
- }
1
+ /**
2
+ * Runtime Decision Recorder (T1.2.3).
3
+ *
4
+ * Core logic: after a workspace `runHeartbeatCycle` completes, persist two rows that
5
+ * `loadStatus` already filters on, so operator status stops returning `unknown` for
6
+ * `rhythm.mode` / `runtime.serviceStatus` once the runtime has executed at least once.
7
+ * - `decision_ledger` row via `DecisionLedger.recordHeartbeatDecision()` with
8
+ * `traceId` prefix `sn-runtime-` (matches `INTERNAL_RUNTIME_TRACE_PREFIX`).
9
+ * - `execution_attempts` row via `ExecutionTelemetry.startAttempt` +
10
+ * `completeAttempt` with `platformId === "second-nature-runtime"` (matches
11
+ * `INTERNAL_RUNTIME_PLATFORM_ID`).
12
+ *
13
+ * Boundaries:
14
+ * - Recorder failure must NOT break the heartbeat surface response — caller wraps with try/catch.
15
+ * - Carrier-only / probe-only / runtime-unavailable paths do NOT invoke this recorder
16
+ * (their semantics intentionally remain "unknown" until a full-runtime turn happens).
17
+ * - This is a derived observability writer; it is not the canonical decision producer
18
+ * (control-plane keeps that contract). It exists to close the read-side aggregation gap.
19
+ */
20
+ import { randomUUID } from "node:crypto";
21
+ import { DecisionLedger } from "./decision-ledger.js";
22
+ import { ExecutionTelemetry } from "./execution-telemetry.js";
23
+ export const RUNTIME_DECISION_TRACE_PREFIX = "sn-runtime-";
24
+ export const RUNTIME_INTERNAL_PLATFORM_ID = "second-nature-runtime";
25
+ const RUNTIME_INTERNAL_CAPABILITY = "runtime.heartbeat";
26
+ const RUNTIME_INTERNAL_CHANNEL = "internal";
27
+ export function createRuntimeDecisionRecorder(observabilityDb, overrides = {}) {
28
+ const ledger = overrides.ledger ?? new DecisionLedger(observabilityDb);
29
+ const telemetry = overrides.telemetry ?? new ExecutionTelemetry(observabilityDb);
30
+ return {
31
+ async recordHeartbeatCycle({ cycle, signal, rhythmMode }) {
32
+ const timestamp = typeof signal.payload.timestamp === "string" && signal.payload.timestamp.trim().length > 0
33
+ ? signal.payload.timestamp
34
+ : new Date().toISOString();
35
+ const uniqueId = randomUUID();
36
+ const traceId = `${RUNTIME_DECISION_TRACE_PREFIX}${cycle.scope}-${cycle.status}-${uniqueId}`;
37
+ const decisionId = `decision-runtime-${uniqueId}`;
38
+ const tickId = `tick-runtime-${uniqueId}`;
39
+ const event = {
40
+ id: decisionId,
41
+ tickId,
42
+ traceId,
43
+ runtimeScope: cycle.scope,
44
+ triggerSource: signal.trigger,
45
+ decisionStatus: mapCycleStatus(cycle.status),
46
+ reasons: cycle.reasons,
47
+ intentId: cycle.selectedIntentId,
48
+ mode: rhythmMode ?? "active",
49
+ createdAt: timestamp,
50
+ };
51
+ await ledger.recordHeartbeatDecision(event);
52
+ const attemptId = await telemetry.startAttempt({
53
+ traceId,
54
+ decisionId,
55
+ intentId: cycle.selectedIntentId ?? `${RUNTIME_INTERNAL_PLATFORM_ID}-tick`,
56
+ platformId: RUNTIME_INTERNAL_PLATFORM_ID,
57
+ capability: RUNTIME_INTERNAL_CAPABILITY,
58
+ channel: RUNTIME_INTERNAL_CHANNEL,
59
+ startedAt: timestamp,
60
+ });
61
+ const status = isFailureCycle(cycle.status) ? "failed" : "succeeded";
62
+ const failureClass = status === "failed" ? cycleStatusFailureClass(cycle.status) : undefined;
63
+ await telemetry.completeAttempt(traceId, status, undefined, failureClass);
64
+ return { traceId, decisionId, attemptId };
65
+ },
66
+ };
67
+ }
68
+ function mapCycleStatus(status) {
69
+ switch (status) {
70
+ case "intent_selected":
71
+ return "intent_selected";
72
+ case "denied":
73
+ return "denied";
74
+ case "deferred":
75
+ return "deferred";
76
+ case "delivery_unavailable":
77
+ return "delivery_unavailable";
78
+ case "runtime_carrier_only":
79
+ return "runtime_carrier_only";
80
+ case "heartbeat_ok":
81
+ default:
82
+ return "heartbeat_ok";
83
+ }
84
+ }
85
+ function isFailureCycle(status) {
86
+ return status === "delivery_unavailable" || status === "denied";
87
+ }
88
+ function cycleStatusFailureClass(status) {
89
+ if (status === "delivery_unavailable")
90
+ return "delivery_unavailable";
91
+ if (status === "denied")
92
+ return "decision_denied";
93
+ return undefined;
94
+ }
@@ -1,7 +1,7 @@
1
- export interface NativeSqliteProbeResult {
2
- moduleLoadOk: boolean;
3
- /** package version when load succeeds */
4
- version?: string;
5
- errorMessage?: string;
6
- }
7
- export declare function probeNativeSqliteLoad(): NativeSqliteProbeResult;
1
+ export interface NativeSqliteProbeResult {
2
+ moduleLoadOk: boolean;
3
+ /** package version when load succeeds */
4
+ version?: string;
5
+ errorMessage?: string;
6
+ }
7
+ export declare function probeNativeSqliteLoad(): NativeSqliteProbeResult;
@@ -1,28 +1,28 @@
1
- /**
2
- * Optional better-sqlite3 load probe (T4.1.4). Second Nature state DB currently uses sql.js only;
3
- * this probe records whether the native module can load for packaging / host diagnostics.
4
- */
5
- import { createRequire } from "node:module";
6
- const require = createRequire(import.meta.url);
7
- export function probeNativeSqliteLoad() {
8
- try {
9
- const Database = require("better-sqlite3");
10
- const db = new Database(":memory:");
11
- db.close();
12
- let version;
13
- try {
14
- const pkg = require("better-sqlite3/package.json");
15
- version = pkg.version;
16
- }
17
- catch {
18
- version = undefined;
19
- }
20
- return { moduleLoadOk: true, version };
21
- }
22
- catch (error) {
23
- return {
24
- moduleLoadOk: false,
25
- errorMessage: error instanceof Error ? error.message : String(error),
26
- };
27
- }
28
- }
1
+ /**
2
+ * Optional better-sqlite3 load probe (T4.1.4). Second Nature state DB currently uses sql.js only;
3
+ * this probe records whether the native module can load for packaging / host diagnostics.
4
+ */
5
+ import { createRequire } from "node:module";
6
+ const require = createRequire(import.meta.url);
7
+ export function probeNativeSqliteLoad() {
8
+ try {
9
+ const Database = require("better-sqlite3");
10
+ const db = new Database(":memory:");
11
+ db.close();
12
+ let version;
13
+ try {
14
+ const pkg = require("better-sqlite3/package.json");
15
+ version = pkg.version;
16
+ }
17
+ catch {
18
+ version = undefined;
19
+ }
20
+ return { moduleLoadOk: true, version };
21
+ }
22
+ catch (error) {
23
+ return {
24
+ moduleLoadOk: false,
25
+ errorMessage: error instanceof Error ? error.message : String(error),
26
+ };
27
+ }
28
+ }
@@ -1,17 +1,17 @@
1
- import type { StateDatabase } from "../db/index.js";
2
- import { createRepairAndBackupService, type RepairAndBackupOptions } from "../services/repair-and-backup.js";
3
- export interface RepairStateIndexesOptions {
4
- startupGate?: boolean;
5
- workspaceRoot: string;
6
- /** When true, also runs asset registry repair + backup (existing repair service) */
7
- reconcileAssets?: boolean;
8
- assetRepairOptions?: RepairAndBackupOptions;
9
- }
10
- export type RepairGateStatus = "ok" | "repair_required";
11
- export interface RepairSummary {
12
- status: RepairGateStatus;
13
- repairedEvidenceIndexRows: number;
14
- repairNotes: string[];
15
- assetRepair?: Awaited<ReturnType<ReturnType<typeof createRepairAndBackupService>["runStartupRepair"]>>;
16
- }
17
- export declare function repairStateIndexes(state: StateDatabase, options: RepairStateIndexesOptions): Promise<RepairSummary>;
1
+ import type { StateDatabase } from "../db/index.js";
2
+ import { createRepairAndBackupService, type RepairAndBackupOptions } from "../services/repair-and-backup.js";
3
+ export interface RepairStateIndexesOptions {
4
+ startupGate?: boolean;
5
+ workspaceRoot: string;
6
+ /** When true, also runs asset registry repair + backup (existing repair service) */
7
+ reconcileAssets?: boolean;
8
+ assetRepairOptions?: RepairAndBackupOptions;
9
+ }
10
+ export type RepairGateStatus = "ok" | "repair_required";
11
+ export interface RepairSummary {
12
+ status: RepairGateStatus;
13
+ repairedEvidenceIndexRows: number;
14
+ repairNotes: string[];
15
+ assetRepair?: Awaited<ReturnType<ReturnType<typeof createRepairAndBackupService>["runStartupRepair"]>>;
16
+ }
17
+ export declare function repairStateIndexes(state: StateDatabase, options: RepairStateIndexesOptions): Promise<RepairSummary>;
@@ -1,71 +1,71 @@
1
- /**
2
- * Startup repair gate for state indexes (T4.1.3) — reconciles life evidence filesystem vs SQLite index.
3
- *
4
- * Core logic: scan `.second-nature/evidence/*.json`; on startupGate, corrupt JSON fails closed with repair_required;
5
- * otherwise backfill missing `life_evidence_index` rows from parsed artifacts.
6
- *
7
- * Test coverage: tests/unit/storage/repair-gate.test.ts
8
- */
9
- import fs from "node:fs";
10
- import path from "node:path";
11
- import { eq } from "drizzle-orm";
12
- import { lifeEvidenceIndex } from "../db/schema/life-evidence-index.js";
13
- import { createRepairAndBackupService, } from "../services/repair-and-backup.js";
14
- export async function repairStateIndexes(state, options) {
15
- const notes = [];
16
- let repaired = 0;
17
- const evidenceDir = path.join(options.workspaceRoot, ".second-nature", "evidence");
18
- if (!fs.existsSync(evidenceDir)) {
19
- notes.push("no_evidence_dir");
20
- }
21
- else {
22
- const entries = fs.readdirSync(evidenceDir);
23
- for (const name of entries) {
24
- if (!name.endsWith(".json") || name.startsWith(".")) {
25
- continue;
26
- }
27
- const abs = path.join(evidenceDir, name);
28
- let parsed;
29
- try {
30
- parsed = JSON.parse(fs.readFileSync(abs, "utf-8"));
31
- }
32
- catch {
33
- if (options.startupGate) {
34
- return {
35
- status: "repair_required",
36
- repairedEvidenceIndexRows: repaired,
37
- repairNotes: [...notes, `corrupt_evidence_json:${name}`],
38
- };
39
- }
40
- notes.push(`skip_corrupt:${name}`);
41
- continue;
42
- }
43
- const existing = await state.db.select().from(lifeEvidenceIndex).where(eq(lifeEvidenceIndex.id, parsed.id)).limit(1);
44
- if (existing.length === 0) {
45
- await state.db.insert(lifeEvidenceIndex).values({
46
- id: parsed.id,
47
- timestamp: parsed.timestamp,
48
- evidenceType: parsed.evidenceType,
49
- sensitivity: parsed.sensitivity,
50
- producer: parsed.producer,
51
- artifactPath: path.join(".second-nature", "evidence", `${parsed.id}.json`).replace(/\\/g, "/"),
52
- platformId: parsed.platformId ?? null,
53
- sourceRefsJson: JSON.stringify(parsed.sourceRefs),
54
- });
55
- repaired += 1;
56
- notes.push(`reindexed:${parsed.id}`);
57
- }
58
- }
59
- }
60
- let assetRepair;
61
- if (options.reconcileAssets) {
62
- const svc = createRepairAndBackupService(state);
63
- assetRepair = await svc.runStartupRepair(options.assetRepairOptions ?? {});
64
- }
65
- return {
66
- status: "ok",
67
- repairedEvidenceIndexRows: repaired,
68
- repairNotes: notes,
69
- assetRepair,
70
- };
71
- }
1
+ /**
2
+ * Startup repair gate for state indexes (T4.1.3) — reconciles life evidence filesystem vs SQLite index.
3
+ *
4
+ * Core logic: scan `.second-nature/evidence/*.json`; on startupGate, corrupt JSON fails closed with repair_required;
5
+ * otherwise backfill missing `life_evidence_index` rows from parsed artifacts.
6
+ *
7
+ * Test coverage: tests/unit/storage/repair-gate.test.ts
8
+ */
9
+ import fs from "node:fs";
10
+ import path from "node:path";
11
+ import { eq } from "drizzle-orm";
12
+ import { lifeEvidenceIndex } from "../db/schema/life-evidence-index.js";
13
+ import { createRepairAndBackupService, } from "../services/repair-and-backup.js";
14
+ export async function repairStateIndexes(state, options) {
15
+ const notes = [];
16
+ let repaired = 0;
17
+ const evidenceDir = path.join(options.workspaceRoot, ".second-nature", "evidence");
18
+ if (!fs.existsSync(evidenceDir)) {
19
+ notes.push("no_evidence_dir");
20
+ }
21
+ else {
22
+ const entries = fs.readdirSync(evidenceDir);
23
+ for (const name of entries) {
24
+ if (!name.endsWith(".json") || name.startsWith(".")) {
25
+ continue;
26
+ }
27
+ const abs = path.join(evidenceDir, name);
28
+ let parsed;
29
+ try {
30
+ parsed = JSON.parse(fs.readFileSync(abs, "utf-8"));
31
+ }
32
+ catch {
33
+ if (options.startupGate) {
34
+ return {
35
+ status: "repair_required",
36
+ repairedEvidenceIndexRows: repaired,
37
+ repairNotes: [...notes, `corrupt_evidence_json:${name}`],
38
+ };
39
+ }
40
+ notes.push(`skip_corrupt:${name}`);
41
+ continue;
42
+ }
43
+ const existing = await state.db.select().from(lifeEvidenceIndex).where(eq(lifeEvidenceIndex.id, parsed.id)).limit(1);
44
+ if (existing.length === 0) {
45
+ await state.db.insert(lifeEvidenceIndex).values({
46
+ id: parsed.id,
47
+ timestamp: parsed.timestamp,
48
+ evidenceType: parsed.evidenceType,
49
+ sensitivity: parsed.sensitivity,
50
+ producer: parsed.producer,
51
+ artifactPath: path.join(".second-nature", "evidence", `${parsed.id}.json`).replace(/\\/g, "/"),
52
+ platformId: parsed.platformId ?? null,
53
+ sourceRefsJson: JSON.stringify(parsed.sourceRefs),
54
+ });
55
+ repaired += 1;
56
+ notes.push(`reindexed:${parsed.id}`);
57
+ }
58
+ }
59
+ }
60
+ let assetRepair;
61
+ if (options.reconcileAssets) {
62
+ const svc = createRepairAndBackupService(state);
63
+ assetRepair = await svc.runStartupRepair(options.assetRepairOptions ?? {});
64
+ }
65
+ return {
66
+ status: "ok",
67
+ repairedEvidenceIndexRows: repaired,
68
+ repairNotes: notes,
69
+ assetRepair,
70
+ };
71
+ }
@@ -1,38 +1,38 @@
1
- import { probeNativeSqliteLoad } from "./native-sqlite-probe.js";
2
- export interface StorageModeSmokeSemantics {
3
- sqlJs: {
4
- walAssumed: false;
5
- journalConcurrencyNotes: string;
6
- backupNotes: string;
7
- repairNotes: string;
8
- };
9
- nativeSqliteWhenAvailable: {
10
- journalConcurrencyNotes: string;
11
- backupNotes: string;
12
- };
13
- }
14
- export interface StorageModeSmokeRepairFixtureResult {
15
- ran: boolean;
16
- workspaceRoot?: string;
17
- repairStatus?: "ok" | "repair_required";
18
- repairedEvidenceIndexRows?: number;
19
- repairNotes?: string[];
20
- }
21
- export interface StorageModeSmokeReport {
22
- generatedAt: string;
23
- /** Implementation backing `createStateDatabase` today — wasm sql.js, not native WAL */
24
- runtimeIndexDriver: "sql_js";
25
- nativeSqliteProbe: ReturnType<typeof probeNativeSqliteLoad> & {
26
- /** Current code path does not use native driver even when load succeeds */
27
- runtimeUsesNativeDriver: false;
28
- };
29
- semantics: StorageModeSmokeSemantics;
30
- repairFromArtifactsFixture?: StorageModeSmokeRepairFixtureResult;
31
- }
32
- export interface RunStorageModeSmokeOptions {
33
- /** Required when runRepairFixture is true — temp dir created if omitted */
34
- workspaceRoot?: string;
35
- /** Run artifact→index backfill smoke (sql.js path); uses temp workspace when workspaceRoot unset */
36
- runRepairFixture?: boolean;
37
- }
38
- export declare function runStorageModeSmoke(options?: RunStorageModeSmokeOptions): Promise<StorageModeSmokeReport>;
1
+ import { probeNativeSqliteLoad } from "./native-sqlite-probe.js";
2
+ export interface StorageModeSmokeSemantics {
3
+ sqlJs: {
4
+ walAssumed: false;
5
+ journalConcurrencyNotes: string;
6
+ backupNotes: string;
7
+ repairNotes: string;
8
+ };
9
+ nativeSqliteWhenAvailable: {
10
+ journalConcurrencyNotes: string;
11
+ backupNotes: string;
12
+ };
13
+ }
14
+ export interface StorageModeSmokeRepairFixtureResult {
15
+ ran: boolean;
16
+ workspaceRoot?: string;
17
+ repairStatus?: "ok" | "repair_required";
18
+ repairedEvidenceIndexRows?: number;
19
+ repairNotes?: string[];
20
+ }
21
+ export interface StorageModeSmokeReport {
22
+ generatedAt: string;
23
+ /** Implementation backing `createStateDatabase` today — wasm sql.js, not native WAL */
24
+ runtimeIndexDriver: "sql_js";
25
+ nativeSqliteProbe: ReturnType<typeof probeNativeSqliteLoad> & {
26
+ /** Current code path does not use native driver even when load succeeds */
27
+ runtimeUsesNativeDriver: false;
28
+ };
29
+ semantics: StorageModeSmokeSemantics;
30
+ repairFromArtifactsFixture?: StorageModeSmokeRepairFixtureResult;
31
+ }
32
+ export interface RunStorageModeSmokeOptions {
33
+ /** Required when runRepairFixture is true — temp dir created if omitted */
34
+ workspaceRoot?: string;
35
+ /** Run artifact→index backfill smoke (sql.js path); uses temp workspace when workspaceRoot unset */
36
+ runRepairFixture?: boolean;
37
+ }
38
+ export declare function runStorageModeSmoke(options?: RunStorageModeSmokeOptions): Promise<StorageModeSmokeReport>;