@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,41 @@
1
+ import { eq } from "drizzle-orm";
2
+ import { provenanceEdges } from "../db/schema/index.js";
3
+ export class ProvenanceRepository {
4
+ database;
5
+ constructor(database) {
6
+ this.database = database;
7
+ }
8
+ async create(record) {
9
+ await this.database.db.insert(provenanceEdges).values(record);
10
+ }
11
+ async listByTarget(toId) {
12
+ return this.database.db.select().from(provenanceEdges).where(eq(provenanceEdges.toId, toId));
13
+ }
14
+ async linkEntrySources(entryId, sourceRefs) {
15
+ for (const sourceId of sourceRefs) {
16
+ await this.create({
17
+ id: `prov:${Date.now()}:${Math.random().toString(36).slice(2, 8)}`,
18
+ fromId: sourceId,
19
+ toId: entryId,
20
+ kind: "source",
21
+ createdAt: new Date().toISOString(),
22
+ });
23
+ }
24
+ }
25
+ async traceAsset(assetId) {
26
+ const edges = await this.listByTarget(assetId);
27
+ const upstreamSources = edges.filter((e) => e.kind === "source").map((e) => e.fromId);
28
+ const proposalIds = edges.filter((e) => e.kind === "proposal").map((e) => e.fromId);
29
+ const applyIds = edges.filter((e) => e.kind === "apply").map((e) => e.fromId);
30
+ return { assetId, upstreamSources, proposalIds, applyIds };
31
+ }
32
+ async recordApply(proposalId, assetId, info) {
33
+ await this.create({
34
+ id: `apply:${Date.now()}:${Math.random().toString(36).slice(2, 8)}`,
35
+ fromId: proposalId,
36
+ toId: assetId,
37
+ kind: "apply",
38
+ createdAt: new Date().toISOString(),
39
+ });
40
+ }
41
+ }
@@ -0,0 +1,8 @@
1
+ import type { StateDatabase } from "../db/index.js";
2
+ import type { CredentialContextWrite, CredentialContext, CredentialState } from "../../shared/types/index.js";
3
+ export interface CredentialVault {
4
+ saveCredentialContext(input: CredentialContextWrite): Promise<void>;
5
+ loadCredentialContext(platformId: string): Promise<CredentialContext | null>;
6
+ getCredentialState(platformId: string): Promise<CredentialState>;
7
+ }
8
+ export declare function createCredentialVault(db: StateDatabase["db"]): CredentialVault;
@@ -0,0 +1,78 @@
1
+ import * as crypto from "crypto";
2
+ import { eq } from "drizzle-orm";
3
+ import { credentialRecords } from "../db/schema/index.js";
4
+ const ENCRYPTION_KEY = process.env.SECOND_NATURE_ENCRYPTION_KEY || crypto.randomBytes(32).toString("hex");
5
+ const ALGORITHM = "aes-256-gcm";
6
+ function encrypt(plaintext) {
7
+ const iv = crypto.randomBytes(16);
8
+ const key = Buffer.from(ENCRYPTION_KEY.slice(0, 32), "utf8");
9
+ const cipher = crypto.createCipheriv(ALGORITHM, key, iv);
10
+ const encrypted = Buffer.concat([cipher.update(plaintext, "utf8"), cipher.final()]);
11
+ const authTag = cipher.getAuthTag();
12
+ return iv.toString("hex") + ":" + authTag.toString("hex") + ":" + encrypted.toString("hex");
13
+ }
14
+ function decrypt(ciphertext) {
15
+ const parts = ciphertext.split(":");
16
+ if (parts.length !== 3)
17
+ return ciphertext;
18
+ const iv = Buffer.from(parts[0], "hex");
19
+ const authTag = Buffer.from(parts[1], "hex");
20
+ const encrypted = Buffer.from(parts[2], "hex");
21
+ const key = Buffer.from(ENCRYPTION_KEY.slice(0, 32), "utf8");
22
+ const decipher = crypto.createDecipheriv(ALGORITHM, key, iv);
23
+ decipher.setAuthTag(authTag);
24
+ return decipher.update(encrypted) + decipher.final("utf8");
25
+ }
26
+ export function createCredentialVault(db) {
27
+ return {
28
+ async saveCredentialContext(input) {
29
+ const encrypted = input.encryptedValue ? encrypt(input.encryptedValue) : "";
30
+ await db.insert(credentialRecords).values({
31
+ platformId: input.platformId,
32
+ credentialType: input.credentialType,
33
+ encryptedValue: encrypted,
34
+ status: input.status,
35
+ verificationCode: input.verificationCode ?? null,
36
+ challengeText: input.challengeText ?? null,
37
+ expiresAt: input.expiresAt ?? null,
38
+ attemptsRemaining: input.attemptsRemaining ?? null,
39
+ updatedAt: new Date().toISOString(),
40
+ }).onConflictDoUpdate({
41
+ target: credentialRecords.platformId,
42
+ set: {
43
+ credentialType: input.credentialType,
44
+ encryptedValue: encrypted,
45
+ status: input.status,
46
+ verificationCode: input.verificationCode ?? null,
47
+ challengeText: input.challengeText ?? null,
48
+ expiresAt: input.expiresAt ?? null,
49
+ attemptsRemaining: input.attemptsRemaining ?? null,
50
+ updatedAt: new Date().toISOString(),
51
+ },
52
+ });
53
+ },
54
+ async loadCredentialContext(platformId) {
55
+ const record = await db.query.credentialRecords.findFirst({
56
+ where: (tbl) => eq(tbl.platformId, platformId),
57
+ });
58
+ if (!record)
59
+ return null;
60
+ return {
61
+ platformId: record.platformId,
62
+ credentialType: record.credentialType,
63
+ status: record.status,
64
+ encryptedValue: record.encryptedValue ? decrypt(record.encryptedValue) : undefined,
65
+ verificationCode: record.verificationCode ?? undefined,
66
+ challengeText: record.challengeText ?? undefined,
67
+ verificationDeadline: record.expiresAt ?? undefined,
68
+ attemptsRemaining: record.attemptsRemaining ?? undefined,
69
+ };
70
+ },
71
+ async getCredentialState(platformId) {
72
+ const record = await db.query.credentialRecords.findFirst({
73
+ where: (tbl) => eq(tbl.platformId, platformId),
74
+ });
75
+ return record?.status || "missing";
76
+ },
77
+ };
78
+ }
@@ -0,0 +1,47 @@
1
+ import type { AssetRepository } from "../repositories/asset-repository.js";
2
+ import type { ProvenanceRepository } from "../repositories/provenance-repository.js";
3
+ export interface ActivityLogWrite {
4
+ id: string;
5
+ timestamp: string;
6
+ platform?: string;
7
+ kind: "browse" | "action" | "failure" | "task" | "heartbeat";
8
+ content: string;
9
+ sourceRefs: string[];
10
+ }
11
+ export interface ObservationWrite {
12
+ id: string;
13
+ timestamp: string;
14
+ summary: string;
15
+ mood?: string;
16
+ sourceRefs: string[];
17
+ }
18
+ export interface DailyReportInput {
19
+ day: string;
20
+ summary: string;
21
+ highlights: string[];
22
+ activityRefs: string[];
23
+ observationRefs: string[];
24
+ }
25
+ export interface CuratedMemoryWrite {
26
+ id: string;
27
+ title: string;
28
+ summary: string;
29
+ confidence: number;
30
+ ttlClass: "short" | "medium" | "long";
31
+ sourceRefs: string[];
32
+ supersedes?: string[];
33
+ }
34
+ export interface AssetWriteAck {
35
+ assetPath: string;
36
+ hash: string;
37
+ }
38
+ export declare class DailyLogPipeline {
39
+ private readonly assetRepository;
40
+ private readonly provenanceRepository;
41
+ constructor(assetRepository: AssetRepository, provenanceRepository: ProvenanceRepository);
42
+ appendActivityLog(entry: ActivityLogWrite): Promise<AssetWriteAck>;
43
+ appendObservation(entry: ObservationWrite): Promise<AssetWriteAck>;
44
+ generateDailyReport(input: DailyReportInput): Promise<AssetWriteAck>;
45
+ upsertCuratedMemory(candidate: CuratedMemoryWrite): Promise<AssetWriteAck>;
46
+ }
47
+ export declare function createDailyLogPipeline(assetRepository: AssetRepository, provenanceRepository: ProvenanceRepository): DailyLogPipeline;
@@ -0,0 +1,86 @@
1
+ import { writeCanonicalArtifact, appendLine, hashFile, resolveDailyJournalPath, resolveDailyReportPath, resolveCuratedPath, serializeActivityLog, serializeObservation, renderDailyReport, renderCuratedMemory, buildJournalAssetId, buildReportAssetId, buildCuratedAssetId, } from "../memory/workspace/paths.js";
2
+ export class DailyLogPipeline {
3
+ assetRepository;
4
+ provenanceRepository;
5
+ constructor(assetRepository, provenanceRepository) {
6
+ this.assetRepository = assetRepository;
7
+ this.provenanceRepository = provenanceRepository;
8
+ }
9
+ async appendActivityLog(entry) {
10
+ const journalPath = resolveDailyJournalPath(entry.timestamp);
11
+ const serialized = serializeActivityLog(entry);
12
+ await appendLine(journalPath, serialized);
13
+ const hash = await hashFile(journalPath);
14
+ await this.assetRepository.upsert({
15
+ id: buildJournalAssetId(journalPath),
16
+ kind: "daily_journal",
17
+ path: journalPath,
18
+ hash,
19
+ version: 1,
20
+ layer: "daily_journal",
21
+ lastIndexedAt: new Date().toISOString(),
22
+ });
23
+ if (entry.sourceRefs.length > 0) {
24
+ await this.provenanceRepository.linkEntrySources(entry.id, entry.sourceRefs);
25
+ }
26
+ return { assetPath: journalPath, hash };
27
+ }
28
+ async appendObservation(entry) {
29
+ const journalPath = resolveDailyJournalPath(entry.timestamp);
30
+ const serialized = serializeObservation(entry);
31
+ await appendLine(journalPath, serialized);
32
+ const hash = await hashFile(journalPath);
33
+ await this.assetRepository.upsert({
34
+ id: buildJournalAssetId(journalPath),
35
+ kind: "daily_journal",
36
+ path: journalPath,
37
+ hash,
38
+ version: 1,
39
+ layer: "daily_journal",
40
+ lastIndexedAt: new Date().toISOString(),
41
+ });
42
+ return { assetPath: journalPath, hash };
43
+ }
44
+ async generateDailyReport(input) {
45
+ const reportPath = resolveDailyReportPath(input.day);
46
+ const content = renderDailyReport(input);
47
+ await writeCanonicalArtifact(reportPath, content);
48
+ const hash = await hashFile(reportPath);
49
+ await this.assetRepository.upsert({
50
+ id: buildReportAssetId(input.day),
51
+ kind: "daily_report",
52
+ path: reportPath,
53
+ hash,
54
+ version: 1,
55
+ layer: "daily_journal",
56
+ lastIndexedAt: new Date().toISOString(),
57
+ });
58
+ await this.provenanceRepository.linkEntrySources(buildReportAssetId(input.day), [
59
+ ...input.activityRefs,
60
+ ...input.observationRefs,
61
+ ]);
62
+ return { assetPath: reportPath, hash };
63
+ }
64
+ async upsertCuratedMemory(candidate) {
65
+ const curatedPath = resolveCuratedPath(candidate.id);
66
+ const content = renderCuratedMemory(candidate);
67
+ await writeCanonicalArtifact(curatedPath, content);
68
+ const hash = await hashFile(curatedPath);
69
+ await this.assetRepository.upsert({
70
+ id: buildCuratedAssetId(candidate.id),
71
+ kind: "curated_memory",
72
+ path: curatedPath,
73
+ hash,
74
+ version: 1,
75
+ layer: "curated_memory",
76
+ lastIndexedAt: new Date().toISOString(),
77
+ });
78
+ if (candidate.sourceRefs.length > 0) {
79
+ await this.provenanceRepository.linkEntrySources(buildCuratedAssetId(candidate.id), candidate.sourceRefs);
80
+ }
81
+ return { assetPath: curatedPath, hash };
82
+ }
83
+ }
84
+ export function createDailyLogPipeline(assetRepository, provenanceRepository) {
85
+ return new DailyLogPipeline(assetRepository, provenanceRepository);
86
+ }
@@ -0,0 +1,11 @@
1
+ import type { StateDatabase } from "../db/index.js";
2
+ import type { IntentCommitRecord, IntentCommitRecordInput, IntentCommitState, IntentCommitOutcome } from "../../shared/types/index.js";
3
+ export interface EffectCommitStore {
4
+ createIntentCommitRecord(input: IntentCommitRecordInput): Promise<IntentCommitRecord>;
5
+ advanceIntentCommitState(id: string, state: IntentCommitState, metadata?: Record<string, unknown>): Promise<void>;
6
+ commitIntentOutcome(id: string, outcome: IntentCommitOutcome): Promise<void>;
7
+ loadIntentCommitRecord(intentId: string): Promise<IntentCommitRecord | null>;
8
+ abortIntentCommit(id: string, reason: string): Promise<void>;
9
+ markIntentCommitReconcile(id: string, details: Record<string, unknown>): Promise<void>;
10
+ }
11
+ export declare function createEffectCommitStore(db: StateDatabase["db"]): EffectCommitStore;
@@ -0,0 +1,93 @@
1
+ import * as crypto from "crypto";
2
+ import { eq } from "drizzle-orm";
3
+ import { intentCommitRecords } from "../db/schema/index.js";
4
+ const VALID_TRANSITIONS = {
5
+ planned: ["dispatched", "aborted"],
6
+ dispatched: ["externally_acknowledged", "aborted"],
7
+ externally_acknowledged: ["committed", "reconcile", "aborted"],
8
+ committed: [],
9
+ reconcile: ["planned", "aborted"],
10
+ aborted: [],
11
+ };
12
+ export function createEffectCommitStore(db) {
13
+ return {
14
+ async createIntentCommitRecord(input) {
15
+ const record = {
16
+ id: crypto.randomUUID(),
17
+ intentId: input.intentId,
18
+ decisionId: input.decisionId,
19
+ checkpointId: input.checkpointId ?? null,
20
+ state: input.state,
21
+ outcomeRef: null,
22
+ metadataJson: null,
23
+ updatedAt: new Date().toISOString(),
24
+ };
25
+ await db.insert(intentCommitRecords).values(record);
26
+ return {
27
+ id: record.id,
28
+ intentId: record.intentId,
29
+ decisionId: record.decisionId,
30
+ checkpointId: record.checkpointId ?? undefined,
31
+ state: record.state,
32
+ outcomeRef: undefined,
33
+ metadata: undefined,
34
+ updatedAt: record.updatedAt,
35
+ };
36
+ },
37
+ async advanceIntentCommitState(id, state, metadata) {
38
+ const existing = await db.query.intentCommitRecords.findFirst({
39
+ where: (tbl) => eq(tbl.id, id),
40
+ });
41
+ if (!existing)
42
+ throw new Error("intent_commit_not_found");
43
+ const currentState = existing.state;
44
+ const allowed = VALID_TRANSITIONS[currentState] ?? [];
45
+ if (!allowed.includes(state)) {
46
+ throw new Error(`invalid_state_transition: ${currentState} -> ${state}`);
47
+ }
48
+ await db.update(intentCommitRecords).set({
49
+ state,
50
+ metadataJson: metadata ? JSON.stringify(metadata) : null,
51
+ updatedAt: new Date().toISOString(),
52
+ }).where(eq(intentCommitRecords.id, id));
53
+ },
54
+ async commitIntentOutcome(id, outcome) {
55
+ await db.update(intentCommitRecords).set({
56
+ state: "committed",
57
+ outcomeRef: outcome.outcomeRef,
58
+ metadataJson: JSON.stringify({ traceId: outcome.traceId }),
59
+ updatedAt: new Date().toISOString(),
60
+ }).where(eq(intentCommitRecords.id, id));
61
+ },
62
+ async loadIntentCommitRecord(intentId) {
63
+ const record = await db.query.intentCommitRecords.findFirst({
64
+ where: (tbl) => eq(tbl.intentId, intentId),
65
+ });
66
+ if (!record)
67
+ return null;
68
+ return {
69
+ id: record.id,
70
+ intentId: record.intentId,
71
+ decisionId: record.decisionId,
72
+ checkpointId: record.checkpointId ?? undefined,
73
+ state: record.state,
74
+ outcomeRef: record.outcomeRef ?? undefined,
75
+ metadata: record.metadataJson ? JSON.parse(record.metadataJson) : undefined,
76
+ updatedAt: record.updatedAt,
77
+ };
78
+ },
79
+ async abortIntentCommit(id, _reason) {
80
+ await db.update(intentCommitRecords).set({
81
+ state: "aborted",
82
+ updatedAt: new Date().toISOString(),
83
+ }).where(eq(intentCommitRecords.id, id));
84
+ },
85
+ async markIntentCommitReconcile(id, details) {
86
+ await db.update(intentCommitRecords).set({
87
+ state: "reconcile",
88
+ metadataJson: JSON.stringify(details),
89
+ updatedAt: new Date().toISOString(),
90
+ }).where(eq(intentCommitRecords.id, id));
91
+ },
92
+ };
93
+ }
@@ -0,0 +1,40 @@
1
+ import type { StateDatabase } from "../db/index.js";
2
+ import { ProposalRepository } from "../repositories/proposal-repository.js";
3
+ import { AssetRepository } from "../repositories/asset-repository.js";
4
+ import { ProvenanceRepository } from "../repositories/provenance-repository.js";
5
+ export interface AnchorWriteProposal {
6
+ id: string;
7
+ targetAssetId: string;
8
+ beforeHash?: string;
9
+ afterHash?: string;
10
+ status: "draft" | "requires_review" | "approved" | "rejected" | "applied" | "conflicted";
11
+ proposedDiff: string;
12
+ reason: string;
13
+ supportingSources: string[];
14
+ confidence: number;
15
+ policyBasis?: string[];
16
+ riskFlags?: string[];
17
+ createdAt: string;
18
+ }
19
+ export interface ProposalAck {
20
+ proposalId: string;
21
+ proposalPath: string;
22
+ status: string;
23
+ }
24
+ export interface ApplyAck {
25
+ applied: boolean;
26
+ assetId: string;
27
+ hash: string;
28
+ }
29
+ export declare class GovernanceLayer {
30
+ private readonly proposalRepository;
31
+ private readonly assetRepository;
32
+ private readonly provenanceRepository;
33
+ constructor(proposalRepository: ProposalRepository, assetRepository: AssetRepository, provenanceRepository: ProvenanceRepository);
34
+ proposeAnchorWrite(proposal: AnchorWriteProposal): Promise<ProposalAck>;
35
+ applyGovernedAnchorWrite(proposalId: string): Promise<ApplyAck>;
36
+ approveProposal(proposalId: string): Promise<void>;
37
+ rejectProposal(proposalId: string): Promise<void>;
38
+ loadProposal(proposalId: string): Promise<AnchorWriteProposal | null>;
39
+ }
40
+ export declare function createGovernanceLayer(database: StateDatabase): GovernanceLayer;
@@ -0,0 +1,103 @@
1
+ import { ProposalRepository } from "../repositories/proposal-repository.js";
2
+ import { AssetRepository } from "../repositories/asset-repository.js";
3
+ import { ProvenanceRepository } from "../repositories/provenance-repository.js";
4
+ import { writeCanonicalArtifact, readText, hashFile, resolveProposalPath, renderProposal, applyDiff, } from "../memory/workspace/paths.js";
5
+ const CONFIDENCE_THRESHOLD_FOR_ANCHOR = 0.8;
6
+ export class GovernanceLayer {
7
+ proposalRepository;
8
+ assetRepository;
9
+ provenanceRepository;
10
+ constructor(proposalRepository, assetRepository, provenanceRepository) {
11
+ this.proposalRepository = proposalRepository;
12
+ this.assetRepository = assetRepository;
13
+ this.provenanceRepository = provenanceRepository;
14
+ }
15
+ async proposeAnchorWrite(proposal) {
16
+ if (!proposal.supportingSources.length) {
17
+ throw new Error("anchor_proposal_requires_sources");
18
+ }
19
+ if (proposal.confidence < CONFIDENCE_THRESHOLD_FOR_ANCHOR) {
20
+ throw new Error("anchor_proposal_confidence_too_low");
21
+ }
22
+ const proposalPath = resolveProposalPath(proposal.id);
23
+ const initialStatus = (proposal.riskFlags && proposal.riskFlags.length > 0) ? "requires_review" : "draft";
24
+ await writeCanonicalArtifact(proposalPath, renderProposal(proposal));
25
+ await this.proposalRepository.create({
26
+ id: proposal.id,
27
+ targetAssetId: proposal.targetAssetId,
28
+ beforeHash: proposal.beforeHash ?? null,
29
+ afterHash: proposal.afterHash ?? null,
30
+ status: initialStatus,
31
+ proposedDiff: proposal.proposedDiff,
32
+ reason: proposal.reason,
33
+ supportingSources: JSON.stringify(proposal.supportingSources),
34
+ confidence: proposal.confidence,
35
+ createdAt: proposal.createdAt ?? new Date().toISOString(),
36
+ });
37
+ if (proposal.supportingSources.length > 0) {
38
+ await this.provenanceRepository.linkEntrySources(proposal.id, proposal.supportingSources);
39
+ }
40
+ return { proposalId: proposal.id, proposalPath, status: initialStatus };
41
+ }
42
+ async applyGovernedAnchorWrite(proposalId) {
43
+ const proposal = await this.proposalRepository.findById(proposalId);
44
+ if (!proposal) {
45
+ throw new Error("proposal_not_found");
46
+ }
47
+ if (proposal.status !== "approved") {
48
+ throw new Error("proposal_not_approved");
49
+ }
50
+ const target = await this.assetRepository.findById(proposal.targetAssetId);
51
+ if (!target) {
52
+ throw new Error("target_asset_not_found");
53
+ }
54
+ const beforeContent = await readText(target.path);
55
+ const beforeHash = await hashFile(target.path);
56
+ if (proposal.beforeHash && proposal.beforeHash !== beforeHash) {
57
+ await this.proposalRepository.updateStatus(proposalId, "conflicted");
58
+ throw new Error("anchor_proposal_conflict");
59
+ }
60
+ const nextContent = applyDiff(beforeContent, proposal.proposedDiff);
61
+ await writeCanonicalArtifact(target.path, nextContent);
62
+ const hash = await hashFile(target.path);
63
+ await this.assetRepository.upsert({
64
+ ...target,
65
+ hash,
66
+ version: target.version + 1,
67
+ lastIndexedAt: new Date().toISOString(),
68
+ });
69
+ await this.proposalRepository.updateStatus(proposalId, "applied", hash);
70
+ await this.provenanceRepository.recordApply(proposalId, target.id, {
71
+ beforeHash,
72
+ afterHash: hash,
73
+ diff: proposal.proposedDiff,
74
+ });
75
+ return { applied: true, assetId: target.id, hash };
76
+ }
77
+ async approveProposal(proposalId) {
78
+ await this.proposalRepository.updateStatus(proposalId, "approved");
79
+ }
80
+ async rejectProposal(proposalId) {
81
+ await this.proposalRepository.updateStatus(proposalId, "rejected");
82
+ }
83
+ async loadProposal(proposalId) {
84
+ const record = await this.proposalRepository.findById(proposalId);
85
+ if (!record)
86
+ return null;
87
+ return {
88
+ id: record.id,
89
+ targetAssetId: record.targetAssetId,
90
+ beforeHash: record.beforeHash ?? undefined,
91
+ afterHash: record.afterHash ?? undefined,
92
+ status: record.status,
93
+ proposedDiff: record.proposedDiff,
94
+ reason: record.reason,
95
+ supportingSources: JSON.parse(record.supportingSources),
96
+ confidence: record.confidence,
97
+ createdAt: record.createdAt,
98
+ };
99
+ }
100
+ }
101
+ export function createGovernanceLayer(database) {
102
+ return new GovernanceLayer(new ProposalRepository(database), new AssetRepository(database), new ProvenanceRepository(database));
103
+ }
@@ -0,0 +1,5 @@
1
+ import type { PersonaCandidate, SceneContext } from "../../guidance/types.js";
2
+ export interface PersonaCandidateLoader {
3
+ loadPersonaCandidates(sceneContext: SceneContext): Promise<PersonaCandidate[]>;
4
+ }
5
+ export declare function createPersonaCandidateLoader(): PersonaCandidateLoader;
@@ -0,0 +1,41 @@
1
+ import path from "node:path";
2
+ import { readText, resolveAnchorPath } from "../memory/workspace/paths.js";
3
+ const ANCHOR_ASSET_SOURCES = [
4
+ { source: "SOUL", fileName: "SOUL.md" },
5
+ { source: "USER", fileName: "USER.md" },
6
+ { source: "IDENTITY", fileName: "IDENTITY.md" },
7
+ { source: "MEMORY", fileName: "MEMORY.md" },
8
+ ];
9
+ function toTags(sceneContext, fileName) {
10
+ const base = path.basename(fileName, ".md").toLowerCase();
11
+ return [sceneContext.sceneType, sceneContext.mode, base];
12
+ }
13
+ function toSnippetCandidates(input) {
14
+ const normalized = input.content
15
+ .split(/\r?\n{2,}/)
16
+ .map((chunk) => chunk.replace(/^#+\s+/gm, "").replace(/\s+/g, " ").trim())
17
+ .filter((chunk) => chunk.length > 0)
18
+ .slice(0, 6);
19
+ return normalized.map((text, index) => ({
20
+ id: `${input.source.toLowerCase()}-${index + 1}`,
21
+ source: input.source,
22
+ text,
23
+ tags: toTags(input.sceneContext, input.fileName),
24
+ }));
25
+ }
26
+ export function createPersonaCandidateLoader() {
27
+ return {
28
+ async loadPersonaCandidates(sceneContext) {
29
+ const loaded = await Promise.all(ANCHOR_ASSET_SOURCES.map(async ({ source, fileName }) => {
30
+ const content = await readText(resolveAnchorPath(fileName));
31
+ return toSnippetCandidates({
32
+ sceneContext,
33
+ source,
34
+ fileName,
35
+ content,
36
+ });
37
+ }));
38
+ return loaded.flat();
39
+ },
40
+ };
41
+ }
@@ -0,0 +1,40 @@
1
+ import type { StateDatabase } from "../db/index.js";
2
+ import { ProvenanceRepository } from "../repositories/provenance-repository.js";
3
+ import { ProposalRepository } from "../repositories/proposal-repository.js";
4
+ import { AssetRepository } from "../repositories/asset-repository.js";
5
+ export interface ProvenanceTrace {
6
+ assetId: string;
7
+ upstreamSources: string[];
8
+ proposalIds: string[];
9
+ applyIds: string[];
10
+ }
11
+ export interface ProvenanceDetail {
12
+ assetId: string;
13
+ assetPath?: string;
14
+ assetHash?: string;
15
+ assetVersion?: number;
16
+ currentContent?: string;
17
+ provenance: ProvenanceTrace;
18
+ proposals?: Array<{
19
+ id: string;
20
+ status: string;
21
+ targetAssetId: string;
22
+ proposedDiff: string;
23
+ reason: string;
24
+ confidence: number;
25
+ supportingSources: string[];
26
+ }>;
27
+ applies?: Array<{
28
+ id: string;
29
+ beforeHash: string;
30
+ afterHash: string;
31
+ }>;
32
+ }
33
+ export declare class ProvenanceService {
34
+ private readonly provenanceRepository;
35
+ private readonly proposalRepository;
36
+ private readonly assetRepository;
37
+ constructor(provenanceRepository: ProvenanceRepository, proposalRepository: ProposalRepository, assetRepository: AssetRepository);
38
+ explainProvenance(assetId: string): Promise<ProvenanceDetail>;
39
+ }
40
+ export declare function createProvenanceService(database: StateDatabase): ProvenanceService;
@@ -0,0 +1,43 @@
1
+ import { ProvenanceRepository } from "../repositories/provenance-repository.js";
2
+ import { ProposalRepository } from "../repositories/proposal-repository.js";
3
+ import { AssetRepository } from "../repositories/asset-repository.js";
4
+ export class ProvenanceService {
5
+ provenanceRepository;
6
+ proposalRepository;
7
+ assetRepository;
8
+ constructor(provenanceRepository, proposalRepository, assetRepository) {
9
+ this.provenanceRepository = provenanceRepository;
10
+ this.proposalRepository = proposalRepository;
11
+ this.assetRepository = assetRepository;
12
+ }
13
+ async explainProvenance(assetId) {
14
+ const asset = await this.assetRepository.findById(assetId);
15
+ const trace = await this.provenanceRepository.traceAsset(assetId);
16
+ const proposals = [];
17
+ for (const pid of trace.proposalIds) {
18
+ const p = await this.proposalRepository.findById(pid);
19
+ if (p) {
20
+ proposals.push({
21
+ id: p.id,
22
+ status: p.status,
23
+ targetAssetId: p.targetAssetId,
24
+ proposedDiff: p.proposedDiff,
25
+ reason: p.reason,
26
+ confidence: p.confidence,
27
+ supportingSources: JSON.parse(p.supportingSources),
28
+ });
29
+ }
30
+ }
31
+ return {
32
+ assetId,
33
+ assetPath: asset?.path,
34
+ assetHash: asset?.hash,
35
+ assetVersion: asset?.version,
36
+ provenance: trace,
37
+ proposals,
38
+ };
39
+ }
40
+ }
41
+ export function createProvenanceService(database) {
42
+ return new ProvenanceService(new ProvenanceRepository(database), new ProposalRepository(database), new AssetRepository(database));
43
+ }