@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,15 @@
1
+ import type { ConnectorRequest, ExecutionPlan, RawAttempt } from "../../base/contract.js";
2
+ export interface MoltbookApiClient {
3
+ readFeed(payload: Record<string, unknown>): Promise<unknown>;
4
+ publishPost(payload: Record<string, unknown>): Promise<unknown>;
5
+ replyComment(payload: Record<string, unknown>): Promise<unknown>;
6
+ }
7
+ export interface MoltbookSkillRunner {
8
+ run(intent: string, payload: Record<string, unknown>): Promise<unknown>;
9
+ }
10
+ export declare function createMoltbookRunner(input: {
11
+ apiClient: MoltbookApiClient;
12
+ skillRunner: MoltbookSkillRunner;
13
+ }): {
14
+ run(plan: ExecutionPlan, request: ConnectorRequest): Promise<RawAttempt>;
15
+ };
@@ -0,0 +1,48 @@
1
+ export function createMoltbookRunner(input) {
2
+ const { apiClient, skillRunner } = input;
3
+ return {
4
+ async run(plan, request) {
5
+ const started = Date.now();
6
+ try {
7
+ const payload = await executeByChannel(plan, request.payload, apiClient, skillRunner);
8
+ return {
9
+ platformId: request.platformId,
10
+ channel: plan.channel,
11
+ latencyMs: Date.now() - started,
12
+ degraded: plan.channel === "skill" || plan.channel === "browser",
13
+ success: true,
14
+ payload: {
15
+ capability: request.intent,
16
+ channel: plan.channel,
17
+ data: payload,
18
+ },
19
+ };
20
+ }
21
+ catch (error) {
22
+ return {
23
+ platformId: request.platformId,
24
+ channel: plan.channel,
25
+ latencyMs: Date.now() - started,
26
+ degraded: plan.channel === "skill" || plan.channel === "browser",
27
+ success: false,
28
+ error,
29
+ };
30
+ }
31
+ },
32
+ };
33
+ }
34
+ async function executeByChannel(plan, payload, apiClient, skillRunner) {
35
+ if (plan.channel === "api_rest") {
36
+ if (plan.intent === "feed.read")
37
+ return apiClient.readFeed(payload);
38
+ if (plan.intent === "post.publish")
39
+ return apiClient.publishPost(payload);
40
+ if (plan.intent === "comment.reply")
41
+ return apiClient.replyComment(payload);
42
+ throw { code: "protocol_mismatch", detail: `unsupported intent for moltbook api: ${plan.intent}` };
43
+ }
44
+ if (plan.channel === "skill" || plan.channel === "browser") {
45
+ return skillRunner.run(plan.intent, payload);
46
+ }
47
+ throw { code: "protocol_mismatch", detail: `unsupported channel for moltbook: ${plan.channel}` };
48
+ }
@@ -0,0 +1,2 @@
1
+ export * from "./manifest.js";
2
+ export * from "./adapter.js";
@@ -0,0 +1,2 @@
1
+ export * from "./manifest.js";
2
+ export * from "./adapter.js";
@@ -0,0 +1,7 @@
1
+ import type { ConnectorManifest } from "../../base/manifest.js";
2
+ export declare const moltbookManifest: ConnectorManifest;
3
+ export declare const MOLTBOOK_DOC_RISK: {
4
+ readonly key: "moltbook_skill_doc_availability";
5
+ readonly fallbackChannel: "skill";
6
+ readonly note: "official skill/doc may be transiently unavailable; adapter seam remains replaceable via injected skill runner";
7
+ };
@@ -0,0 +1,12 @@
1
+ export const moltbookManifest = {
2
+ platformId: "moltbook",
3
+ supportedCapabilities: ["feed.read", "post.publish", "comment.reply"],
4
+ channelPriority: ["api_rest", "skill", "browser"],
5
+ credentialTypes: ["api_key"],
6
+ degradedChannels: ["skill", "browser"],
7
+ };
8
+ export const MOLTBOOK_DOC_RISK = {
9
+ key: "moltbook_skill_doc_availability",
10
+ fallbackChannel: "skill",
11
+ note: "official skill/doc may be transiently unavailable; adapter seam remains replaceable via injected skill runner",
12
+ };
@@ -0,0 +1,10 @@
1
+ import type { GuidanceFallback, GuidancePayload } from "../../../guidance/index.js";
2
+ export interface AppliedGuidanceContext {
3
+ source: "guidance_payload" | "minimal_fallback";
4
+ sceneType: string;
5
+ atmosphereText?: string;
6
+ impulseTexts: string[];
7
+ personaRationales: string[];
8
+ outputConstraints: string[];
9
+ }
10
+ export declare function applyGuidance(input: GuidancePayload | GuidanceFallback): AppliedGuidanceContext;
@@ -0,0 +1,10 @@
1
+ export function applyGuidance(input) {
2
+ return {
3
+ source: "minimal" in input && input.minimal ? "minimal_fallback" : "guidance_payload",
4
+ sceneType: input.scene.sceneType,
5
+ atmosphereText: input.atmosphere?.text,
6
+ impulseTexts: input.impulses.map((item) => item.text),
7
+ personaRationales: input.personaReinforcement.map((item) => item.rationale),
8
+ outputConstraints: input.outputGuard?.constraints ?? [],
9
+ };
10
+ }
@@ -0,0 +1,18 @@
1
+ import { type GuidanceFallback, type GuidancePayload, type GuidanceUnavailable, type PersonaCandidate, type SceneContext } from "../../../guidance/index.js";
2
+ export interface RequestGuidancePort {
3
+ assembleGuidance(input: {
4
+ sceneContext: SceneContext;
5
+ personaCandidates: PersonaCandidate[];
6
+ }): Promise<GuidancePayload | GuidanceUnavailable>;
7
+ }
8
+ export interface RequestGuidanceResult {
9
+ owner: "control-plane-system";
10
+ sceneContext: SceneContext;
11
+ guidance: GuidancePayload | GuidanceFallback;
12
+ usedFallback: boolean;
13
+ }
14
+ export declare function requestGuidance(input: {
15
+ sceneContext: SceneContext;
16
+ personaCandidates?: PersonaCandidate[];
17
+ port?: RequestGuidancePort;
18
+ }): Promise<RequestGuidanceResult>;
@@ -0,0 +1,22 @@
1
+ import { assembleGuidance, buildMinimalGuidanceFallback, } from "../../../guidance/index.js";
2
+ export async function requestGuidance(input) {
3
+ const port = input.port ?? { assembleGuidance };
4
+ const result = await port.assembleGuidance({
5
+ sceneContext: input.sceneContext,
6
+ personaCandidates: input.personaCandidates ?? [],
7
+ });
8
+ if ("available" in result) {
9
+ return {
10
+ owner: "control-plane-system",
11
+ sceneContext: input.sceneContext,
12
+ guidance: buildMinimalGuidanceFallback(input.sceneContext),
13
+ usedFallback: true,
14
+ };
15
+ }
16
+ return {
17
+ owner: "control-plane-system",
18
+ sceneContext: input.sceneContext,
19
+ guidance: result,
20
+ usedFallback: false,
21
+ };
22
+ }
@@ -0,0 +1,14 @@
1
+ export * from "./types.js";
2
+ export * from "./rhythm/rhythm-policy.js";
3
+ export * from "./rhythm/select-window.js";
4
+ export * from "./orchestrator/intent-planner.js";
5
+ export * from "./orchestrator/guard-layer.js";
6
+ export * from "./orchestrator/lease-manager.js";
7
+ export * from "./orchestrator/effect-dispatcher.js";
8
+ export * from "./orchestrator/resume-from-checkpoint.js";
9
+ export * from "./quiet/quiet-pipeline.js";
10
+ export * from "./reflection/run-narrative-reflection.js";
11
+ export * from "./outreach/evaluate-outreach.js";
12
+ export * from "./outreach/build-message.js";
13
+ export * from "./guidance/request-guidance.js";
14
+ export * from "./guidance/apply-guidance.js";
@@ -0,0 +1,14 @@
1
+ export * from "./types.js";
2
+ export * from "./rhythm/rhythm-policy.js";
3
+ export * from "./rhythm/select-window.js";
4
+ export * from "./orchestrator/intent-planner.js";
5
+ export * from "./orchestrator/guard-layer.js";
6
+ export * from "./orchestrator/lease-manager.js";
7
+ export * from "./orchestrator/effect-dispatcher.js";
8
+ export * from "./orchestrator/resume-from-checkpoint.js";
9
+ export * from "./quiet/quiet-pipeline.js";
10
+ export * from "./reflection/run-narrative-reflection.js";
11
+ export * from "./outreach/evaluate-outreach.js";
12
+ export * from "./outreach/build-message.js";
13
+ export * from "./guidance/request-guidance.js";
14
+ export * from "./guidance/apply-guidance.js";
@@ -0,0 +1,100 @@
1
+ import type { ConnectorResult, CapabilityIntent } from "../../../connectors/base/contract.js";
2
+ import { LeaseManager, type EffectClass } from "./lease-manager.js";
3
+ export interface AllowedIntent {
4
+ id: string;
5
+ kind: "work" | "exploration" | "social" | "reflection" | "outreach" | "maintenance";
6
+ summary: string;
7
+ effectClass: EffectClass;
8
+ platformId?: string;
9
+ payload?: Record<string, unknown>;
10
+ }
11
+ export interface DecisionContext {
12
+ decisionId: string;
13
+ intentId: string;
14
+ tickId: string;
15
+ checkpointId: string;
16
+ traceId: string;
17
+ }
18
+ export interface IntentCommitPort {
19
+ createIntentCommitRecord(input: {
20
+ intentId: string;
21
+ decisionId: string;
22
+ checkpointId?: string;
23
+ state: "planned" | "dispatched" | "externally_acknowledged" | "committed" | "reconcile" | "aborted";
24
+ }): Promise<{
25
+ id: string;
26
+ }>;
27
+ advanceIntentCommitState(id: string, state: "planned" | "dispatched" | "externally_acknowledged" | "committed" | "reconcile" | "aborted", metadata?: Record<string, unknown>): Promise<void>;
28
+ commitIntentOutcome(id: string, outcome: {
29
+ traceId: string;
30
+ outcomeRef: string;
31
+ }): Promise<void>;
32
+ abortIntentCommit(id: string, reason: string): Promise<void>;
33
+ }
34
+ export interface ConnectorExecutor {
35
+ executeEffect(input: {
36
+ platformId: string;
37
+ intent: CapabilityIntent;
38
+ payload: Record<string, unknown>;
39
+ decisionId: string;
40
+ intentId: string;
41
+ idempotencyKey: string;
42
+ }): Promise<ConnectorResult<unknown>>;
43
+ }
44
+ export interface CheckpointPort {
45
+ saveCheckpoint(input: {
46
+ id: string;
47
+ tickId: string;
48
+ intentId: string;
49
+ phase: "before_effect" | "before_quiet_write";
50
+ snapshotRef: string;
51
+ }): Promise<void>;
52
+ }
53
+ export interface MemoryPort {
54
+ persistCurationResult(input: {
55
+ summary: string;
56
+ sourceRefs: string[];
57
+ traceId: string;
58
+ }): Promise<void>;
59
+ }
60
+ export interface ReflectionPort {
61
+ runNarrativeReflection(input: {
62
+ decisionId: string;
63
+ intentId: string;
64
+ traceId: string;
65
+ }): Promise<{
66
+ outcomeRef: string;
67
+ }>;
68
+ }
69
+ export type DispatchResult = {
70
+ status: "deferred";
71
+ reason: string;
72
+ } | {
73
+ status: "effect_executed";
74
+ result: ConnectorResult<unknown>;
75
+ commitId: string;
76
+ } | {
77
+ status: "curated";
78
+ commitId: string;
79
+ } | {
80
+ status: "reflected";
81
+ commitId: string;
82
+ } | {
83
+ status: "maintenance_done";
84
+ commitId: string;
85
+ };
86
+ export declare class EffectDispatcher {
87
+ private readonly leaseManager;
88
+ private readonly commitPort;
89
+ private readonly connectorExecutor;
90
+ private readonly checkpointPort;
91
+ private readonly memoryPort;
92
+ private readonly reflectionPort;
93
+ constructor(leaseManager: LeaseManager, commitPort: IntentCommitPort, connectorExecutor: ConnectorExecutor, checkpointPort: CheckpointPort, memoryPort: MemoryPort, reflectionPort: ReflectionPort);
94
+ dispatchEffect(intent: AllowedIntent, decision: DecisionContext): Promise<DispatchResult>;
95
+ }
96
+ export declare function buildDecisionContext(input: {
97
+ tickId: string;
98
+ decisionId?: string;
99
+ intentId: string;
100
+ }): DecisionContext;
@@ -0,0 +1,139 @@
1
+ import * as crypto from "crypto";
2
+ function needsLease(effectClass) {
3
+ return effectClass === "external_platform_action" || effectClass === "user_outreach";
4
+ }
5
+ function needsCheckpoint(effectClass) {
6
+ return effectClass !== "maintenance";
7
+ }
8
+ function toCapabilityIntent(intent) {
9
+ if (intent.kind === "work")
10
+ return "work.discover";
11
+ if (intent.kind === "exploration")
12
+ return "feed.read";
13
+ if (intent.kind === "social")
14
+ return "comment.reply";
15
+ if (intent.kind === "outreach")
16
+ return "message.send";
17
+ return "feed.read";
18
+ }
19
+ export class EffectDispatcher {
20
+ leaseManager;
21
+ commitPort;
22
+ connectorExecutor;
23
+ checkpointPort;
24
+ memoryPort;
25
+ reflectionPort;
26
+ constructor(leaseManager, commitPort, connectorExecutor, checkpointPort, memoryPort, reflectionPort) {
27
+ this.leaseManager = leaseManager;
28
+ this.commitPort = commitPort;
29
+ this.connectorExecutor = connectorExecutor;
30
+ this.checkpointPort = checkpointPort;
31
+ this.memoryPort = memoryPort;
32
+ this.reflectionPort = reflectionPort;
33
+ }
34
+ async dispatchEffect(intent, decision) {
35
+ const lease = needsLease(intent.effectClass)
36
+ ? await this.leaseManager.acquire(intent.effectClass, intent.platformId ?? intent.id)
37
+ : await this.leaseManager.acquire("maintenance");
38
+ if (!lease.granted) {
39
+ return { status: "deferred", reason: "lease_unavailable" };
40
+ }
41
+ if (needsCheckpoint(intent.effectClass)) {
42
+ await this.checkpointPort.saveCheckpoint({
43
+ id: decision.checkpointId,
44
+ tickId: decision.tickId,
45
+ intentId: decision.intentId,
46
+ phase: intent.effectClass === "external_platform_action" ? "before_effect" : "before_quiet_write",
47
+ snapshotRef: decision.traceId,
48
+ });
49
+ }
50
+ const commit = await this.commitPort.createIntentCommitRecord({
51
+ intentId: decision.intentId,
52
+ decisionId: decision.decisionId,
53
+ checkpointId: decision.checkpointId,
54
+ state: "planned",
55
+ });
56
+ try {
57
+ if (intent.effectClass === "external_platform_action") {
58
+ await this.commitPort.advanceIntentCommitState(commit.id, "dispatched");
59
+ const result = await this.connectorExecutor.executeEffect({
60
+ platformId: intent.platformId ?? "unknown",
61
+ intent: toCapabilityIntent(intent),
62
+ payload: intent.payload ?? {},
63
+ decisionId: decision.decisionId,
64
+ intentId: decision.intentId,
65
+ idempotencyKey: `idem:${decision.decisionId}:${decision.intentId}`,
66
+ });
67
+ if (result.status === "success") {
68
+ await this.commitPort.advanceIntentCommitState(commit.id, "externally_acknowledged", {
69
+ outcomeRef: result.metadata.platformId,
70
+ });
71
+ await this.commitPort.commitIntentOutcome(commit.id, {
72
+ traceId: decision.traceId,
73
+ outcomeRef: result.metadata.platformId,
74
+ });
75
+ }
76
+ else {
77
+ if (result.status === "retryable_failure") {
78
+ await this.commitPort.advanceIntentCommitState(commit.id, "reconcile", {
79
+ failureClass: result.failureClass,
80
+ });
81
+ }
82
+ else {
83
+ await this.commitPort.abortIntentCommit(commit.id, result.failureClass ?? "external_effect_failed");
84
+ }
85
+ }
86
+ return { status: "effect_executed", result, commitId: commit.id };
87
+ }
88
+ if (intent.effectClass === "memory_curation") {
89
+ await this.commitPort.advanceIntentCommitState(commit.id, "dispatched");
90
+ await this.memoryPort.persistCurationResult({
91
+ summary: intent.summary,
92
+ sourceRefs: [decision.traceId],
93
+ traceId: decision.traceId,
94
+ });
95
+ await this.commitPort.commitIntentOutcome(commit.id, {
96
+ traceId: decision.traceId,
97
+ outcomeRef: "memory_curation",
98
+ });
99
+ return { status: "curated", commitId: commit.id };
100
+ }
101
+ if (intent.effectClass === "narrative_reflection") {
102
+ await this.commitPort.advanceIntentCommitState(commit.id, "dispatched");
103
+ const reflection = await this.reflectionPort.runNarrativeReflection({
104
+ decisionId: decision.decisionId,
105
+ intentId: decision.intentId,
106
+ traceId: decision.traceId,
107
+ });
108
+ await this.commitPort.commitIntentOutcome(commit.id, {
109
+ traceId: decision.traceId,
110
+ outcomeRef: reflection.outcomeRef,
111
+ });
112
+ return { status: "reflected", commitId: commit.id };
113
+ }
114
+ await this.commitPort.advanceIntentCommitState(commit.id, "dispatched");
115
+ await this.commitPort.commitIntentOutcome(commit.id, {
116
+ traceId: decision.traceId,
117
+ outcomeRef: "maintenance",
118
+ });
119
+ return { status: "maintenance_done", commitId: commit.id };
120
+ }
121
+ catch (error) {
122
+ await this.commitPort.abortIntentCommit(commit.id, String(error));
123
+ throw error;
124
+ }
125
+ finally {
126
+ await lease.release();
127
+ }
128
+ }
129
+ }
130
+ export function buildDecisionContext(input) {
131
+ const decisionId = input.decisionId ?? crypto.randomUUID();
132
+ return {
133
+ decisionId,
134
+ intentId: input.intentId,
135
+ tickId: input.tickId,
136
+ checkpointId: `checkpoint:${input.intentId}:${Date.now()}`,
137
+ traceId: `trace:${decisionId}`,
138
+ };
139
+ }
@@ -0,0 +1,2 @@
1
+ import type { CandidateIntent, ContinuitySnapshot, GuardEvaluation } from "../types.js";
2
+ export declare function evaluateGuards(intent: CandidateIntent, snapshot: ContinuitySnapshot): GuardEvaluation;
@@ -0,0 +1,54 @@
1
+ function stableIntentHash(intent) {
2
+ return `${intent.kind}:${intent.summary}`;
3
+ }
4
+ function isDuplicateIntent(intent, snapshot) {
5
+ const hash = stableIntentHash(intent);
6
+ return snapshot.deniedIntents.some((item) => item.intentHash === hash && item.reason === "duplicate_intent");
7
+ }
8
+ function isBudgetExceeded(intent, snapshot) {
9
+ if (intent.kind !== "social")
10
+ return false;
11
+ if (!snapshot.budgets)
12
+ return false;
13
+ return snapshot.budgets.socialUsed >= snapshot.budgets.socialLimit;
14
+ }
15
+ function isQuietSuppressed(intent, snapshot) {
16
+ if (snapshot.mode !== "quiet")
17
+ return false;
18
+ if (intent.effectClass === "maintenance" || intent.effectClass === "memory_curation" || intent.effectClass === "narrative_reflection") {
19
+ return false;
20
+ }
21
+ return true;
22
+ }
23
+ export function evaluateGuards(intent, snapshot) {
24
+ const reasons = [];
25
+ if (isDuplicateIntent(intent, snapshot)) {
26
+ reasons.push("duplicate_intent");
27
+ }
28
+ if (isBudgetExceeded(intent, snapshot)) {
29
+ reasons.push("budget_exceeded");
30
+ }
31
+ if (isQuietSuppressed(intent, snapshot)) {
32
+ reasons.push("quiet_window");
33
+ }
34
+ if (snapshot.awaitingUserInput) {
35
+ reasons.push("awaiting_user");
36
+ }
37
+ if (reasons.length === 0) {
38
+ return {
39
+ verdict: "allow",
40
+ reasons,
41
+ quietSuppressed: false,
42
+ leaseRequired: intent.effectClass === "external_platform_action" || intent.effectClass === "user_outreach",
43
+ requiresCheckpoint: intent.effectClass !== "maintenance",
44
+ };
45
+ }
46
+ const escalated = reasons.includes("awaiting_user") && intent.kind === "outreach";
47
+ return {
48
+ verdict: escalated ? "escalate" : "deny",
49
+ reasons,
50
+ quietSuppressed: reasons.includes("quiet_window"),
51
+ leaseRequired: false,
52
+ requiresCheckpoint: false,
53
+ };
54
+ }
@@ -0,0 +1,3 @@
1
+ import type { CandidateIntent, ContinuitySnapshot, DecisionBasis } from "../types.js";
2
+ export declare function planIntent(snapshot: ContinuitySnapshot): CandidateIntent[];
3
+ export declare function decideDecisionBasis(intent: CandidateIntent): DecisionBasis;
@@ -0,0 +1,92 @@
1
+ const MAX_CANDIDATES = 6;
2
+ function planObligationIntents(snapshot) {
3
+ return snapshot.pendingObligations.map((obligation, index) => ({
4
+ id: `intent-obligation-${index}`,
5
+ kind: "work",
6
+ priority: 100 - index,
7
+ source: "obligation",
8
+ summary: `fulfill obligation: ${obligation}`,
9
+ effectClass: "external_platform_action",
10
+ }));
11
+ }
12
+ function planPlatformIntents(snapshot) {
13
+ const socialPriorityBase = snapshot.budgets && snapshot.budgets.socialUsed >= snapshot.budgets.socialLimit ? 10 : 60;
14
+ return [
15
+ {
16
+ id: "intent-exploration",
17
+ kind: "exploration",
18
+ priority: 70,
19
+ source: "tick",
20
+ summary: "scan platform opportunities",
21
+ effectClass: "external_platform_action",
22
+ },
23
+ {
24
+ id: "intent-social",
25
+ kind: "social",
26
+ priority: socialPriorityBase,
27
+ source: "tick",
28
+ summary: "engage social platforms",
29
+ effectClass: "external_platform_action",
30
+ },
31
+ ];
32
+ }
33
+ function planQuietIntents(snapshot) {
34
+ if (snapshot.mode !== "quiet") {
35
+ return [];
36
+ }
37
+ return [
38
+ {
39
+ id: "intent-maintenance",
40
+ kind: "maintenance",
41
+ priority: 90,
42
+ source: "quiet_plan",
43
+ summary: "run maintenance checks",
44
+ effectClass: "maintenance",
45
+ },
46
+ {
47
+ id: "intent-reflection",
48
+ kind: "reflection",
49
+ priority: 80,
50
+ source: "quiet_plan",
51
+ summary: "run narrative reflection",
52
+ effectClass: "narrative_reflection",
53
+ },
54
+ ];
55
+ }
56
+ function planOutreachIntents(snapshot) {
57
+ if (snapshot.recentOutreachHashes.length > 3) {
58
+ return [];
59
+ }
60
+ return [
61
+ {
62
+ id: "intent-outreach",
63
+ kind: "outreach",
64
+ priority: 40,
65
+ source: "tick",
66
+ summary: "consider proactive user outreach",
67
+ effectClass: "user_outreach",
68
+ },
69
+ ];
70
+ }
71
+ export function planIntent(snapshot) {
72
+ const intents = [
73
+ ...planObligationIntents(snapshot),
74
+ ...planPlatformIntents(snapshot),
75
+ ...planQuietIntents(snapshot),
76
+ ...planOutreachIntents(snapshot),
77
+ ];
78
+ return intents
79
+ .sort((a, b) => b.priority - a.priority)
80
+ .slice(0, MAX_CANDIDATES);
81
+ }
82
+ export function decideDecisionBasis(intent) {
83
+ if (intent.source === "obligation")
84
+ return "rule_only";
85
+ if (intent.kind === "maintenance")
86
+ return "rule_only";
87
+ if (intent.kind === "outreach" || intent.kind === "reflection")
88
+ return "model_assisted";
89
+ if (intent.kind === "exploration" || intent.kind === "social" || intent.kind === "work")
90
+ return "score_based";
91
+ return "rule_only";
92
+ }
@@ -0,0 +1,14 @@
1
+ export type EffectClass = "external_platform_action" | "memory_curation" | "narrative_reflection" | "user_outreach" | "maintenance";
2
+ export interface LeaseHandle {
3
+ id: string;
4
+ granted: boolean;
5
+ scope: string;
6
+ release(): Promise<void>;
7
+ }
8
+ export declare class LeaseManager {
9
+ private readonly ttlMs;
10
+ private readonly leases;
11
+ constructor(ttlMs?: number);
12
+ acquire(effectClass: EffectClass, scopeHint?: string): Promise<LeaseHandle>;
13
+ private resolveScope;
14
+ }
@@ -0,0 +1,58 @@
1
+ import * as crypto from "crypto";
2
+ const GLOBAL_SCOPE = "global-control-plane-flight";
3
+ const DEFAULT_TTL_MS = 90_000;
4
+ export class LeaseManager {
5
+ ttlMs;
6
+ leases = new Map();
7
+ constructor(ttlMs = DEFAULT_TTL_MS) {
8
+ this.ttlMs = ttlMs;
9
+ }
10
+ async acquire(effectClass, scopeHint) {
11
+ const scope = this.resolveScope(effectClass, scopeHint);
12
+ if (!scope) {
13
+ return {
14
+ id: "no-lease-required",
15
+ granted: true,
16
+ scope: "none",
17
+ async release() {
18
+ return;
19
+ },
20
+ };
21
+ }
22
+ const now = Date.now();
23
+ const existing = this.leases.get(scope);
24
+ if (existing && existing.expiresAt > now) {
25
+ return {
26
+ id: existing.id,
27
+ granted: false,
28
+ scope,
29
+ async release() {
30
+ return;
31
+ },
32
+ };
33
+ }
34
+ const record = {
35
+ id: crypto.randomUUID(),
36
+ scope,
37
+ expiresAt: now + this.ttlMs,
38
+ };
39
+ this.leases.set(scope, record);
40
+ return {
41
+ id: record.id,
42
+ granted: true,
43
+ scope,
44
+ release: async () => {
45
+ const current = this.leases.get(scope);
46
+ if (current && current.id === record.id) {
47
+ this.leases.delete(scope);
48
+ }
49
+ },
50
+ };
51
+ }
52
+ resolveScope(effectClass, scopeHint) {
53
+ if (effectClass === "external_platform_action" || effectClass === "user_outreach") {
54
+ return scopeHint && scopeHint.length > 0 ? `${GLOBAL_SCOPE}:${scopeHint}` : GLOBAL_SCOPE;
55
+ }
56
+ return null;
57
+ }
58
+ }