@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,150 @@
1
+ /**
2
+ * Minimal loadUserInterestSnapshot: anchor + curated presence, no fabricated preferences (T4.2.2).
3
+ *
4
+ * Core logic: USER.md / MEMORY.md / memory/curated/*.md drive signals; otherwise insufficient.
5
+ * Boundaries: never invent topics; staleness insufficient when anchors missing and no curated signals.
6
+ */
7
+ import * as crypto from "node:crypto";
8
+ import * as fs from "fs/promises";
9
+ import * as path from "node:path";
10
+ import { fileExists, readText } from "../memory/workspace/paths.js";
11
+ const MIN_MEANINGFUL_ANCHOR_CHARS = 24;
12
+ const STALE_MS = 30 * 24 * 60 * 60 * 1000;
13
+ const INSUFFICIENT_CONFIDENCE_THRESHOLD = 0.35;
14
+ function anchorRef(asset, workspaceRoot) {
15
+ return {
16
+ id: `anchor:${asset}`,
17
+ kind: "user_anchor",
18
+ uri: path.join(workspaceRoot, asset),
19
+ observedAt: new Date().toISOString(),
20
+ };
21
+ }
22
+ async function newestMtime(paths) {
23
+ let max = 0;
24
+ for (const p of paths) {
25
+ try {
26
+ const st = await fs.stat(p);
27
+ max = Math.max(max, st.mtimeMs);
28
+ }
29
+ catch {
30
+ /* missing */
31
+ }
32
+ }
33
+ return max;
34
+ }
35
+ async function listCuratedSignalFiles(workspaceRoot) {
36
+ const dir = path.join(workspaceRoot, "memory", "curated");
37
+ if (!(await fileExists(dir)))
38
+ return [];
39
+ const entries = await fs.readdir(dir, { withFileTypes: true });
40
+ return entries.filter((e) => e.isFile() && e.name.endsWith(".md")).map((e) => path.join(dir, e.name));
41
+ }
42
+ export async function loadUserInterestSnapshot(workspaceRoot) {
43
+ const generatedAt = new Date().toISOString();
44
+ const userPath = path.join(workspaceRoot, "USER.md");
45
+ const memoryPath = path.join(workspaceRoot, "MEMORY.md");
46
+ const hasUser = await fileExists(userPath);
47
+ const hasMemory = await fileExists(memoryPath);
48
+ const userText = hasUser ? (await readText(userPath)).trim() : "";
49
+ const memoryText = hasMemory ? (await readText(memoryPath)).trim() : "";
50
+ const curatedFiles = await listCuratedSignalFiles(workspaceRoot);
51
+ const curatedNonEmpty = [];
52
+ for (const fp of curatedFiles) {
53
+ const body = (await readText(fp)).trim();
54
+ if (body.length >= MIN_MEANINGFUL_ANCHOR_CHARS)
55
+ curatedNonEmpty.push(fp);
56
+ }
57
+ const userOk = hasUser && userText.length >= MIN_MEANINGFUL_ANCHOR_CHARS;
58
+ const memoryOk = hasMemory && memoryText.length >= MIN_MEANINGFUL_ANCHOR_CHARS;
59
+ if (!userOk && !memoryOk && curatedNonEmpty.length === 0) {
60
+ return {
61
+ snapshotId: crypto.randomUUID(),
62
+ generatedAt,
63
+ signals: [],
64
+ sourceRefs: [],
65
+ confidence: 0,
66
+ staleness: "insufficient",
67
+ missingReasons: ["missing_user_interest_model"],
68
+ };
69
+ }
70
+ const signals = [];
71
+ const allRefs = [];
72
+ if (userOk) {
73
+ const ref = anchorRef("USER.md", workspaceRoot);
74
+ allRefs.push(ref);
75
+ signals.push({
76
+ id: `interest:user:${crypto.randomUUID()}`,
77
+ topic: "user_anchor_profile",
78
+ affinity: "unknown",
79
+ reason: "derived_from_USER.md_anchor",
80
+ confidence: 0.55,
81
+ sourceRefs: [ref],
82
+ updatedAt: generatedAt,
83
+ });
84
+ }
85
+ if (memoryOk) {
86
+ const ref = anchorRef("MEMORY.md", workspaceRoot);
87
+ allRefs.push(ref);
88
+ signals.push({
89
+ id: `interest:memory:${crypto.randomUUID()}`,
90
+ topic: "relational_memory_anchor",
91
+ affinity: "watching",
92
+ reason: "derived_from_MEMORY.md_anchor",
93
+ confidence: 0.52,
94
+ sourceRefs: [ref],
95
+ updatedAt: generatedAt,
96
+ });
97
+ }
98
+ for (const fp of curatedNonEmpty) {
99
+ const ref = {
100
+ id: `curated:${path.basename(fp, ".md")}`,
101
+ kind: "workspace_artifact",
102
+ uri: fp,
103
+ observedAt: generatedAt,
104
+ };
105
+ allRefs.push(ref);
106
+ signals.push({
107
+ id: `interest:curated:${crypto.randomUUID()}`,
108
+ topic: `curated:${path.basename(fp, ".md")}`,
109
+ affinity: "positive",
110
+ reason: "derived_from_curated_memory_file",
111
+ confidence: 0.48,
112
+ sourceRefs: [ref],
113
+ updatedAt: generatedAt,
114
+ });
115
+ }
116
+ if (signals.length === 0) {
117
+ return {
118
+ snapshotId: crypto.randomUUID(),
119
+ generatedAt,
120
+ signals: [],
121
+ sourceRefs: [],
122
+ confidence: 0,
123
+ staleness: "insufficient",
124
+ missingReasons: ["missing_user_interest_model"],
125
+ };
126
+ }
127
+ const confidence = signals.reduce((s, x) => s + x.confidence, 0) / signals.length;
128
+ if (confidence < INSUFFICIENT_CONFIDENCE_THRESHOLD) {
129
+ return {
130
+ snapshotId: crypto.randomUUID(),
131
+ generatedAt,
132
+ signals: [],
133
+ sourceRefs: [],
134
+ confidence: 0,
135
+ staleness: "insufficient",
136
+ missingReasons: ["missing_user_interest_model"],
137
+ };
138
+ }
139
+ const mtimes = await newestMtime([hasUser ? userPath : "", hasMemory ? memoryPath : "", ...curatedNonEmpty].filter(Boolean));
140
+ const staleness = mtimes > 0 && Date.now() - mtimes > STALE_MS ? "stale" : "fresh";
141
+ const uniqueRefs = [...new Map(allRefs.map((r) => [r.uri, r])).values()];
142
+ return {
143
+ snapshotId: crypto.randomUUID(),
144
+ generatedAt,
145
+ signals,
146
+ sourceRefs: uniqueRefs,
147
+ confidence,
148
+ staleness,
149
+ };
150
+ }
@@ -0,0 +1,25 @@
1
+ /**
2
+ * User interest read model (T4.2.2 / state-system v5 subset).
3
+ *
4
+ * Test coverage: tests/unit/storage/user-interest-snapshot.test.ts
5
+ */
6
+ import type { SourceRef } from "../life-evidence/types.js";
7
+ export type UserInterestStaleness = "fresh" | "stale" | "insufficient";
8
+ export interface UserInterestSignal {
9
+ id: string;
10
+ topic: string;
11
+ affinity: "positive" | "negative" | "watching" | "unknown";
12
+ reason: string;
13
+ confidence: number;
14
+ sourceRefs: SourceRef[];
15
+ updatedAt: string;
16
+ }
17
+ export interface UserInterestSnapshot {
18
+ snapshotId: string;
19
+ generatedAt: string;
20
+ signals: UserInterestSignal[];
21
+ sourceRefs: SourceRef[];
22
+ confidence: number;
23
+ staleness: UserInterestStaleness;
24
+ missingReasons?: string[];
25
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,78 @@
1
+ /**
2
+ * T1.1.4 — Lazy workspace full-ops bridge (OpenClaw plugin).
3
+ *
4
+ * Core logic: dynamic-import packaged `runtime/` + open workspace `data/*.db` with the same
5
+ * `createCliRuntimeDeps` + `createOpsRouter` + `createCliCommands` path as the workspace CLI.
6
+ * `process.chdir(workspaceRoot)` during dispatch so `memory/workspace` paths match CLI cwd semantics.
7
+ *
8
+ * Boundaries: no static imports from `./runtime/*` (sql.js top-level await stays out of register() graph).
9
+ *
10
+ * Plan B (CH-11-01): if the host VM blocks dynamic import + sql.js, fall back to a subprocess invoking
11
+ * the workspace `second-nature` CLI — not implemented here; bridge failures surface as explicit errors.
12
+ *
13
+ * Test coverage: tests/integration/cli/plugin-workspace-ops-bridge.test.ts
14
+ */
15
+ import fs from "node:fs";
16
+ import path from "node:path";
17
+ import { fileURLToPath } from "node:url";
18
+ const PLUGIN_PACKAGE_ROOT = path.dirname(fileURLToPath(import.meta.url));
19
+ export async function openWorkspaceOpsBridge(workspaceRoot) {
20
+ const resolvedRoot = path.resolve(workspaceRoot);
21
+ try {
22
+ // Packaged `plugin/runtime` is emitted JS without sibling `.d.ts` in this repo layout.
23
+ // @ts-expect-error TS7016 — intentional dynamic import of artifact bundle
24
+ const cliIndex = (await import("./runtime/cli/index.js"));
25
+ const commandsMod = (await import("./runtime/cli/commands/index.js"));
26
+ const storageDb = (await import("./runtime/storage/db/index.js"));
27
+ const obsDb = (await import("./runtime/observability/db/index.js"));
28
+ const boundary = (await import("./runtime/cli/runtime/runtime-artifact-boundary.js"));
29
+ const dataDir = path.join(resolvedRoot, "data");
30
+ fs.mkdirSync(dataDir, { recursive: true });
31
+ const statePath = path.join(dataDir, "state.db");
32
+ const obsPath = path.join(dataDir, "observability.db");
33
+ const stateDb = storageDb.createStateDatabase(statePath);
34
+ const observabilityDb = obsDb.createObservabilityDatabase(obsPath);
35
+ const deps = cliIndex.createCliRuntimeDeps({ stateDb, observabilityDb });
36
+ const runtimeResolved = boundary.resolvePackagedRuntime(PLUGIN_PACKAGE_ROOT);
37
+ const opsRouter = cliIndex.createOpsRouter({
38
+ runtimeAvailable: runtimeResolved.ok,
39
+ readModels: deps.readModels,
40
+ });
41
+ const commands = commandsMod.createCliCommands({
42
+ readModels: deps.readModels,
43
+ actionBridge: deps.actionBridge,
44
+ opsRouter,
45
+ });
46
+ const dispatch = async (command, input) => {
47
+ const def = commands.find((c) => c.name === command);
48
+ if (!def) {
49
+ return {
50
+ ok: false,
51
+ error: { code: "unknown_command", message: `Unknown Second Nature command: ${command}` },
52
+ };
53
+ }
54
+ const prevCwd = process.cwd();
55
+ try {
56
+ process.chdir(resolvedRoot);
57
+ return await def.execute(input);
58
+ }
59
+ finally {
60
+ process.chdir(prevCwd);
61
+ }
62
+ };
63
+ const close = () => {
64
+ cliIndex.closeCliRuntimeDeps(deps);
65
+ };
66
+ return { ok: true, workspaceRoot: resolvedRoot, dispatch, close };
67
+ }
68
+ catch (error) {
69
+ return {
70
+ ok: false,
71
+ error: {
72
+ code: "WORKSPACE_FULL_OPS_BRIDGE_FAILED",
73
+ message: error instanceof Error ? error.message : String(error),
74
+ nextStep: "Confirm the packaged plugin includes plugin/runtime and that the host allows dynamic import of sql.js. If the VM forbids it, use a subprocess workspace CLI (Plan B) or run outside the sandbox.",
75
+ },
76
+ };
77
+ }
78
+ }