@haaaiawd/second-nature 0.1.1 → 0.1.2

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 (200) hide show
  1. package/index.ts +64 -21
  2. package/package.json +8 -2
  3. package/runtime/cli/action-bridge.d.ts +11 -0
  4. package/runtime/cli/action-bridge.js +27 -0
  5. package/runtime/cli/commands/credential.d.ts +2 -0
  6. package/runtime/cli/commands/credential.js +40 -0
  7. package/runtime/cli/commands/index.d.ts +12 -0
  8. package/runtime/cli/commands/index.js +138 -0
  9. package/runtime/cli/commands/policy.d.ts +12 -0
  10. package/runtime/cli/commands/policy.js +43 -0
  11. package/runtime/cli/explain/format-explanation.d.ts +10 -0
  12. package/runtime/cli/explain/format-explanation.js +10 -0
  13. package/runtime/cli/explain/resolve-subject.d.ts +2 -0
  14. package/runtime/cli/explain/resolve-subject.js +26 -0
  15. package/runtime/cli/index.d.ts +25 -0
  16. package/runtime/cli/index.js +36 -0
  17. package/runtime/cli/read-models/index.d.ts +20 -0
  18. package/runtime/cli/read-models/index.js +161 -0
  19. package/runtime/cli/read-models/types.d.ts +75 -0
  20. package/runtime/cli/read-models/types.js +1 -0
  21. package/runtime/connectors/agent-network/evomap/adapter.d.ts +23 -0
  22. package/runtime/connectors/agent-network/evomap/adapter.js +69 -0
  23. package/runtime/connectors/agent-network/evomap/index.d.ts +2 -0
  24. package/runtime/connectors/agent-network/evomap/index.js +2 -0
  25. package/runtime/connectors/agent-network/evomap/manifest.d.ts +2 -0
  26. package/runtime/connectors/agent-network/evomap/manifest.js +7 -0
  27. package/runtime/connectors/base/channel-health.d.ts +29 -0
  28. package/runtime/connectors/base/channel-health.js +23 -0
  29. package/runtime/connectors/base/contract.d.ts +81 -0
  30. package/runtime/connectors/base/contract.js +71 -0
  31. package/runtime/connectors/base/failure-taxonomy.d.ts +13 -0
  32. package/runtime/connectors/base/failure-taxonomy.js +105 -0
  33. package/runtime/connectors/base/index.d.ts +6 -0
  34. package/runtime/connectors/base/index.js +6 -0
  35. package/runtime/connectors/base/manifest.d.ts +11 -0
  36. package/runtime/connectors/base/manifest.js +36 -0
  37. package/runtime/connectors/base/policy-layer.d.ts +27 -0
  38. package/runtime/connectors/base/policy-layer.js +213 -0
  39. package/runtime/connectors/base/route-planner.d.ts +10 -0
  40. package/runtime/connectors/base/route-planner.js +98 -0
  41. package/runtime/connectors/index.d.ts +4 -0
  42. package/runtime/connectors/index.js +4 -0
  43. package/runtime/connectors/social-community/instreet/adapter.d.ts +32 -0
  44. package/runtime/connectors/social-community/instreet/adapter.js +79 -0
  45. package/runtime/connectors/social-community/instreet/index.d.ts +2 -0
  46. package/runtime/connectors/social-community/instreet/index.js +2 -0
  47. package/runtime/connectors/social-community/instreet/manifest.d.ts +2 -0
  48. package/runtime/connectors/social-community/instreet/manifest.js +7 -0
  49. package/runtime/connectors/social-community/moltbook/adapter.d.ts +15 -0
  50. package/runtime/connectors/social-community/moltbook/adapter.js +48 -0
  51. package/runtime/connectors/social-community/moltbook/index.d.ts +2 -0
  52. package/runtime/connectors/social-community/moltbook/index.js +2 -0
  53. package/runtime/connectors/social-community/moltbook/manifest.d.ts +7 -0
  54. package/runtime/connectors/social-community/moltbook/manifest.js +12 -0
  55. package/runtime/core/second-nature/guidance/apply-guidance.d.ts +10 -0
  56. package/runtime/core/second-nature/guidance/apply-guidance.js +10 -0
  57. package/runtime/core/second-nature/guidance/request-guidance.d.ts +18 -0
  58. package/runtime/core/second-nature/guidance/request-guidance.js +22 -0
  59. package/runtime/core/second-nature/index.d.ts +14 -0
  60. package/runtime/core/second-nature/index.js +14 -0
  61. package/runtime/core/second-nature/orchestrator/effect-dispatcher.d.ts +100 -0
  62. package/runtime/core/second-nature/orchestrator/effect-dispatcher.js +139 -0
  63. package/runtime/core/second-nature/orchestrator/guard-layer.d.ts +2 -0
  64. package/runtime/core/second-nature/orchestrator/guard-layer.js +54 -0
  65. package/runtime/core/second-nature/orchestrator/intent-planner.d.ts +3 -0
  66. package/runtime/core/second-nature/orchestrator/intent-planner.js +92 -0
  67. package/runtime/core/second-nature/orchestrator/lease-manager.d.ts +14 -0
  68. package/runtime/core/second-nature/orchestrator/lease-manager.js +58 -0
  69. package/runtime/core/second-nature/orchestrator/resume-from-checkpoint.d.ts +32 -0
  70. package/runtime/core/second-nature/orchestrator/resume-from-checkpoint.js +23 -0
  71. package/runtime/core/second-nature/outreach/build-message.d.ts +16 -0
  72. package/runtime/core/second-nature/outreach/build-message.js +27 -0
  73. package/runtime/core/second-nature/outreach/evaluate-outreach.d.ts +13 -0
  74. package/runtime/core/second-nature/outreach/evaluate-outreach.js +41 -0
  75. package/runtime/core/second-nature/quiet/quiet-pipeline.d.ts +34 -0
  76. package/runtime/core/second-nature/quiet/quiet-pipeline.js +35 -0
  77. package/runtime/core/second-nature/reflection/run-narrative-reflection.d.ts +39 -0
  78. package/runtime/core/second-nature/reflection/run-narrative-reflection.js +29 -0
  79. package/runtime/core/second-nature/rhythm/rhythm-policy.d.ts +18 -0
  80. package/runtime/core/second-nature/rhythm/rhythm-policy.js +24 -0
  81. package/runtime/core/second-nature/rhythm/select-window.d.ts +3 -0
  82. package/runtime/core/second-nature/rhythm/select-window.js +50 -0
  83. package/runtime/core/second-nature/runtime/lifecycle-service.d.ts +26 -0
  84. package/runtime/core/second-nature/runtime/lifecycle-service.js +38 -0
  85. package/runtime/core/second-nature/runtime/service-entry.d.ts +36 -0
  86. package/runtime/core/second-nature/runtime/service-entry.js +44 -0
  87. package/runtime/core/second-nature/types.d.ts +37 -0
  88. package/runtime/core/second-nature/types.js +1 -0
  89. package/runtime/guidance/contracts.d.ts +48 -0
  90. package/runtime/guidance/contracts.js +54 -0
  91. package/runtime/guidance/fallback.d.ts +2 -0
  92. package/runtime/guidance/fallback.js +17 -0
  93. package/runtime/guidance/guidance-assembler.d.ts +5 -0
  94. package/runtime/guidance/guidance-assembler.js +62 -0
  95. package/runtime/guidance/index.d.ts +8 -0
  96. package/runtime/guidance/index.js +8 -0
  97. package/runtime/guidance/output-guard.d.ts +10 -0
  98. package/runtime/guidance/output-guard.js +29 -0
  99. package/runtime/guidance/persona-selection.d.ts +11 -0
  100. package/runtime/guidance/persona-selection.js +90 -0
  101. package/runtime/guidance/review-workflow.d.ts +15 -0
  102. package/runtime/guidance/review-workflow.js +60 -0
  103. package/runtime/guidance/template-registry.d.ts +3 -0
  104. package/runtime/guidance/template-registry.js +45 -0
  105. package/runtime/guidance/types.d.ts +72 -0
  106. package/runtime/guidance/types.js +1 -0
  107. package/runtime/observability/db/index.d.ts +10 -0
  108. package/runtime/observability/db/index.js +17 -0
  109. package/runtime/observability/db/schema/index.d.ts +946 -0
  110. package/runtime/observability/db/schema/index.js +70 -0
  111. package/runtime/observability/index.d.ts +12 -0
  112. package/runtime/observability/index.js +11 -0
  113. package/runtime/observability/projections/guidance-audit.d.ts +16 -0
  114. package/runtime/observability/projections/guidance-audit.js +35 -0
  115. package/runtime/observability/projections/outreach-quality-audit.d.ts +15 -0
  116. package/runtime/observability/projections/outreach-quality-audit.js +9 -0
  117. package/runtime/observability/projections/reflection-audit.d.ts +17 -0
  118. package/runtime/observability/projections/reflection-audit.js +9 -0
  119. package/runtime/observability/query/compose-evidence.d.ts +56 -0
  120. package/runtime/observability/query/compose-evidence.js +43 -0
  121. package/runtime/observability/query/evidence-query-engine.d.ts +17 -0
  122. package/runtime/observability/query/evidence-query-engine.js +166 -0
  123. package/runtime/observability/redaction/manifest.d.ts +18 -0
  124. package/runtime/observability/redaction/manifest.js +109 -0
  125. package/runtime/observability/redaction/policy.d.ts +19 -0
  126. package/runtime/observability/redaction/policy.js +71 -0
  127. package/runtime/observability/services/decision-ledger.d.ts +33 -0
  128. package/runtime/observability/services/decision-ledger.js +115 -0
  129. package/runtime/observability/services/execution-telemetry.d.ts +32 -0
  130. package/runtime/observability/services/execution-telemetry.js +126 -0
  131. package/runtime/observability/services/governance-audit.d.ts +27 -0
  132. package/runtime/observability/services/governance-audit.js +139 -0
  133. package/runtime/observability/services/redaction-store.d.ts +3 -0
  134. package/runtime/observability/services/redaction-store.js +20 -0
  135. package/runtime/shared/types/continuity.d.ts +69 -0
  136. package/runtime/shared/types/continuity.js +1 -0
  137. package/runtime/shared/types/credential.d.ts +22 -0
  138. package/runtime/shared/types/credential.js +1 -0
  139. package/runtime/shared/types/index.d.ts +3 -0
  140. package/runtime/shared/types/index.js +3 -0
  141. package/runtime/shared/types/outreach.d.ts +19 -0
  142. package/runtime/shared/types/outreach.js +1 -0
  143. package/runtime/storage/bootstrap/repair.d.ts +3 -0
  144. package/runtime/storage/bootstrap/repair.js +5 -0
  145. package/runtime/storage/db/index.d.ts +10 -0
  146. package/runtime/storage/db/index.js +17 -0
  147. package/runtime/storage/db/schema/assets.d.ts +140 -0
  148. package/runtime/storage/db/schema/assets.js +10 -0
  149. package/runtime/storage/db/schema/credentials.d.ts +178 -0
  150. package/runtime/storage/db/schema/credentials.js +12 -0
  151. package/runtime/storage/db/schema/index.d.ts +6 -0
  152. package/runtime/storage/db/schema/index.js +6 -0
  153. package/runtime/storage/db/schema/intent-commits.d.ts +161 -0
  154. package/runtime/storage/db/schema/intent-commits.js +11 -0
  155. package/runtime/storage/db/schema/policies.d.ts +81 -0
  156. package/runtime/storage/db/schema/policies.js +7 -0
  157. package/runtime/storage/db/schema/proposals.d.ts +216 -0
  158. package/runtime/storage/db/schema/proposals.js +14 -0
  159. package/runtime/storage/db/schema/provenance.d.ts +104 -0
  160. package/runtime/storage/db/schema/provenance.js +8 -0
  161. package/runtime/storage/index.d.ts +16 -0
  162. package/runtime/storage/index.js +16 -0
  163. package/runtime/storage/memory/workspace/paths.d.ts +62 -0
  164. package/runtime/storage/memory/workspace/paths.js +160 -0
  165. package/runtime/storage/memory/workspace/store.d.ts +26 -0
  166. package/runtime/storage/memory/workspace/store.js +153 -0
  167. package/runtime/storage/memory/workspace/types.d.ts +45 -0
  168. package/runtime/storage/memory/workspace/types.js +1 -0
  169. package/runtime/storage/repositories/asset-repository.d.ts +8 -0
  170. package/runtime/storage/repositories/asset-repository.js +19 -0
  171. package/runtime/storage/repositories/credential-repository.d.ts +8 -0
  172. package/runtime/storage/repositories/credential-repository.js +19 -0
  173. package/runtime/storage/repositories/index.d.ts +6 -0
  174. package/runtime/storage/repositories/index.js +6 -0
  175. package/runtime/storage/repositories/intent-commit-repository.d.ts +10 -0
  176. package/runtime/storage/repositories/intent-commit-repository.js +35 -0
  177. package/runtime/storage/repositories/policy-repository.d.ts +8 -0
  178. package/runtime/storage/repositories/policy-repository.js +19 -0
  179. package/runtime/storage/repositories/proposal-repository.d.ts +9 -0
  180. package/runtime/storage/repositories/proposal-repository.js +26 -0
  181. package/runtime/storage/repositories/provenance-repository.d.ts +20 -0
  182. package/runtime/storage/repositories/provenance-repository.js +41 -0
  183. package/runtime/storage/services/credential-vault.d.ts +8 -0
  184. package/runtime/storage/services/credential-vault.js +78 -0
  185. package/runtime/storage/services/daily-log-pipeline.d.ts +47 -0
  186. package/runtime/storage/services/daily-log-pipeline.js +86 -0
  187. package/runtime/storage/services/effect-commit-store.d.ts +11 -0
  188. package/runtime/storage/services/effect-commit-store.js +93 -0
  189. package/runtime/storage/services/governance-layer.d.ts +40 -0
  190. package/runtime/storage/services/governance-layer.js +103 -0
  191. package/runtime/storage/services/persona-candidate-loader.d.ts +5 -0
  192. package/runtime/storage/services/persona-candidate-loader.js +41 -0
  193. package/runtime/storage/services/provenance-service.d.ts +40 -0
  194. package/runtime/storage/services/provenance-service.js +43 -0
  195. package/runtime/storage/services/quiet-input-loader.d.ts +40 -0
  196. package/runtime/storage/services/quiet-input-loader.js +131 -0
  197. package/runtime/storage/services/repair-and-backup.d.ts +22 -0
  198. package/runtime/storage/services/repair-and-backup.js +73 -0
  199. package/runtime/storage/state-api.d.ts +46 -0
  200. package/runtime/storage/state-api.js +73 -0
package/index.ts CHANGED
@@ -12,10 +12,6 @@ interface RegisterApi {
12
12
  registerTool(tool: unknown, options?: unknown): void;
13
13
  }
14
14
 
15
- const lifecycleState = {
16
- registerCount: 0,
17
- };
18
-
19
15
  function createFallbackCommands(): Array<{
20
16
  name: string;
21
17
  description: string;
@@ -41,7 +37,7 @@ function resolveCommandRouterSafe(): {
41
37
  const require = createRequire(import.meta.url);
42
38
 
43
39
  try {
44
- const mod = require("../src/cli/index.js") as { createCommandRouter: () => { commands: any[]; resolve: (name: string) => any } };
40
+ const mod = require("./runtime/cli/index.js") as { createCommandRouter: () => { commands: any[]; resolve: (name: string) => any } };
45
41
  if (mod?.createCommandRouter) {
46
42
  return mod.createCommandRouter();
47
43
  }
@@ -58,30 +54,77 @@ function resolveCommandRouterSafe(): {
58
54
  };
59
55
  }
60
56
 
61
- const serviceShell = {
62
- id: "second-nature-runtime",
63
- start() {
64
- return;
65
- },
66
- };
57
+ function createRuntimeService(): { id: string; start: () => unknown } {
58
+ const require = createRequire(import.meta.url);
59
+
60
+ try {
61
+ const runtimeMod = require("./runtime/core/second-nature/runtime/service-entry.js") as {
62
+ startRuntimeService: (ctx?: Record<string, unknown>) => { ready: boolean; version: string; close: () => void };
63
+ };
64
+
65
+ if (runtimeMod?.startRuntimeService) {
66
+ const handle = runtimeMod.startRuntimeService();
67
+ return {
68
+ id: "second-nature-runtime",
69
+ start() {
70
+ return { ready: handle.ready, version: handle.version };
71
+ },
72
+ };
73
+ }
74
+ } catch {
75
+ // fall through to minimal service shell
76
+ }
77
+
78
+ return {
79
+ id: "second-nature-runtime",
80
+ start() {
81
+ return { ready: true, version: "0.1.0-minimal" };
82
+ },
83
+ };
84
+ }
85
+
86
+ function createLifecycleService(): { id: string; start: () => unknown } {
87
+ const require = createRequire(import.meta.url);
88
+
89
+ try {
90
+ const lifecycleMod = require("./runtime/core/second-nature/runtime/lifecycle-service.js") as {
91
+ recordRegistration: () => { registerCount: number; phase: string; lastChangedAt: number };
92
+ };
93
+
94
+ if (lifecycleMod?.recordRegistration) {
95
+ return {
96
+ id: "second-nature-lifecycle",
97
+ start() {
98
+ const state = lifecycleMod.recordRegistration();
99
+ return { phase: state.phase, registerCount: state.registerCount };
100
+ },
101
+ };
102
+ }
103
+ } catch {
104
+ // fall through to minimal lifecycle shell
105
+ }
106
+
107
+ let registerCount = 0;
108
+ return {
109
+ id: "second-nature-lifecycle",
110
+ start() {
111
+ registerCount += 1;
112
+ return { phase: registerCount === 1 ? "loading" : "reloading", registerCount };
113
+ },
114
+ };
115
+ }
67
116
 
68
117
  export default {
69
118
  id: "second-nature",
70
119
  name: "Second Nature",
71
120
  description: "Registers command/tool/service surface with load-reload lifecycle semantics.",
72
121
  register(api: RegisterApi) {
73
- lifecycleState.registerCount += 1;
74
- const lifecycleEvent = lifecycleState.registerCount === 1 ? "load" : "reload";
75
122
  const router = resolveCommandRouterSafe();
123
+ const runtimeService = createRuntimeService();
124
+ const lifecycleService = createLifecycleService();
76
125
 
77
- api.registerService(serviceShell);
78
-
79
- api.registerService({
80
- id: "second-nature-lifecycle",
81
- start() {
82
- return;
83
- },
84
- });
126
+ api.registerService(runtimeService);
127
+ api.registerService(lifecycleService);
85
128
 
86
129
  api.registerCli(
87
130
  ({ program }) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@haaaiawd/second-nature",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "OpenClaw native plugin for long-running agent continuity, Quiet memory curation, and explainable operator flows.",
5
5
  "keywords": [
6
6
  "openclaw",
@@ -17,7 +17,8 @@
17
17
  "main": "./index.ts",
18
18
  "files": [
19
19
  "index.ts",
20
- "openclaw.plugin.json"
20
+ "openclaw.plugin.json",
21
+ "runtime/"
21
22
  ],
22
23
  "publishConfig": {
23
24
  "access": "public"
@@ -27,5 +28,10 @@
27
28
  "extensions": [
28
29
  "./index.ts"
29
30
  ]
31
+ },
32
+ "dependencies": {
33
+ "better-sqlite3": "^11.10.0",
34
+ "drizzle-orm": "^0.44.4",
35
+ "zod": "^4.1.5"
30
36
  }
31
37
  }
@@ -0,0 +1,11 @@
1
+ import type { StateAPI } from "../storage/state-api.js";
2
+ export interface PolicyWriteInput {
3
+ platformId: string;
4
+ socialDailyLimit: number;
5
+ quietEnabled: boolean;
6
+ }
7
+ export interface ActionBridge {
8
+ savePolicy(input: PolicyWriteInput): Promise<void>;
9
+ verifyCredential(platformId: string, answer: string): Promise<void>;
10
+ }
11
+ export declare function createActionBridge(stateApi: StateAPI): ActionBridge;
@@ -0,0 +1,27 @@
1
+ export function createActionBridge(stateApi) {
2
+ return {
3
+ async savePolicy(input) {
4
+ await stateApi.write.savePolicy(input);
5
+ },
6
+ async verifyCredential(platformId, answer) {
7
+ const existing = await stateApi.credentials.loadCredentialContext(platformId);
8
+ if (!existing) {
9
+ throw new Error("credential_context_not_found");
10
+ }
11
+ const isPending = existing.status === "pending_verification";
12
+ if (!isPending) {
13
+ throw new Error("credential_not_pending_verification");
14
+ }
15
+ if (!answer.trim()) {
16
+ throw new Error("verification_answer_required");
17
+ }
18
+ await stateApi.credentials.saveCredentialContext({
19
+ ...existing,
20
+ status: "active",
21
+ verificationCode: answer,
22
+ encryptedValue: existing.encryptedValue,
23
+ updatedAt: new Date().toISOString(),
24
+ });
25
+ },
26
+ };
27
+ }
@@ -0,0 +1,2 @@
1
+ import type { ActionBridge } from "../action-bridge.js";
2
+ export declare function credentialVerify(bridge: ActionBridge, input?: Record<string, unknown>): Promise<Record<string, unknown>>;
@@ -0,0 +1,40 @@
1
+ export async function credentialVerify(bridge, input) {
2
+ const platformId = typeof input?.platformId === "string" ? input.platformId.trim() : "";
3
+ const answer = typeof input?.answer === "string" ? input.answer.trim() : "";
4
+ const requiredUserInput = [];
5
+ if (!platformId)
6
+ requiredUserInput.push("platform_id");
7
+ if (!answer)
8
+ requiredUserInput.push("verification_answer");
9
+ if (requiredUserInput.length > 0) {
10
+ return {
11
+ ok: false,
12
+ error: {
13
+ code: "MISSING_VERIFICATION_FIELDS",
14
+ message: "credential verify requires platform and answer",
15
+ requiredUserInput,
16
+ nextStep: "reinvoke_credential_verify_with_required_fields",
17
+ },
18
+ };
19
+ }
20
+ try {
21
+ await bridge.verifyCredential(platformId, answer);
22
+ return {
23
+ ok: true,
24
+ data: {
25
+ platformId,
26
+ verified: true,
27
+ },
28
+ };
29
+ }
30
+ catch (error) {
31
+ return {
32
+ ok: false,
33
+ error: {
34
+ code: "CREDENTIAL_VERIFY_FAILED",
35
+ message: String(error),
36
+ nextStep: "inspect_credential_status_then_retry_verify",
37
+ },
38
+ };
39
+ }
40
+ }
@@ -0,0 +1,12 @@
1
+ import type { ActionBridge } from "../action-bridge.js";
2
+ import type { CliReadModels } from "../read-models/index.js";
3
+ export interface CliCommandDefinition {
4
+ name: string;
5
+ description: string;
6
+ execute(input?: Record<string, unknown>): Promise<Record<string, unknown>>;
7
+ }
8
+ export interface CliCommandDeps {
9
+ readModels: CliReadModels;
10
+ actionBridge: ActionBridge;
11
+ }
12
+ export declare function createCliCommands(deps: CliCommandDeps): CliCommandDefinition[];
@@ -0,0 +1,138 @@
1
+ import { credentialVerify } from "./credential.js";
2
+ import { formatExplanation } from "../explain/format-explanation.js";
3
+ import { resolveExplainSubject } from "../explain/resolve-subject.js";
4
+ import { policySet } from "./policy.js";
5
+ const notImplemented = async (command) => ({
6
+ ok: false,
7
+ command,
8
+ message: "Command shell registered. Implementation lands in later Wave tasks.",
9
+ });
10
+ function explainSubjectError(code, message) {
11
+ return {
12
+ ok: false,
13
+ error: {
14
+ code,
15
+ message,
16
+ requiredUserInput: ["subject"],
17
+ nextStep: "reinvoke_explain_with_supported_subject",
18
+ },
19
+ };
20
+ }
21
+ export function createCliCommands(deps) {
22
+ const { readModels, actionBridge } = deps;
23
+ return [
24
+ {
25
+ name: "status",
26
+ description: "Show aggregated Second Nature status",
27
+ execute: async (input) => {
28
+ const scope = typeof input?.scope === "string" ? input.scope : undefined;
29
+ const data = await readModels.loadStatus(scope);
30
+ return { ok: true, data };
31
+ },
32
+ },
33
+ {
34
+ name: "policy",
35
+ description: "Write or inspect policy state",
36
+ execute: async (input) => {
37
+ const action = typeof input?.action === "string" ? input.action : "show";
38
+ if (action === "set") {
39
+ return policySet(actionBridge, input);
40
+ }
41
+ return notImplemented("policy");
42
+ },
43
+ },
44
+ {
45
+ name: "credential",
46
+ description: "Inspect or recover credential state",
47
+ execute: async (input) => {
48
+ const action = typeof input?.action === "string" ? input.action : "show";
49
+ if (action === "verify") {
50
+ return credentialVerify(actionBridge, input);
51
+ }
52
+ const platformId = typeof input?.platformId === "string" ? input.platformId : "unknown";
53
+ const data = await readModels.loadCredential(platformId);
54
+ return { ok: true, data };
55
+ },
56
+ },
57
+ {
58
+ name: "quiet",
59
+ description: "Inspect Quiet lifecycle state",
60
+ execute: async (input) => {
61
+ const scope = typeof input?.scope === "string" ? input.scope : undefined;
62
+ const data = await readModels.loadQuiet(scope);
63
+ return { ok: true, data };
64
+ },
65
+ },
66
+ {
67
+ name: "report",
68
+ description: "Show daily report artifacts",
69
+ execute: async (input) => {
70
+ const day = typeof input?.day === "string" ? input.day : new Date().toISOString().slice(0, 10);
71
+ const data = await readModels.loadDailyReport(day);
72
+ return { ok: true, data };
73
+ },
74
+ },
75
+ {
76
+ name: "session",
77
+ description: "Inspect continuity session details",
78
+ execute: async (input) => {
79
+ const sessionId = typeof input?.sessionId === "string" ? input.sessionId : "";
80
+ if (!sessionId) {
81
+ return {
82
+ ok: false,
83
+ error: {
84
+ code: "MISSING_SESSION_ID",
85
+ message: "session show requires sessionId",
86
+ requiredUserInput: ["session_id"],
87
+ nextStep: "reinvoke_session_with_session_id",
88
+ },
89
+ };
90
+ }
91
+ const data = await readModels.loadSession(sessionId);
92
+ return { ok: true, data };
93
+ },
94
+ },
95
+ {
96
+ name: "audit",
97
+ description: "Inspect audit and evidence views",
98
+ execute: () => notImplemented("audit"),
99
+ },
100
+ {
101
+ name: "explain",
102
+ description: "Answer why-question explain requests",
103
+ execute: async (input) => {
104
+ const subjectRaw = typeof input?.subject === "string" ? input.subject.trim() : "";
105
+ if (!subjectRaw) {
106
+ return {
107
+ ok: false,
108
+ error: {
109
+ code: "MISSING_EXPLAIN_SUBJECT",
110
+ message: "explain requires subject",
111
+ requiredUserInput: ["subject"],
112
+ nextStep: "reinvoke_explain_with_subject",
113
+ },
114
+ };
115
+ }
116
+ let subject;
117
+ try {
118
+ subject = resolveExplainSubject(subjectRaw);
119
+ }
120
+ catch (error) {
121
+ const code = error.message;
122
+ if (code === "explain_subject_requires_id") {
123
+ return explainSubjectError("EXPLAIN_SUBJECT_REQUIRES_ID", "subject must include identifier");
124
+ }
125
+ if (code === "explain_subject_unsupported") {
126
+ return explainSubjectError("EXPLAIN_SUBJECT_UNSUPPORTED", "supported subjects are decision:<id>, platform:<id>, outreach:<id>, soul:<id>");
127
+ }
128
+ return explainSubjectError("EXPLAIN_SUBJECT_INVALID", "invalid explain subject");
129
+ }
130
+ const model = await readModels.explain(subject);
131
+ return {
132
+ ok: true,
133
+ data: formatExplanation(model),
134
+ };
135
+ },
136
+ },
137
+ ];
138
+ }
@@ -0,0 +1,12 @@
1
+ import type { ActionBridge } from "../action-bridge.js";
2
+ export interface CliResult<T = Record<string, unknown>> {
3
+ ok: boolean;
4
+ data?: T;
5
+ error?: {
6
+ code: string;
7
+ message: string;
8
+ requiredUserInput?: string[];
9
+ nextStep?: string;
10
+ };
11
+ }
12
+ export declare function policySet(bridge: ActionBridge, input?: Record<string, unknown>): Promise<Record<string, unknown>>;
@@ -0,0 +1,43 @@
1
+ function toNumber(value) {
2
+ if (typeof value === "number" && Number.isFinite(value))
3
+ return value;
4
+ if (typeof value === "string" && value.trim()) {
5
+ const parsed = Number(value);
6
+ if (Number.isFinite(parsed))
7
+ return parsed;
8
+ }
9
+ return undefined;
10
+ }
11
+ export async function policySet(bridge, input) {
12
+ const platformId = typeof input?.platformId === "string" ? input.platformId.trim() : "";
13
+ const socialDailyLimit = toNumber(input?.socialDailyLimit);
14
+ const quietEnabled = typeof input?.quietEnabled === "boolean" ? input.quietEnabled : undefined;
15
+ const requiredUserInput = [];
16
+ if (!platformId)
17
+ requiredUserInput.push("platform_id");
18
+ if (socialDailyLimit === undefined)
19
+ requiredUserInput.push("social_daily_limit");
20
+ if (quietEnabled === undefined)
21
+ requiredUserInput.push("quiet_enabled");
22
+ if (requiredUserInput.length > 0) {
23
+ return {
24
+ ok: false,
25
+ error: {
26
+ code: "MISSING_POLICY_FIELDS",
27
+ message: "policy set requires complete non-interactive fields",
28
+ requiredUserInput,
29
+ nextStep: "reinvoke_policy_set_with_required_fields",
30
+ },
31
+ };
32
+ }
33
+ const payload = {
34
+ platformId,
35
+ socialDailyLimit: socialDailyLimit,
36
+ quietEnabled: quietEnabled,
37
+ };
38
+ await bridge.savePolicy(payload);
39
+ return {
40
+ ok: true,
41
+ data: { platformId },
42
+ };
43
+ }
@@ -0,0 +1,10 @@
1
+ import type { ExplainReadModel } from "../read-models/types.js";
2
+ export interface FormattedExplanation {
3
+ subjectType: ExplainReadModel["subjectType"];
4
+ conclusion: string;
5
+ keyFactors: string[];
6
+ evidenceRefs: string[];
7
+ requiredUserInput?: string[];
8
+ nextStep?: string;
9
+ }
10
+ export declare function formatExplanation(model: ExplainReadModel): FormattedExplanation;
@@ -0,0 +1,10 @@
1
+ export function formatExplanation(model) {
2
+ return {
3
+ subjectType: model.subjectType,
4
+ conclusion: model.conclusion,
5
+ keyFactors: model.keyFactors,
6
+ evidenceRefs: model.evidenceRefs,
7
+ requiredUserInput: model.requiredUserInput,
8
+ nextStep: model.nextStep,
9
+ };
10
+ }
@@ -0,0 +1,2 @@
1
+ import type { ExplainSubject } from "../read-models/index.js";
2
+ export declare function resolveExplainSubject(raw: string): ExplainSubject;
@@ -0,0 +1,26 @@
1
+ function splitSubject(raw) {
2
+ const [prefix, ...rest] = raw.split(":");
3
+ return {
4
+ prefix: (prefix ?? "").trim(),
5
+ id: rest.join(":").trim(),
6
+ };
7
+ }
8
+ export function resolveExplainSubject(raw) {
9
+ const { prefix, id } = splitSubject(raw);
10
+ if (!id) {
11
+ throw new Error("explain_subject_requires_id");
12
+ }
13
+ if (prefix === "decision") {
14
+ return { kind: "decision", id };
15
+ }
16
+ if (prefix === "platform") {
17
+ return { kind: "platform-selection", id };
18
+ }
19
+ if (prefix === "outreach") {
20
+ return { kind: "outreach", id };
21
+ }
22
+ if (prefix === "soul") {
23
+ return { kind: "soul-change", id };
24
+ }
25
+ throw new Error("explain_subject_unsupported");
26
+ }
@@ -0,0 +1,25 @@
1
+ import { type ObservabilityDatabase } from "../observability/db/index.js";
2
+ import { type StateDatabase, type StateAPI } from "../storage/index.js";
3
+ import { type ActionBridge } from "./action-bridge.js";
4
+ import { type CliCommandDefinition } from "./commands/index.js";
5
+ import { type CliReadModels } from "./read-models/index.js";
6
+ export interface CommandRouter {
7
+ commands: CliCommandDefinition[];
8
+ resolve(name: string): CliCommandDefinition | undefined;
9
+ }
10
+ export interface CommandRouterDeps {
11
+ commands: CliCommandDefinition[];
12
+ }
13
+ export interface CliRuntimeDeps {
14
+ stateDb: StateDatabase;
15
+ observabilityDb: ObservabilityDatabase;
16
+ stateApi: StateAPI;
17
+ readModels: CliReadModels;
18
+ actionBridge: ActionBridge;
19
+ }
20
+ export interface CreateCommandRouterOptions {
21
+ deps?: Partial<CliRuntimeDeps>;
22
+ }
23
+ export declare function createCliRuntimeDeps(overrides?: Partial<CliRuntimeDeps>): CliRuntimeDeps;
24
+ export declare function createCommandRouter(options?: CreateCommandRouterOptions): CommandRouter;
25
+ export declare function closeCliRuntimeDeps(deps: Pick<CliRuntimeDeps, "stateDb" | "observabilityDb">): void;
@@ -0,0 +1,36 @@
1
+ import { createObservabilityDatabase } from "../observability/db/index.js";
2
+ import { createStateAPI, createStateDatabase } from "../storage/index.js";
3
+ import { createActionBridge } from "./action-bridge.js";
4
+ import { createCliCommands } from "./commands/index.js";
5
+ import { createCliReadModels } from "./read-models/index.js";
6
+ export function createCliRuntimeDeps(overrides = {}) {
7
+ const stateDb = overrides.stateDb ?? createStateDatabase();
8
+ const observabilityDb = overrides.observabilityDb ?? createObservabilityDatabase();
9
+ const stateApi = overrides.stateApi ?? createStateAPI(stateDb);
10
+ const readModels = overrides.readModels ?? createCliReadModels({ stateDb, observabilityDb });
11
+ const actionBridge = overrides.actionBridge ?? createActionBridge(stateApi);
12
+ return {
13
+ stateDb,
14
+ observabilityDb,
15
+ stateApi,
16
+ readModels,
17
+ actionBridge,
18
+ };
19
+ }
20
+ export function createCommandRouter(options = {}) {
21
+ const runtime = createCliRuntimeDeps(options.deps);
22
+ const commands = createCliCommands({
23
+ readModels: runtime.readModels,
24
+ actionBridge: runtime.actionBridge,
25
+ });
26
+ return {
27
+ commands,
28
+ resolve(name) {
29
+ return commands.find((command) => command.name === name);
30
+ },
31
+ };
32
+ }
33
+ export function closeCliRuntimeDeps(deps) {
34
+ deps.stateDb.close();
35
+ deps.observabilityDb.close();
36
+ }
@@ -0,0 +1,20 @@
1
+ import type { StateDatabase } from "../../storage/db/index.js";
2
+ import type { ObservabilityDatabase } from "../../observability/db/index.js";
3
+ import type { StatusReadModel, DailyReportReadModel, QuietReadModel, SessionDetailReadModel, CredentialReadModel, ExplainReadModel } from "./types.js";
4
+ export interface CliReadModels {
5
+ loadStatus(scope?: string): Promise<StatusReadModel>;
6
+ loadDailyReport(day: string): Promise<DailyReportReadModel>;
7
+ loadQuiet(scope?: string): Promise<QuietReadModel>;
8
+ loadSession(sessionId: string): Promise<SessionDetailReadModel>;
9
+ loadCredential(platformId: string): Promise<CredentialReadModel>;
10
+ explain(subject: ExplainSubject): Promise<ExplainReadModel>;
11
+ }
12
+ export interface ExplainSubject {
13
+ kind: "decision" | "platform-selection" | "outreach" | "soul-change";
14
+ id: string;
15
+ }
16
+ export interface CliReadModelsDeps {
17
+ stateDb: StateDatabase;
18
+ observabilityDb: ObservabilityDatabase;
19
+ }
20
+ export declare function createCliReadModels(deps: CliReadModelsDeps): CliReadModels;