@haaaiawd/second-nature 0.1.1 → 0.1.3

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 (202) hide show
  1. package/index.ts +64 -21
  2. package/openclaw.plugin.json +1 -1
  3. package/package.json +8 -2
  4. package/runtime/cli/action-bridge.d.ts +11 -0
  5. package/runtime/cli/action-bridge.js +27 -0
  6. package/runtime/cli/commands/credential.d.ts +2 -0
  7. package/runtime/cli/commands/credential.js +40 -0
  8. package/runtime/cli/commands/index.d.ts +12 -0
  9. package/runtime/cli/commands/index.js +138 -0
  10. package/runtime/cli/commands/policy.d.ts +12 -0
  11. package/runtime/cli/commands/policy.js +43 -0
  12. package/runtime/cli/explain/format-explanation.d.ts +10 -0
  13. package/runtime/cli/explain/format-explanation.js +10 -0
  14. package/runtime/cli/explain/resolve-subject.d.ts +2 -0
  15. package/runtime/cli/explain/resolve-subject.js +26 -0
  16. package/runtime/cli/index.d.ts +25 -0
  17. package/runtime/cli/index.js +36 -0
  18. package/runtime/cli/read-models/index.d.ts +20 -0
  19. package/runtime/cli/read-models/index.js +161 -0
  20. package/runtime/cli/read-models/types.d.ts +75 -0
  21. package/runtime/cli/read-models/types.js +1 -0
  22. package/runtime/connectors/agent-network/evomap/adapter.d.ts +23 -0
  23. package/runtime/connectors/agent-network/evomap/adapter.js +69 -0
  24. package/runtime/connectors/agent-network/evomap/index.d.ts +2 -0
  25. package/runtime/connectors/agent-network/evomap/index.js +2 -0
  26. package/runtime/connectors/agent-network/evomap/manifest.d.ts +2 -0
  27. package/runtime/connectors/agent-network/evomap/manifest.js +7 -0
  28. package/runtime/connectors/base/channel-health.d.ts +29 -0
  29. package/runtime/connectors/base/channel-health.js +23 -0
  30. package/runtime/connectors/base/contract.d.ts +81 -0
  31. package/runtime/connectors/base/contract.js +71 -0
  32. package/runtime/connectors/base/failure-taxonomy.d.ts +13 -0
  33. package/runtime/connectors/base/failure-taxonomy.js +105 -0
  34. package/runtime/connectors/base/index.d.ts +6 -0
  35. package/runtime/connectors/base/index.js +6 -0
  36. package/runtime/connectors/base/manifest.d.ts +11 -0
  37. package/runtime/connectors/base/manifest.js +36 -0
  38. package/runtime/connectors/base/policy-layer.d.ts +27 -0
  39. package/runtime/connectors/base/policy-layer.js +213 -0
  40. package/runtime/connectors/base/route-planner.d.ts +10 -0
  41. package/runtime/connectors/base/route-planner.js +98 -0
  42. package/runtime/connectors/index.d.ts +4 -0
  43. package/runtime/connectors/index.js +4 -0
  44. package/runtime/connectors/social-community/instreet/adapter.d.ts +32 -0
  45. package/runtime/connectors/social-community/instreet/adapter.js +79 -0
  46. package/runtime/connectors/social-community/instreet/index.d.ts +2 -0
  47. package/runtime/connectors/social-community/instreet/index.js +2 -0
  48. package/runtime/connectors/social-community/instreet/manifest.d.ts +2 -0
  49. package/runtime/connectors/social-community/instreet/manifest.js +7 -0
  50. package/runtime/connectors/social-community/moltbook/adapter.d.ts +15 -0
  51. package/runtime/connectors/social-community/moltbook/adapter.js +48 -0
  52. package/runtime/connectors/social-community/moltbook/index.d.ts +2 -0
  53. package/runtime/connectors/social-community/moltbook/index.js +2 -0
  54. package/runtime/connectors/social-community/moltbook/manifest.d.ts +7 -0
  55. package/runtime/connectors/social-community/moltbook/manifest.js +12 -0
  56. package/runtime/core/second-nature/guidance/apply-guidance.d.ts +10 -0
  57. package/runtime/core/second-nature/guidance/apply-guidance.js +10 -0
  58. package/runtime/core/second-nature/guidance/request-guidance.d.ts +18 -0
  59. package/runtime/core/second-nature/guidance/request-guidance.js +22 -0
  60. package/runtime/core/second-nature/index.d.ts +14 -0
  61. package/runtime/core/second-nature/index.js +14 -0
  62. package/runtime/core/second-nature/orchestrator/effect-dispatcher.d.ts +100 -0
  63. package/runtime/core/second-nature/orchestrator/effect-dispatcher.js +139 -0
  64. package/runtime/core/second-nature/orchestrator/guard-layer.d.ts +2 -0
  65. package/runtime/core/second-nature/orchestrator/guard-layer.js +54 -0
  66. package/runtime/core/second-nature/orchestrator/intent-planner.d.ts +3 -0
  67. package/runtime/core/second-nature/orchestrator/intent-planner.js +92 -0
  68. package/runtime/core/second-nature/orchestrator/lease-manager.d.ts +14 -0
  69. package/runtime/core/second-nature/orchestrator/lease-manager.js +58 -0
  70. package/runtime/core/second-nature/orchestrator/resume-from-checkpoint.d.ts +32 -0
  71. package/runtime/core/second-nature/orchestrator/resume-from-checkpoint.js +23 -0
  72. package/runtime/core/second-nature/outreach/build-message.d.ts +16 -0
  73. package/runtime/core/second-nature/outreach/build-message.js +27 -0
  74. package/runtime/core/second-nature/outreach/evaluate-outreach.d.ts +13 -0
  75. package/runtime/core/second-nature/outreach/evaluate-outreach.js +41 -0
  76. package/runtime/core/second-nature/quiet/quiet-pipeline.d.ts +34 -0
  77. package/runtime/core/second-nature/quiet/quiet-pipeline.js +35 -0
  78. package/runtime/core/second-nature/reflection/run-narrative-reflection.d.ts +39 -0
  79. package/runtime/core/second-nature/reflection/run-narrative-reflection.js +29 -0
  80. package/runtime/core/second-nature/rhythm/rhythm-policy.d.ts +18 -0
  81. package/runtime/core/second-nature/rhythm/rhythm-policy.js +24 -0
  82. package/runtime/core/second-nature/rhythm/select-window.d.ts +3 -0
  83. package/runtime/core/second-nature/rhythm/select-window.js +50 -0
  84. package/runtime/core/second-nature/runtime/lifecycle-service.d.ts +26 -0
  85. package/runtime/core/second-nature/runtime/lifecycle-service.js +38 -0
  86. package/runtime/core/second-nature/runtime/service-entry.d.ts +36 -0
  87. package/runtime/core/second-nature/runtime/service-entry.js +44 -0
  88. package/runtime/core/second-nature/types.d.ts +37 -0
  89. package/runtime/core/second-nature/types.js +1 -0
  90. package/runtime/guidance/contracts.d.ts +48 -0
  91. package/runtime/guidance/contracts.js +54 -0
  92. package/runtime/guidance/fallback.d.ts +2 -0
  93. package/runtime/guidance/fallback.js +17 -0
  94. package/runtime/guidance/guidance-assembler.d.ts +5 -0
  95. package/runtime/guidance/guidance-assembler.js +62 -0
  96. package/runtime/guidance/index.d.ts +8 -0
  97. package/runtime/guidance/index.js +8 -0
  98. package/runtime/guidance/output-guard.d.ts +10 -0
  99. package/runtime/guidance/output-guard.js +29 -0
  100. package/runtime/guidance/persona-selection.d.ts +11 -0
  101. package/runtime/guidance/persona-selection.js +90 -0
  102. package/runtime/guidance/review-workflow.d.ts +15 -0
  103. package/runtime/guidance/review-workflow.js +60 -0
  104. package/runtime/guidance/template-registry.d.ts +3 -0
  105. package/runtime/guidance/template-registry.js +45 -0
  106. package/runtime/guidance/types.d.ts +72 -0
  107. package/runtime/guidance/types.js +1 -0
  108. package/runtime/observability/db/index.d.ts +10 -0
  109. package/runtime/observability/db/index.js +17 -0
  110. package/runtime/observability/db/schema/index.d.ts +946 -0
  111. package/runtime/observability/db/schema/index.js +70 -0
  112. package/runtime/observability/index.d.ts +12 -0
  113. package/runtime/observability/index.js +11 -0
  114. package/runtime/observability/projections/guidance-audit.d.ts +16 -0
  115. package/runtime/observability/projections/guidance-audit.js +35 -0
  116. package/runtime/observability/projections/outreach-quality-audit.d.ts +15 -0
  117. package/runtime/observability/projections/outreach-quality-audit.js +9 -0
  118. package/runtime/observability/projections/reflection-audit.d.ts +17 -0
  119. package/runtime/observability/projections/reflection-audit.js +9 -0
  120. package/runtime/observability/query/compose-evidence.d.ts +56 -0
  121. package/runtime/observability/query/compose-evidence.js +43 -0
  122. package/runtime/observability/query/evidence-query-engine.d.ts +17 -0
  123. package/runtime/observability/query/evidence-query-engine.js +166 -0
  124. package/runtime/observability/redaction/manifest.d.ts +18 -0
  125. package/runtime/observability/redaction/manifest.js +109 -0
  126. package/runtime/observability/redaction/policy.d.ts +19 -0
  127. package/runtime/observability/redaction/policy.js +71 -0
  128. package/runtime/observability/services/decision-ledger.d.ts +33 -0
  129. package/runtime/observability/services/decision-ledger.js +115 -0
  130. package/runtime/observability/services/execution-telemetry.d.ts +32 -0
  131. package/runtime/observability/services/execution-telemetry.js +126 -0
  132. package/runtime/observability/services/governance-audit.d.ts +27 -0
  133. package/runtime/observability/services/governance-audit.js +139 -0
  134. package/runtime/observability/services/redaction-store.d.ts +3 -0
  135. package/runtime/observability/services/redaction-store.js +20 -0
  136. package/runtime/setup/HOST_SETUP.md +112 -0
  137. package/runtime/shared/types/continuity.d.ts +69 -0
  138. package/runtime/shared/types/continuity.js +1 -0
  139. package/runtime/shared/types/credential.d.ts +22 -0
  140. package/runtime/shared/types/credential.js +1 -0
  141. package/runtime/shared/types/index.d.ts +3 -0
  142. package/runtime/shared/types/index.js +3 -0
  143. package/runtime/shared/types/outreach.d.ts +19 -0
  144. package/runtime/shared/types/outreach.js +1 -0
  145. package/runtime/storage/bootstrap/repair.d.ts +3 -0
  146. package/runtime/storage/bootstrap/repair.js +5 -0
  147. package/runtime/storage/db/index.d.ts +10 -0
  148. package/runtime/storage/db/index.js +17 -0
  149. package/runtime/storage/db/schema/assets.d.ts +140 -0
  150. package/runtime/storage/db/schema/assets.js +10 -0
  151. package/runtime/storage/db/schema/credentials.d.ts +178 -0
  152. package/runtime/storage/db/schema/credentials.js +12 -0
  153. package/runtime/storage/db/schema/index.d.ts +6 -0
  154. package/runtime/storage/db/schema/index.js +6 -0
  155. package/runtime/storage/db/schema/intent-commits.d.ts +161 -0
  156. package/runtime/storage/db/schema/intent-commits.js +11 -0
  157. package/runtime/storage/db/schema/policies.d.ts +81 -0
  158. package/runtime/storage/db/schema/policies.js +7 -0
  159. package/runtime/storage/db/schema/proposals.d.ts +216 -0
  160. package/runtime/storage/db/schema/proposals.js +14 -0
  161. package/runtime/storage/db/schema/provenance.d.ts +104 -0
  162. package/runtime/storage/db/schema/provenance.js +8 -0
  163. package/runtime/storage/index.d.ts +16 -0
  164. package/runtime/storage/index.js +16 -0
  165. package/runtime/storage/memory/workspace/paths.d.ts +62 -0
  166. package/runtime/storage/memory/workspace/paths.js +160 -0
  167. package/runtime/storage/memory/workspace/store.d.ts +26 -0
  168. package/runtime/storage/memory/workspace/store.js +153 -0
  169. package/runtime/storage/memory/workspace/types.d.ts +45 -0
  170. package/runtime/storage/memory/workspace/types.js +1 -0
  171. package/runtime/storage/repositories/asset-repository.d.ts +8 -0
  172. package/runtime/storage/repositories/asset-repository.js +19 -0
  173. package/runtime/storage/repositories/credential-repository.d.ts +8 -0
  174. package/runtime/storage/repositories/credential-repository.js +19 -0
  175. package/runtime/storage/repositories/index.d.ts +6 -0
  176. package/runtime/storage/repositories/index.js +6 -0
  177. package/runtime/storage/repositories/intent-commit-repository.d.ts +10 -0
  178. package/runtime/storage/repositories/intent-commit-repository.js +35 -0
  179. package/runtime/storage/repositories/policy-repository.d.ts +8 -0
  180. package/runtime/storage/repositories/policy-repository.js +19 -0
  181. package/runtime/storage/repositories/proposal-repository.d.ts +9 -0
  182. package/runtime/storage/repositories/proposal-repository.js +26 -0
  183. package/runtime/storage/repositories/provenance-repository.d.ts +20 -0
  184. package/runtime/storage/repositories/provenance-repository.js +41 -0
  185. package/runtime/storage/services/credential-vault.d.ts +8 -0
  186. package/runtime/storage/services/credential-vault.js +78 -0
  187. package/runtime/storage/services/daily-log-pipeline.d.ts +47 -0
  188. package/runtime/storage/services/daily-log-pipeline.js +86 -0
  189. package/runtime/storage/services/effect-commit-store.d.ts +11 -0
  190. package/runtime/storage/services/effect-commit-store.js +93 -0
  191. package/runtime/storage/services/governance-layer.d.ts +40 -0
  192. package/runtime/storage/services/governance-layer.js +103 -0
  193. package/runtime/storage/services/persona-candidate-loader.d.ts +5 -0
  194. package/runtime/storage/services/persona-candidate-loader.js +41 -0
  195. package/runtime/storage/services/provenance-service.d.ts +40 -0
  196. package/runtime/storage/services/provenance-service.js +43 -0
  197. package/runtime/storage/services/quiet-input-loader.d.ts +40 -0
  198. package/runtime/storage/services/quiet-input-loader.js +131 -0
  199. package/runtime/storage/services/repair-and-backup.d.ts +22 -0
  200. package/runtime/storage/services/repair-and-backup.js +73 -0
  201. package/runtime/storage/state-api.d.ts +46 -0
  202. package/runtime/storage/state-api.js +73 -0
@@ -0,0 +1,71 @@
1
+ export const REDACTION_CONFIG = {
2
+ maskedFieldNames: [
3
+ "token",
4
+ "access_token",
5
+ "refresh_token",
6
+ "api_key",
7
+ "apiSecret",
8
+ "secret",
9
+ "password",
10
+ "bearer_token",
11
+ "authorization",
12
+ "node_secret",
13
+ ],
14
+ eraseFieldNames: [
15
+ "full_message",
16
+ "full_post",
17
+ "private_message",
18
+ "prompt",
19
+ "system_prompt",
20
+ "completion",
21
+ "response_content",
22
+ ],
23
+ hashFieldNames: [
24
+ "user_id",
25
+ "session_id",
26
+ "trace_id",
27
+ "content_hash",
28
+ ],
29
+ sensitivityLevels: ["public", "internal", "confidential", "restricted"],
30
+ };
31
+ export const DEFAULT_REDACTION_POLICY = {
32
+ defaultPolicy: [
33
+ { fieldName: "token", action: "mask" },
34
+ { fieldName: "access_token", action: "mask" },
35
+ { fieldName: "refresh_token", action: "mask" },
36
+ { fieldName: "api_key", action: "mask" },
37
+ { fieldName: "apiSecret", action: "mask" },
38
+ { fieldName: "secret", action: "mask" },
39
+ { fieldName: "password", action: "mask" },
40
+ { fieldName: "bearer_token", action: "mask" },
41
+ { fieldName: "authorization", action: "mask" },
42
+ { fieldName: "node_secret", action: "mask" },
43
+ { fieldName: "full_message", action: "erase" },
44
+ { fieldName: "full_post", action: "erase" },
45
+ { fieldName: "private_message", action: "erase" },
46
+ { fieldName: "prompt", action: "erase" },
47
+ { fieldName: "system_prompt", action: "erase" },
48
+ { fieldName: "completion", action: "erase" },
49
+ { fieldName: "response_content", action: "erase" },
50
+ { fieldName: "content_hash", action: "hash" },
51
+ ],
52
+ fieldOverrides: {},
53
+ maxFieldLength: 500,
54
+ };
55
+ export function getFieldRedactionRule(fieldName, policy = DEFAULT_REDACTION_POLICY) {
56
+ for (const rule of policy.defaultPolicy) {
57
+ if (rule.fieldName === fieldName) {
58
+ return rule;
59
+ }
60
+ }
61
+ for (const [prefix, rules] of Object.entries(policy.fieldOverrides)) {
62
+ if (fieldName.startsWith(prefix)) {
63
+ for (const rule of rules) {
64
+ if (rule.fieldName === fieldName || rule.fieldName === "*") {
65
+ return rule;
66
+ }
67
+ }
68
+ }
69
+ }
70
+ return { fieldName, action: "keep" };
71
+ }
@@ -0,0 +1,33 @@
1
+ import type { ObservabilityDatabase } from "../db/index.js";
2
+ import type { DecisionRecord } from "../../shared/types/continuity.js";
3
+ export interface QuietLifecycleEvent {
4
+ id: string;
5
+ tickId: string;
6
+ eventType: "quiet.entered" | "quiet.skipped" | "quiet.interrupted" | "quiet.resumed" | "quiet.suppressed";
7
+ reason?: string;
8
+ suppressedBy?: string;
9
+ reflectionCandidates?: string[];
10
+ createdAt: string;
11
+ }
12
+ export interface OutreachDecision {
13
+ id: string;
14
+ tickId: string;
15
+ eventType: "outreach.considered" | "outreach.denied" | "outreach.deferred" | "outreach.sent";
16
+ platformId?: string;
17
+ targetUserId?: string;
18
+ valueScore?: number;
19
+ suppressionReason?: string;
20
+ messagePreview?: string;
21
+ createdAt: string;
22
+ }
23
+ export declare class DecisionLedger {
24
+ private db;
25
+ constructor(db: ObservabilityDatabase);
26
+ recordDecision(record: DecisionRecord): Promise<void>;
27
+ recordQuietLifecycle(event: QuietLifecycleEvent): Promise<void>;
28
+ recordOutreachDecision(event: OutreachDecision): Promise<void>;
29
+ queryByTickId(tickId: string): Promise<DecisionRecord[]>;
30
+ queryByTraceId(traceId: string): Promise<DecisionRecord | null>;
31
+ queryByIntentId(intentId: string): Promise<DecisionRecord[]>;
32
+ private mapToDecisionRecord;
33
+ }
@@ -0,0 +1,115 @@
1
+ import { eq } from "drizzle-orm";
2
+ import { decisionLedger } from "../db/schema/index.js";
3
+ import { redactEvent } from "../redaction/manifest.js";
4
+ import { persistRedactionManifest } from "./redaction-store.js";
5
+ export class DecisionLedger {
6
+ db;
7
+ constructor(db) {
8
+ this.db = db;
9
+ }
10
+ async recordDecision(record) {
11
+ const { redacted, manifest } = redactEvent(record);
12
+ await this.db.db.insert(decisionLedger).values({
13
+ id: redacted.id,
14
+ tickId: redacted.tickId,
15
+ traceId: redacted.traceId,
16
+ intentId: redacted.intentId ?? null,
17
+ platformId: redacted.platformId ?? null,
18
+ verdict: redacted.verdict,
19
+ mode: redacted.mode,
20
+ reasons: JSON.stringify(redacted.reasons),
21
+ reasonCodes: JSON.stringify(redacted.reasonCodes),
22
+ decisionBasis: redacted.decisionBasis,
23
+ evidenceRefs: JSON.stringify(redacted.evidenceRefs),
24
+ modelEvalRef: redacted.modelEvalRef ?? null,
25
+ createdAt: redacted.createdAt,
26
+ });
27
+ await persistRedactionManifest(this.db, redacted.id, "decision.recorded", manifest);
28
+ }
29
+ async recordQuietLifecycle(event) {
30
+ const { redacted, manifest } = redactEvent(event);
31
+ await this.db.db.insert(decisionLedger).values({
32
+ id: redacted.id,
33
+ tickId: redacted.tickId,
34
+ traceId: `quiet-${redacted.eventType}-${redacted.id}`,
35
+ intentId: null,
36
+ platformId: null,
37
+ verdict: "allow",
38
+ mode: "quiet",
39
+ reasons: JSON.stringify([redacted.eventType, redacted.reason ?? ""].filter(Boolean)),
40
+ reasonCodes: JSON.stringify(["quiet_lifecycle"]),
41
+ decisionBasis: "rule_only",
42
+ evidenceRefs: JSON.stringify(redacted.reflectionCandidates ?? []),
43
+ modelEvalRef: null,
44
+ createdAt: redacted.createdAt,
45
+ });
46
+ await persistRedactionManifest(this.db, redacted.id, redacted.eventType, manifest);
47
+ }
48
+ async recordOutreachDecision(event) {
49
+ const { redacted, manifest } = redactEvent(event);
50
+ const verdict = redacted.eventType === "outreach.sent"
51
+ ? "allow"
52
+ : redacted.eventType === "outreach.deferred" || redacted.eventType === "outreach.considered"
53
+ ? "defer"
54
+ : "deny";
55
+ await this.db.db.insert(decisionLedger).values({
56
+ id: redacted.id,
57
+ tickId: redacted.tickId,
58
+ traceId: `outreach-${redacted.eventType}-${redacted.id}`,
59
+ intentId: null,
60
+ platformId: redacted.platformId ?? null,
61
+ verdict,
62
+ mode: "active",
63
+ reasons: JSON.stringify([
64
+ redacted.eventType,
65
+ redacted.valueScore?.toString() ?? "",
66
+ redacted.suppressionReason ?? "",
67
+ ].filter(Boolean)),
68
+ reasonCodes: JSON.stringify(["outreach_decision"]),
69
+ decisionBasis: "score_based",
70
+ evidenceRefs: JSON.stringify([redacted.targetUserId ?? ""].filter(Boolean)),
71
+ modelEvalRef: null,
72
+ createdAt: redacted.createdAt,
73
+ });
74
+ await persistRedactionManifest(this.db, redacted.id, redacted.eventType, manifest);
75
+ }
76
+ async queryByTickId(tickId) {
77
+ const results = await this.db.db
78
+ .select()
79
+ .from(decisionLedger)
80
+ .where(eq(decisionLedger.tickId, tickId));
81
+ return results.map(this.mapToDecisionRecord);
82
+ }
83
+ async queryByTraceId(traceId) {
84
+ const results = await this.db.db
85
+ .select()
86
+ .from(decisionLedger)
87
+ .where(eq(decisionLedger.traceId, traceId))
88
+ .limit(1);
89
+ return results[0] ? this.mapToDecisionRecord(results[0]) : null;
90
+ }
91
+ async queryByIntentId(intentId) {
92
+ const results = await this.db.db
93
+ .select()
94
+ .from(decisionLedger)
95
+ .where(eq(decisionLedger.intentId, intentId));
96
+ return results.map(this.mapToDecisionRecord);
97
+ }
98
+ mapToDecisionRecord(row) {
99
+ return {
100
+ id: row.id,
101
+ tickId: row.tickId,
102
+ traceId: row.traceId,
103
+ intentId: row.intentId ?? undefined,
104
+ platformId: row.platformId ?? undefined,
105
+ verdict: row.verdict,
106
+ mode: row.mode,
107
+ reasons: JSON.parse(row.reasons),
108
+ reasonCodes: JSON.parse(row.reasonCodes),
109
+ decisionBasis: row.decisionBasis,
110
+ evidenceRefs: JSON.parse(row.evidenceRefs),
111
+ modelEvalRef: row.modelEvalRef ?? undefined,
112
+ createdAt: row.createdAt,
113
+ };
114
+ }
115
+ }
@@ -0,0 +1,32 @@
1
+ import type { ObservabilityDatabase } from "../db/index.js";
2
+ import type { ExecutionAttempt, IntentCommitState } from "../../shared/types/continuity.js";
3
+ export interface ExecutionAttemptInput {
4
+ traceId: string;
5
+ decisionId: string;
6
+ intentId: string;
7
+ platformId: string;
8
+ capability: string;
9
+ channel: string;
10
+ status: ExecutionAttempt["status"];
11
+ commitState?: IntentCommitState;
12
+ failureClass?: string;
13
+ retryPolicy?: string;
14
+ idempotencyKey?: string;
15
+ metadata?: Record<string, unknown>;
16
+ startedAt?: string;
17
+ finishedAt?: string;
18
+ }
19
+ export declare class ExecutionTelemetry {
20
+ private db;
21
+ constructor(db: ObservabilityDatabase);
22
+ recordExecutionAttempt(attempt: ExecutionAttempt): Promise<void>;
23
+ startAttempt(input: ExecutionAttemptInput): Promise<string>;
24
+ completeAttempt(traceId: string, status: "succeeded" | "failed", commitState?: IntentCommitState, failureClass?: string): Promise<void>;
25
+ updateCommitState(traceId: string, commitState: IntentCommitState): Promise<void>;
26
+ queryByTraceId(traceId: string): Promise<ExecutionAttempt | null>;
27
+ queryByDecisionId(decisionId: string): Promise<ExecutionAttempt[]>;
28
+ queryByPlatform(platformId: string): Promise<ExecutionAttempt[]>;
29
+ queryFailedAttempts(since: string): Promise<ExecutionAttempt[]>;
30
+ queryByCommitState(commitState: IntentCommitState): Promise<ExecutionAttempt[]>;
31
+ private mapToExecutionAttempt;
32
+ }
@@ -0,0 +1,126 @@
1
+ import { eq, and, gte } from "drizzle-orm";
2
+ import { executionAttempts } from "../db/schema/index.js";
3
+ import { redactEvent } from "../redaction/manifest.js";
4
+ import { persistRedactionManifest } from "./redaction-store.js";
5
+ export class ExecutionTelemetry {
6
+ db;
7
+ constructor(db) {
8
+ this.db = db;
9
+ }
10
+ async recordExecutionAttempt(attempt) {
11
+ const { redacted, manifest } = redactEvent(attempt);
12
+ await this.db.db.insert(executionAttempts).values({
13
+ id: redacted.id,
14
+ traceId: redacted.traceId,
15
+ decisionId: redacted.decisionId,
16
+ intentId: redacted.intentId,
17
+ platformId: redacted.platformId,
18
+ capability: redacted.capability,
19
+ channel: redacted.channel,
20
+ status: redacted.status,
21
+ commitState: redacted.commitState ?? null,
22
+ failureClass: redacted.failureClass ?? null,
23
+ retryPolicy: redacted.retryPolicy ?? null,
24
+ idempotencyKey: redacted.idempotencyKey ?? null,
25
+ startedAt: redacted.startedAt ?? null,
26
+ finishedAt: redacted.finishedAt ?? null,
27
+ });
28
+ await persistRedactionManifest(this.db, redacted.id, "connector.attempt.recorded", manifest);
29
+ }
30
+ async startAttempt(input) {
31
+ const id = `attempt-${input.traceId}-${Date.now()}`;
32
+ const now = new Date().toISOString();
33
+ const attempt = {
34
+ id,
35
+ traceId: input.traceId,
36
+ decisionId: input.decisionId,
37
+ intentId: input.intentId,
38
+ platformId: input.platformId,
39
+ capability: input.capability,
40
+ channel: input.channel,
41
+ status: "started",
42
+ commitState: input.commitState,
43
+ failureClass: input.failureClass,
44
+ retryPolicy: input.retryPolicy,
45
+ idempotencyKey: input.idempotencyKey,
46
+ metadata: input.metadata,
47
+ startedAt: now,
48
+ finishedAt: undefined,
49
+ };
50
+ await this.recordExecutionAttempt(attempt);
51
+ return id;
52
+ }
53
+ async completeAttempt(traceId, status, commitState, failureClass) {
54
+ const now = new Date().toISOString();
55
+ await this.db.db
56
+ .update(executionAttempts)
57
+ .set({
58
+ status,
59
+ commitState: commitState ?? null,
60
+ failureClass: failureClass ?? null,
61
+ finishedAt: now,
62
+ })
63
+ .where(eq(executionAttempts.traceId, traceId));
64
+ }
65
+ async updateCommitState(traceId, commitState) {
66
+ await this.db.db
67
+ .update(executionAttempts)
68
+ .set({ commitState })
69
+ .where(eq(executionAttempts.traceId, traceId));
70
+ }
71
+ async queryByTraceId(traceId) {
72
+ const results = await this.db.db
73
+ .select()
74
+ .from(executionAttempts)
75
+ .where(eq(executionAttempts.traceId, traceId))
76
+ .limit(1);
77
+ return results[0] ? this.mapToExecutionAttempt(results[0]) : null;
78
+ }
79
+ async queryByDecisionId(decisionId) {
80
+ const results = await this.db.db
81
+ .select()
82
+ .from(executionAttempts)
83
+ .where(eq(executionAttempts.decisionId, decisionId));
84
+ return results.map(this.mapToExecutionAttempt);
85
+ }
86
+ async queryByPlatform(platformId) {
87
+ const results = await this.db.db
88
+ .select()
89
+ .from(executionAttempts)
90
+ .where(eq(executionAttempts.platformId, platformId));
91
+ return results.map(this.mapToExecutionAttempt);
92
+ }
93
+ async queryFailedAttempts(since) {
94
+ const results = await this.db.db
95
+ .select()
96
+ .from(executionAttempts)
97
+ .where(and(eq(executionAttempts.status, "failed"), gte(executionAttempts.startedAt, since)));
98
+ return results.map(this.mapToExecutionAttempt);
99
+ }
100
+ async queryByCommitState(commitState) {
101
+ const results = await this.db.db
102
+ .select()
103
+ .from(executionAttempts)
104
+ .where(eq(executionAttempts.commitState, commitState));
105
+ return results.map(this.mapToExecutionAttempt);
106
+ }
107
+ mapToExecutionAttempt(row) {
108
+ return {
109
+ id: row.id,
110
+ traceId: row.traceId,
111
+ decisionId: row.decisionId,
112
+ intentId: row.intentId,
113
+ platformId: row.platformId,
114
+ capability: row.capability,
115
+ channel: row.channel,
116
+ status: row.status,
117
+ commitState: row.commitState,
118
+ failureClass: row.failureClass ?? undefined,
119
+ retryPolicy: row.retryPolicy ?? undefined,
120
+ idempotencyKey: row.idempotencyKey ?? undefined,
121
+ metadata: undefined,
122
+ startedAt: row.startedAt ?? undefined,
123
+ finishedAt: row.finishedAt ?? undefined,
124
+ };
125
+ }
126
+ }
@@ -0,0 +1,27 @@
1
+ import type { ObservabilityDatabase } from "../db/index.js";
2
+ import type { AnchorChangeAudit } from "../../shared/types/continuity.js";
3
+ export interface CredentialLifecycleAudit {
4
+ id: string;
5
+ platformId: string;
6
+ credentialId: string;
7
+ statusFrom?: string;
8
+ statusTo: string;
9
+ verificationDeadline?: string;
10
+ attemptsRemaining?: number;
11
+ explanationCapsule: string;
12
+ createdAt: string;
13
+ }
14
+ export declare class GovernanceAudit {
15
+ private db;
16
+ constructor(db: ObservabilityDatabase);
17
+ recordAnchorChangeAudit(event: AnchorChangeAudit): Promise<void>;
18
+ recordCredentialLifecycle(event: CredentialLifecycleAudit): Promise<void>;
19
+ recordProposalApply(proposalId: string, targetAssetId: string, assetPath: string, beforeHash: string | undefined, afterHash: string | undefined, supportingSources: string[], reason: string): Promise<void>;
20
+ recordProposalReject(proposalId: string, targetAssetId: string, assetPath: string, reason: string): Promise<void>;
21
+ queryByProposalId(proposalId: string): Promise<AnchorChangeAudit[]>;
22
+ queryByAssetId(assetId: string): Promise<AnchorChangeAudit[]>;
23
+ queryByEventType(eventType: string): Promise<AnchorChangeAudit[]>;
24
+ queryCredentialByPlatform(platformId: string): Promise<CredentialLifecycleAudit[]>;
25
+ private mapToAnchorAudit;
26
+ private mapToCredentialAudit;
27
+ }
@@ -0,0 +1,139 @@
1
+ import { eq } from "drizzle-orm";
2
+ import { governanceAudit } from "../db/schema/index.js";
3
+ import { redactEvent } from "../redaction/manifest.js";
4
+ import { persistRedactionManifest } from "./redaction-store.js";
5
+ export class GovernanceAudit {
6
+ db;
7
+ constructor(db) {
8
+ this.db = db;
9
+ }
10
+ async recordAnchorChangeAudit(event) {
11
+ const { redacted, manifest } = redactEvent(event);
12
+ await this.db.db.insert(governanceAudit).values({
13
+ id: redacted.id,
14
+ eventType: "anchor_change",
15
+ proposalId: redacted.proposalId,
16
+ targetAssetId: redacted.targetAssetId,
17
+ assetPath: redacted.assetPath,
18
+ statusFrom: null,
19
+ statusTo: redacted.status,
20
+ beforeHash: redacted.beforeHash ?? null,
21
+ afterHash: redacted.afterHash ?? null,
22
+ supportingSources: JSON.stringify(redacted.supportingSources),
23
+ reason: redacted.reason,
24
+ verificationDeadline: null,
25
+ attemptsRemaining: null,
26
+ createdAt: redacted.createdAt,
27
+ });
28
+ await persistRedactionManifest(this.db, redacted.id, "anchor.change", manifest);
29
+ }
30
+ async recordCredentialLifecycle(event) {
31
+ const { redacted, manifest } = redactEvent(event);
32
+ await this.db.db.insert(governanceAudit).values({
33
+ id: redacted.id,
34
+ eventType: "credential_lifecycle",
35
+ proposalId: null,
36
+ targetAssetId: redacted.platformId,
37
+ assetPath: redacted.credentialId,
38
+ statusFrom: redacted.statusFrom ?? null,
39
+ statusTo: redacted.statusTo,
40
+ beforeHash: null,
41
+ afterHash: null,
42
+ supportingSources: "[]",
43
+ reason: redacted.explanationCapsule,
44
+ verificationDeadline: redacted.verificationDeadline ?? null,
45
+ attemptsRemaining: redacted.attemptsRemaining ?? null,
46
+ createdAt: redacted.createdAt,
47
+ });
48
+ await persistRedactionManifest(this.db, redacted.id, "credential.lifecycle", manifest);
49
+ }
50
+ async recordProposalApply(proposalId, targetAssetId, assetPath, beforeHash, afterHash, supportingSources, reason) {
51
+ const id = `anchor-${proposalId}-${Date.now()}`;
52
+ const event = {
53
+ id,
54
+ proposalId,
55
+ targetAssetId,
56
+ assetPath,
57
+ status: "applied",
58
+ beforeHash,
59
+ afterHash,
60
+ supportingSources,
61
+ reason,
62
+ appliedAt: new Date().toISOString(),
63
+ createdAt: new Date().toISOString(),
64
+ };
65
+ await this.recordAnchorChangeAudit(event);
66
+ }
67
+ async recordProposalReject(proposalId, targetAssetId, assetPath, reason) {
68
+ const id = `anchor-reject-${proposalId}-${Date.now()}`;
69
+ const event = {
70
+ id,
71
+ proposalId,
72
+ targetAssetId,
73
+ assetPath,
74
+ status: "rejected",
75
+ supportingSources: [],
76
+ reason,
77
+ createdAt: new Date().toISOString(),
78
+ };
79
+ await this.recordAnchorChangeAudit(event);
80
+ }
81
+ async queryByProposalId(proposalId) {
82
+ const results = await this.db.db
83
+ .select()
84
+ .from(governanceAudit)
85
+ .where(eq(governanceAudit.proposalId, proposalId));
86
+ return results.map(this.mapToAnchorAudit);
87
+ }
88
+ async queryByAssetId(assetId) {
89
+ const results = await this.db.db
90
+ .select()
91
+ .from(governanceAudit)
92
+ .where(eq(governanceAudit.targetAssetId, assetId));
93
+ return results.map(this.mapToAnchorAudit);
94
+ }
95
+ async queryByEventType(eventType) {
96
+ const results = await this.db.db
97
+ .select()
98
+ .from(governanceAudit)
99
+ .where(eq(governanceAudit.eventType, eventType));
100
+ return results.map(this.mapToAnchorAudit);
101
+ }
102
+ async queryCredentialByPlatform(platformId) {
103
+ const results = await this.db.db
104
+ .select()
105
+ .from(governanceAudit)
106
+ .where(eq(governanceAudit.targetAssetId, platformId));
107
+ return results
108
+ .filter(r => r.eventType === "credential_lifecycle")
109
+ .map(this.mapToCredentialAudit);
110
+ }
111
+ mapToAnchorAudit(row) {
112
+ return {
113
+ id: row.id,
114
+ proposalId: row.proposalId ?? "",
115
+ targetAssetId: row.targetAssetId ?? "",
116
+ assetPath: row.assetPath ?? "",
117
+ status: row.statusTo,
118
+ beforeHash: row.beforeHash ?? undefined,
119
+ afterHash: row.afterHash ?? undefined,
120
+ supportingSources: JSON.parse(row.supportingSources ?? "[]"),
121
+ reason: row.reason ?? "",
122
+ appliedAt: row.statusTo === "applied" ? row.createdAt : undefined,
123
+ createdAt: row.createdAt,
124
+ };
125
+ }
126
+ mapToCredentialAudit(row) {
127
+ return {
128
+ id: row.id,
129
+ platformId: row.targetAssetId ?? "",
130
+ credentialId: row.assetPath ?? "",
131
+ statusFrom: row.statusFrom ?? undefined,
132
+ statusTo: row.statusTo,
133
+ verificationDeadline: row.verificationDeadline ?? undefined,
134
+ attemptsRemaining: row.attemptsRemaining ?? undefined,
135
+ explanationCapsule: row.reason ?? "",
136
+ createdAt: row.createdAt,
137
+ };
138
+ }
139
+ }
@@ -0,0 +1,3 @@
1
+ import type { ObservabilityDatabase } from "../db/index.js";
2
+ import type { RedactionManifest } from "../redaction/manifest.js";
3
+ export declare function persistRedactionManifest(db: ObservabilityDatabase, eventId: string, eventType: string, manifest: RedactionManifest): Promise<void>;
@@ -0,0 +1,20 @@
1
+ import { redactionManifest as redactionManifestTable } from "../db/schema/index.js";
2
+ export async function persistRedactionManifest(db, eventId, eventType, manifest) {
3
+ const rows = [
4
+ ...manifest.maskedFields.map((fieldName) => ({ fieldName, action: "mask" })),
5
+ ...manifest.erasedFields.map((fieldName) => ({ fieldName, action: "erase" })),
6
+ ...manifest.hashedFields.map((fieldName) => ({ fieldName, action: "hash" })),
7
+ ];
8
+ if (rows.length === 0) {
9
+ rows.push({ fieldName: "*", action: "none" });
10
+ }
11
+ await db.db.insert(redactionManifestTable).values(rows.map((row, index) => ({
12
+ id: `${manifest.id}:${index}`,
13
+ eventId,
14
+ eventType,
15
+ fieldName: row.fieldName,
16
+ action: row.action,
17
+ originalValueHash: null,
18
+ createdAt: manifest.createdAt,
19
+ })));
20
+ }
@@ -0,0 +1,112 @@
1
+ # Second Nature Host Setup Guide
2
+
3
+ This file ships inside the published plugin package.
4
+
5
+ Use it after installing `@haaaiawd/second-nature` in an OpenClaw host to complete the minimum runtime setup and avoid pretending the system is fully connected before it is.
6
+
7
+ ## What to check first
8
+
9
+ Confirm these in order:
10
+
11
+ 1. The plugin is installed and enabled.
12
+ 2. `workspace/` exists in the host environment.
13
+ 3. The anchor files exist:
14
+ - `workspace/SOUL.md`
15
+ - `workspace/USER.md`
16
+ - `workspace/IDENTITY.md`
17
+ - `workspace/MEMORY.md`
18
+ 4. Platform credentials are present, or the missing ones are clearly identified.
19
+ 5. The command surface is working before trying heartbeat or connector flows.
20
+
21
+ ## Minimum workspace setup
22
+
23
+ If the anchor files are missing, create short first-person versions that are actually usable.
24
+
25
+ - `SOUL.md`: values, stance, what I care about, what I refuse to become
26
+ - `USER.md`: who the user is to me, how I should relate to them, what matters to them
27
+ - `IDENTITY.md`: who I am, my role, my behavioral boundaries
28
+ - `MEMORY.md`: stable facts and continuity worth carrying forward
29
+
30
+ Do not leave them as empty headings.
31
+
32
+ ## Platform prerequisites
33
+
34
+ Check platform readiness honestly.
35
+
36
+ ### Moltbook
37
+
38
+ Look for a usable credential first.
39
+
40
+ ### InStreet
41
+
42
+ Check whether the credential is already `active` or still `pending_verification`.
43
+
44
+ ### EvoMap
45
+
46
+ Check whether a `node_secret` already exists.
47
+ Without it, heartbeat, work discovery, and task claim will not be truly connected.
48
+
49
+ ## Command surface to inspect
50
+
51
+ Use these first:
52
+
53
+ - `status`
54
+ - `credential`
55
+ - `quiet`
56
+ - `report`
57
+ - `session`
58
+ - `explain`
59
+
60
+ The purpose is simple:
61
+
62
+ 1. verify the plugin is alive
63
+ 2. verify commands are usable
64
+ 3. see where credentials are blocked
65
+ 4. see whether reports and explain flows already have evidence to read back
66
+
67
+ ## About heartbeat
68
+
69
+ Do not claim heartbeat is connected unless there is evidence.
70
+
71
+ Look for:
72
+
73
+ - heartbeat-related records in `report`
74
+ - evidence in `explain`
75
+ - signs of `heartbeat_bridge` in runtime records
76
+
77
+ If that evidence does not exist, report that heartbeat bridge is not yet confirmed in the host.
78
+
79
+ ## About direct user replies
80
+
81
+ Direct chat with the user should keep very light continuity.
82
+
83
+ - do keep continuity
84
+ - do not use post-reply tone
85
+ - do not pretend the direct user reply path is connected unless you can observe evidence
86
+
87
+ If continuity is not visible, report that the `user_reply` host entry is not yet confirmed.
88
+
89
+ ## Reporting template
90
+
91
+ When setup inspection is done, report in this structure:
92
+
93
+ 1. Plugin state
94
+ 2. Workspace state
95
+ 3. Platform credential state
96
+ 4. Command/tool/service state
97
+ 5. Heartbeat evidence
98
+ 6. Direct user reply continuity evidence
99
+ 7. Current blockers
100
+
101
+ ## Important reminder
102
+
103
+ This guide is only for installation and host bring-up.
104
+
105
+ Long-term principles should move into:
106
+
107
+ - `workspace/SOUL.md`
108
+ - `workspace/USER.md`
109
+ - `workspace/IDENTITY.md`
110
+ - `workspace/MEMORY.md`
111
+
112
+ Do not depend on this file as the long-term memory source.