@haaaiawd/second-nature 0.2.12 → 0.2.13

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 (59) hide show
  1. package/index.js +96 -6
  2. package/openclaw.plugin.json +1 -1
  3. package/package.json +1 -1
  4. package/runtime/cli/commands/index.js +85 -11
  5. package/runtime/cli/host-capability/host-discovery-port.d.ts +85 -0
  6. package/runtime/cli/host-capability/host-discovery-port.js +137 -0
  7. package/runtime/cli/ops/heartbeat-surface.d.ts +3 -3
  8. package/runtime/cli/ops/heartbeat-surface.js +6 -5
  9. package/runtime/cli/ops/ops-router.d.ts +6 -2
  10. package/runtime/cli/ops/ops-router.js +1273 -1145
  11. package/runtime/connectors/base/normalized-evidence-content.d.ts +4 -0
  12. package/runtime/connectors/base/normalized-evidence-content.js +21 -2
  13. package/runtime/connectors/evidence-normalizer.js +32 -1
  14. package/runtime/core/second-nature/action/action-closure-recorder.d.ts +2 -0
  15. package/runtime/core/second-nature/action/action-closure-recorder.js +49 -34
  16. package/runtime/core/second-nature/action/action-proposal-builder.js +3 -2
  17. package/runtime/core/second-nature/action/policy-bound-dispatch.d.ts +2 -0
  18. package/runtime/core/second-nature/action/policy-bound-dispatch.js +7 -3
  19. package/runtime/core/second-nature/control-plane/cycle-finalizer.d.ts +82 -0
  20. package/runtime/core/second-nature/control-plane/cycle-finalizer.js +187 -0
  21. package/runtime/core/second-nature/control-plane/heartbeat-orchestrator.js +13 -9
  22. package/runtime/core/second-nature/control-plane/real-runtime-spine.js +1 -1
  23. package/runtime/core/second-nature/guidance/guidance-proposal-consumer.d.ts +2 -1
  24. package/runtime/core/second-nature/guidance/guidance-proposal-consumer.js +4 -2
  25. package/runtime/core/second-nature/perception/judgment-engine.js +8 -4
  26. package/runtime/core/second-nature/perception/perception-builder.js +14 -2
  27. package/runtime/core/second-nature/quiet-dream/daily-rhythm-scheduler.js +30 -3
  28. package/runtime/core/second-nature/quiet-dream/dream-consolidation-runner.d.ts +5 -1
  29. package/runtime/core/second-nature/quiet-dream/dream-consolidation-runner.js +68 -29
  30. package/runtime/core/second-nature/quiet-dream/dream-scheduler.js +2 -1
  31. package/runtime/core/second-nature/quiet-dream/memory-projection-lifecycle.js +2 -1
  32. package/runtime/core/second-nature/quiet-dream/quiet-daily-review-builder.d.ts +1 -0
  33. package/runtime/core/second-nature/quiet-dream/quiet-daily-review-builder.js +33 -0
  34. package/runtime/observability/causal-loop-health.d.ts +2 -1
  35. package/runtime/observability/causal-loop-health.js +7 -0
  36. package/runtime/observability/loop-stage-event-sink.js +6 -1
  37. package/runtime/observability/loop-status.d.ts +2 -0
  38. package/runtime/observability/loop-status.js +14 -1
  39. package/runtime/observability/services/heartbeat-digest-assembler.d.ts +3 -0
  40. package/runtime/observability/services/heartbeat-digest-assembler.js +9 -0
  41. package/runtime/shared/degraded-status-classifier.d.ts +16 -0
  42. package/runtime/shared/degraded-status-classifier.js +68 -0
  43. package/runtime/shared/evidence-level-classifier.d.ts +61 -0
  44. package/runtime/shared/evidence-level-classifier.js +116 -0
  45. package/runtime/shared/provenance-tier.d.ts +37 -0
  46. package/runtime/shared/provenance-tier.js +97 -0
  47. package/runtime/shared/setup-ack.d.ts +54 -0
  48. package/runtime/shared/setup-ack.js +108 -0
  49. package/runtime/shared/source-ref-compat.js +5 -2
  50. package/runtime/shared/types/v8-contracts.d.ts +13 -2
  51. package/runtime/storage/db/index.js +71 -28
  52. package/runtime/storage/db/migrations/v8-005-single-status-schema.js +2 -2
  53. package/runtime/storage/db/migrations/v8-006-loop-stage-event-proof-trace-columns.d.ts +9 -0
  54. package/runtime/storage/db/migrations/v8-006-loop-stage-event-proof-trace-columns.js +15 -0
  55. package/runtime/storage/db/schema/v8-entities.d.ts +76 -0
  56. package/runtime/storage/db/schema/v8-entities.js +4 -0
  57. package/runtime/storage/services/write-validation-gate.js +1 -1
  58. package/runtime/storage/v8-state-stores.d.ts +7 -2
  59. package/runtime/storage/v8-state-stores.js +37 -19
@@ -0,0 +1,108 @@
1
+ /**
2
+ * Setup Ack Truth Contract (T-ROS.R.8)
3
+ *
4
+ * Core logic: define the canonical SetupAck schema and a validator that rejects
5
+ * `placedIn: "unspecified"`, missing fields, unknown writers, and hand-written
6
+ * files that do not satisfy the schema.
7
+ *
8
+ * Design authority:
9
+ * - `.anws/v8/04_SYSTEM_DESIGN/runtime-ops-system.md §3.2`
10
+ *
11
+ * Dependencies: none (plain validation to keep plugin load lightweight)
12
+ * Boundary: Pure validation; no I/O.
13
+ * Test coverage: tests/unit/shared/setup-ack-validator.test.ts
14
+ */
15
+ export const SETUP_ACK_SCHEMA_VERSION = 1;
16
+ const VALID_PLACEMENTS = new Set([
17
+ "workspace_guide",
18
+ "host_skill_registry",
19
+ "agent_profile",
20
+ "manual_operator_instruction",
21
+ ]);
22
+ const VALID_WRITERS = new Set([
23
+ "setup_ack_command",
24
+ "host_setup_bridge",
25
+ ]);
26
+ export function validateSetupAck(raw) {
27
+ const errors = [];
28
+ if (raw.schemaVersion !== SETUP_ACK_SCHEMA_VERSION) {
29
+ errors.push({
30
+ ok: false,
31
+ field: "schemaVersion",
32
+ reason: `schemaVersion must be ${SETUP_ACK_SCHEMA_VERSION}`,
33
+ repairAction: "Re-run setup_ack with a current client that writes schemaVersion=1.",
34
+ });
35
+ }
36
+ const placedIn = typeof raw.placedIn === "string" ? raw.placedIn : undefined;
37
+ if (!placedIn || placedIn === "unspecified") {
38
+ errors.push({
39
+ ok: false,
40
+ field: "placedIn",
41
+ reason: "placedIn is missing or 'unspecified'",
42
+ repairAction: "Provide a concrete placement target such as 'workspace_guide' or 'host_skill_registry'.",
43
+ });
44
+ }
45
+ else if (!VALID_PLACEMENTS.has(placedIn)) {
46
+ errors.push({
47
+ ok: false,
48
+ field: "placedIn",
49
+ reason: `placedIn '${placedIn}' is not a recognized placement target`,
50
+ repairAction: `Use one of: ${Array.from(VALID_PLACEMENTS).join(", ")}.`,
51
+ });
52
+ }
53
+ const placementProofRef = typeof raw.placementProofRef === "string" ? raw.placementProofRef : undefined;
54
+ if (!placementProofRef || placementProofRef.trim().length === 0) {
55
+ errors.push({
56
+ ok: false,
57
+ field: "placementProofRef",
58
+ reason: "placementProofRef is missing or empty",
59
+ repairAction: "Provide a proof reference such as a host skill registry id, file path, or anchor URI.",
60
+ });
61
+ }
62
+ const writer = typeof raw.writer === "string" ? raw.writer : undefined;
63
+ if (!writer || !VALID_WRITERS.has(writer)) {
64
+ errors.push({
65
+ ok: false,
66
+ field: "writer",
67
+ reason: `writer '${writer ?? "missing"}' is not authorized`,
68
+ repairAction: `Writer must be one of: ${Array.from(VALID_WRITERS).join(", ")}.`,
69
+ });
70
+ }
71
+ const acknowledgedAt = typeof raw.acknowledgedAt === "string" ? raw.acknowledgedAt : undefined;
72
+ if (!acknowledgedAt || Number.isNaN(Date.parse(acknowledgedAt))) {
73
+ errors.push({
74
+ ok: false,
75
+ field: "acknowledgedAt",
76
+ reason: "acknowledgedAt is missing or not a valid ISO timestamp",
77
+ repairAction: "Re-run setup_ack so the client can write a fresh timestamp.",
78
+ });
79
+ }
80
+ if (errors.length > 0) {
81
+ return { ok: false, errors };
82
+ }
83
+ return {
84
+ ok: true,
85
+ ack: {
86
+ schemaVersion: SETUP_ACK_SCHEMA_VERSION,
87
+ acknowledgedAt: acknowledgedAt,
88
+ placedIn: placedIn,
89
+ placementProofRef: placementProofRef,
90
+ writer: writer,
91
+ hostName: typeof raw.hostName === "string" ? raw.hostName : undefined,
92
+ hostVersion: typeof raw.hostVersion === "string" ? raw.hostVersion : undefined,
93
+ acceptedBy: typeof raw.acceptedBy === "string" ? raw.acceptedBy : undefined,
94
+ note: typeof raw.note === "string" ? raw.note : undefined,
95
+ },
96
+ };
97
+ }
98
+ /**
99
+ * Check whether a raw marker object can be considered a complete ack.
100
+ * Hand-written files are treated as incomplete until verified.
101
+ */
102
+ export function isSetupAckComplete(raw) {
103
+ const result = validateSetupAck(raw);
104
+ if (result.ok) {
105
+ return { complete: true, ack: result.ack };
106
+ }
107
+ return { complete: false, errors: result.errors };
108
+ }
@@ -15,6 +15,11 @@ export function sourceRefFamilyFromLegacyKind(kind) {
15
15
  }
16
16
  }
17
17
  export function legacyKindFromSourceRef(ref) {
18
+ // Check family first so canonical connector_result refs with platform://
19
+ // URIs are not incorrectly downgraded to "platform_item".
20
+ if (ref.family === "connector_result") {
21
+ return "connector_result";
22
+ }
18
23
  if (ref.uri.startsWith("platform://")) {
19
24
  return "platform_item";
20
25
  }
@@ -25,8 +30,6 @@ export function legacyKindFromSourceRef(ref) {
25
30
  return "user_anchor";
26
31
  }
27
32
  switch (ref.family) {
28
- case "connector_result":
29
- return "connector_result";
30
33
  case "judgment":
31
34
  return "decision_record";
32
35
  case "evidence":
@@ -38,6 +38,12 @@ export interface SourceRef {
38
38
  resolveStatus?: SourceResolveStatus;
39
39
  resolveFailureReason?: string;
40
40
  }
41
+ export interface ProvenanceBundle {
42
+ sourceRefs: SourceRef[];
43
+ proofRefs: SourceRef[];
44
+ traceRefs: SourceRef[];
45
+ }
46
+ export type ProvenanceTier = "source" | "proof" | "trace";
41
47
  export type HeartbeatCycleStatus = "started" | "completed" | "failed" | "degraded";
42
48
  export interface HeartbeatCycleTrace {
43
49
  cycleId: string;
@@ -59,11 +65,14 @@ export interface LoopStageEvent {
59
65
  status: LoopStageEventStatus;
60
66
  reason?: V8ReasonCode;
61
67
  sourceRefs: SourceRef[];
68
+ proofRefs?: SourceRef[];
69
+ traceRefs?: SourceRef[];
62
70
  redactionClass: RedactionClass;
63
71
  occurredAt: string;
64
72
  expectedDownstreamByCycle?: number;
65
73
  payloadJson?: string;
66
74
  }
75
+ export type EvidenceLevel = "carrier_ack" | "contract_smoke" | "state_present" | "real_runtime" | "durable_verified";
67
76
  export type MemoryReviewClosureSubtype = "remember_for_review";
68
77
  export interface MemoryReviewCandidateClosure {
69
78
  closureSubtype: MemoryReviewClosureSubtype;
@@ -75,12 +84,14 @@ export interface MemoryReviewCandidateClosure {
75
84
  sourceRefs: [SourceRef, ...SourceRef[]];
76
85
  }
77
86
  export interface DegradedOperationResult {
78
- status: "degraded" | "blocked";
87
+ status: "empty" | "partial" | "blocked" | "unavailable" | "unsafe";
79
88
  reason: V8ReasonCode;
80
89
  ownerStage: LoopStage;
81
90
  sourceRefs: SourceRef[];
91
+ proofRefs?: SourceRef[];
92
+ traceRefs?: SourceRef[];
82
93
  operatorNextAction: string;
83
94
  retryable: boolean;
84
95
  }
85
- export type V8ReasonCode = "quiet_completed" | "quiet_empty_input" | "quiet_state_unreadable" | "quiet_validation_failed" | "quiet_redaction_blocked" | "dream_scheduled" | "dream_scheduled_stalled" | "dream_scheduler_unavailable" | "dream_started" | "dream_completed" | "dream_failed" | "dream_blocked_redaction" | "dream_interval_active" | "dream_rules_only" | "dream_model_timeout" | "projection_candidate_created" | "projection_accepted" | "projection_rejected" | "projection_superseded" | "projection_topic_matched" | "proposal_created" | "proposal_no_action" | "proposal_missing_source_refs" | "proposal_risk_blocked" | "policy_allowed" | "policy_deferred_owner_confirmation" | "policy_downgraded_to_draft" | "policy_denied_missing_permission" | "policy_denied_high_risk" | "policy_denied_breaker_open" | "guidance_unavailable" | "closure_completed" | "closure_no_action" | "closure_denied" | "closure_deferred" | "closure_downgraded" | "closure_downgraded_without_draft" | "closure_failed" | "perception_rules_only" | "perception_contract_drift" | "evidence_batch_empty" | "evidence_batch_truncated" | "evidence_content_missing" | "judgment_low_confidence" | "judgment_missing_source_refs" | "source_refs_unresolved" | "state_unreadable" | "stage_event_missing" | "ingestion_no_data" | "ingestion_empty" | "ingestion_state_unreadable" | "ingestion_connector_failed" | "execution_completed" | "execution_failed" | "execution_timeout" | "execution_unavailable";
96
+ export type V8ReasonCode = "quiet_completed" | "quiet_empty_input" | "quiet_state_unreadable" | "quiet_validation_failed" | "quiet_redaction_blocked" | "dream_scheduled" | "dream_scheduled_stalled" | "dream_scheduler_unavailable" | "dream_started" | "dream_completed" | "dream_failed" | "dream_blocked_redaction" | "dream_blocked_no_content" | "dream_blocked_private_redacted" | "dream_blocked_credential" | "dream_blocked_validation_failed" | "dream_interval_active" | "dream_rules_only" | "dream_model_timeout" | "projection_candidate_created" | "projection_accepted" | "projection_rejected" | "projection_superseded" | "projection_topic_matched" | "proposal_created" | "proposal_no_action" | "proposal_missing_source_refs" | "proposal_risk_blocked" | "policy_allowed" | "policy_deferred_owner_confirmation" | "policy_downgraded_to_draft" | "policy_denied_missing_permission" | "policy_denied_high_risk" | "policy_denied_breaker_open" | "guidance_unavailable" | "closure_completed" | "closure_no_action" | "closure_denied" | "closure_deferred" | "closure_downgraded" | "closure_downgraded_without_draft" | "closure_failed" | "closure_idempotency_conflict" | "closure_unavailable" | "perception_rules_only" | "perception_contract_drift" | "evidence_batch_empty" | "evidence_batch_truncated" | "evidence_content_missing" | "judgment_low_confidence" | "judgment_missing_source_refs" | "source_refs_unresolved" | "state_unreadable" | "stage_event_missing" | "ingestion_no_data" | "ingestion_empty" | "ingestion_state_unreadable" | "ingestion_connector_failed" | "execution_completed" | "execution_failed" | "execution_timeout" | "execution_unavailable";
86
97
  export declare const ACTION_KIND_REGISTRY: Readonly<Record<PlatformNeutralActionKind, ActionKindMetadata>>;
@@ -232,10 +232,12 @@ const STATE_SCHEMA_SQL = `
232
232
  status TEXT NOT NULL,
233
233
  reason TEXT,
234
234
  next_state TEXT,
235
- source_refs_json TEXT NOT NULL,
236
- redaction_class TEXT NOT NULL DEFAULT 'none',
237
- payload_json TEXT
238
- );
235
+ source_refs_json TEXT NOT NULL,
236
+ proof_refs_json TEXT,
237
+ trace_refs_json TEXT,
238
+ redaction_class TEXT NOT NULL DEFAULT 'none',
239
+ payload_json TEXT
240
+ );
239
241
  CREATE TABLE IF NOT EXISTS quiet_daily_review (
240
242
  id TEXT PRIMARY KEY,
241
243
  created_at TEXT NOT NULL,
@@ -254,20 +256,20 @@ const STATE_SCHEMA_SQL = `
254
256
  quiet_review_id TEXT NOT NULL,
255
257
  status TEXT NOT NULL,
256
258
  reason TEXT,
257
- source_refs_json TEXT NOT NULL,
258
- redaction_class TEXT NOT NULL DEFAULT 'none',
259
- payload_json TEXT
260
- );
259
+ source_refs_json TEXT NOT NULL,
260
+ redaction_class TEXT NOT NULL DEFAULT 'none',
261
+ payload_json TEXT
262
+ );
261
263
  CREATE TABLE IF NOT EXISTS long_term_memory_projection (
262
264
  id TEXT PRIMARY KEY,
263
265
  created_at TEXT NOT NULL,
264
266
  candidate_id TEXT NOT NULL,
265
267
  topic_key TEXT NOT NULL,
266
268
  status TEXT NOT NULL DEFAULT 'candidate',
267
- source_refs_json TEXT NOT NULL,
268
- redaction_class TEXT NOT NULL DEFAULT 'none',
269
- payload_json TEXT
270
- );
269
+ source_refs_json TEXT NOT NULL,
270
+ redaction_class TEXT NOT NULL DEFAULT 'none',
271
+ payload_json TEXT
272
+ );
271
273
  CREATE TABLE IF NOT EXISTS heartbeat_cycle_trace (
272
274
  id TEXT PRIMARY KEY,
273
275
  cycle_sequence INTEGER NOT NULL,
@@ -276,11 +278,11 @@ const STATE_SCHEMA_SQL = `
276
278
  input_count INTEGER NOT NULL DEFAULT 0,
277
279
  output_count INTEGER NOT NULL DEFAULT 0,
278
280
  expected_downstream_by_cycle INTEGER,
279
- status TEXT NOT NULL,
280
- source_refs_json TEXT,
281
- redaction_class TEXT NOT NULL DEFAULT 'none',
282
- payload_json TEXT
283
- );
281
+ status TEXT NOT NULL,
282
+ source_refs_json TEXT,
283
+ redaction_class TEXT NOT NULL DEFAULT 'none',
284
+ payload_json TEXT
285
+ );
284
286
  CREATE TABLE IF NOT EXISTS loop_stage_event (
285
287
  id TEXT PRIMARY KEY,
286
288
  cycle_id TEXT NOT NULL,
@@ -289,11 +291,13 @@ const STATE_SCHEMA_SQL = `
289
291
  status TEXT NOT NULL,
290
292
  reason TEXT,
291
293
  source_refs_json TEXT NOT NULL,
294
+ proof_refs_json TEXT,
295
+ trace_refs_json TEXT,
292
296
  redaction_class TEXT NOT NULL DEFAULT 'none',
293
- occurred_at TEXT NOT NULL,
294
- expected_downstream_by_cycle INTEGER,
295
- payload_json TEXT
296
- );
297
+ occurred_at TEXT NOT NULL,
298
+ expected_downstream_by_cycle INTEGER,
299
+ payload_json TEXT
300
+ );
297
301
  CREATE TABLE IF NOT EXISTS impulse_context_artifact (
298
302
  id TEXT PRIMARY KEY,
299
303
  created_at TEXT NOT NULL,
@@ -365,20 +369,19 @@ function applyStateSchemaMigrations(sqlite) {
365
369
  // v8-004-schema-closure. Fresh DBs already have these from bootstrap SQL.
366
370
  // Each statement is wrapped individually so duplicate-column errors are
367
371
  // harmless and do not block startup.
368
- const migrations = [
372
+ const addColumnMigrations = [
369
373
  "ALTER TABLE policy_records ADD COLUMN outreach_daily_budget INTEGER NOT NULL DEFAULT 2",
370
374
  "ALTER TABLE action_closure_record ADD COLUMN platform_id TEXT",
371
375
  "ALTER TABLE action_closure_record ADD COLUMN capability_id TEXT",
372
376
  "ALTER TABLE quiet_daily_review ADD COLUMN closure_refs_json TEXT",
373
377
  "ALTER TABLE connector_cooldown_state ADD COLUMN terminal_count INTEGER NOT NULL DEFAULT 0",
378
+ "ALTER TABLE loop_stage_event ADD COLUMN proof_refs_json TEXT",
379
+ "ALTER TABLE loop_stage_event ADD COLUMN trace_refs_json TEXT",
380
+ "ALTER TABLE action_closure_record ADD COLUMN proof_refs_json TEXT",
381
+ "ALTER TABLE action_closure_record ADD COLUMN trace_refs_json TEXT",
374
382
  "CREATE INDEX IF NOT EXISTS connector_cooldown_state_platform_capability_idx ON connector_cooldown_state(platform_id, capability_id)",
375
- "ALTER TABLE action_closure_record DROP COLUMN lifecycle_status",
376
- "ALTER TABLE dream_consolidation_run DROP COLUMN lifecycle_status",
377
- "ALTER TABLE long_term_memory_projection DROP COLUMN lifecycle_status",
378
- "ALTER TABLE heartbeat_cycle_trace DROP COLUMN lifecycle_status",
379
- "ALTER TABLE loop_stage_event DROP COLUMN lifecycle_status",
380
383
  ];
381
- for (const sql of migrations) {
384
+ for (const sql of addColumnMigrations) {
382
385
  try {
383
386
  sqlite.exec(sql);
384
387
  }
@@ -386,6 +389,46 @@ function applyStateSchemaMigrations(sqlite) {
386
389
  /* duplicate column / already migrated */
387
390
  }
388
391
  }
392
+ // DROP COLUMN requires SQLite ≥ 3.35.0. Guard against older native
393
+ // bindings where the statement would silently fail (caught by try/catch)
394
+ // yet leave lifecycle_status in place while the Drizzle schema no longer
395
+ // declares it, masking an incomplete cleanup.
396
+ const vResult = sqlite.exec("SELECT sqlite_version() AS ver");
397
+ const ver = String(vResult[0]?.values[0]?.[0] ?? "0.0.0");
398
+ const [major, minor] = ver.split(".").map(Number);
399
+ const supportsDropColumn = major > 3 || (major === 3 && minor >= 35);
400
+ const dropColumnTables = [
401
+ "action_closure_record",
402
+ "dream_consolidation_run",
403
+ "long_term_memory_projection",
404
+ "heartbeat_cycle_trace",
405
+ "loop_stage_event",
406
+ ];
407
+ for (const table of dropColumnTables) {
408
+ try {
409
+ if (supportsDropColumn) {
410
+ sqlite.exec(`ALTER TABLE ${table} DROP COLUMN lifecycle_status`);
411
+ }
412
+ else {
413
+ // Rebuild the table without lifecycle_status for SQLite < 3.35.0.
414
+ const info = sqlite.exec(`PRAGMA table_info(${table})`);
415
+ if (!info[0])
416
+ continue;
417
+ const nameIdx = info[0].columns.indexOf("name");
418
+ const allNames = info[0].values.map((row) => String(row[nameIdx]));
419
+ const kept = allNames.filter((n) => n !== "lifecycle_status");
420
+ if (kept.length === allNames.length)
421
+ continue; // column already absent
422
+ const colList = kept.join(", ");
423
+ sqlite.exec(`CREATE TABLE ${table}_backup AS SELECT ${colList} FROM ${table}`);
424
+ sqlite.exec(`DROP TABLE ${table}`);
425
+ sqlite.exec(`ALTER TABLE ${table}_backup RENAME TO ${table}`);
426
+ }
427
+ }
428
+ catch {
429
+ /* column already removed or table missing */
430
+ }
431
+ }
389
432
  }
390
433
  export function createStateDatabase(filename = "state.db") {
391
434
  const dbPath = resolveDbPath(filename);
@@ -10,7 +10,7 @@
10
10
  export const V8_005_SINGLE_STATUS_SCHEMA = {
11
11
  version: 9,
12
12
  label: "v8-single-status-schema",
13
- sql: `
14
- SELECT 1;
13
+ sql: `
14
+ SELECT 1;
15
15
  `,
16
16
  };
@@ -0,0 +1,9 @@
1
+ /**
2
+ * v8-006 — Add proof/trace refs columns to loop_stage_event.
3
+ *
4
+ * The loop_stage_event table was created without proof_refs_json and
5
+ * trace_refs_json columns. This migration adds them as nullable TEXT columns
6
+ * so the v8 provenance tier write path can persist proofRefs and traceRefs.
7
+ */
8
+ import type { Migration } from "../migration-runner.js";
9
+ export declare const V8_006_LOOP_STAGE_EVENT_PROOF_TRACE_COLUMNS: Migration;
@@ -0,0 +1,15 @@
1
+ /**
2
+ * v8-006 — Add proof/trace refs columns to loop_stage_event.
3
+ *
4
+ * The loop_stage_event table was created without proof_refs_json and
5
+ * trace_refs_json columns. This migration adds them as nullable TEXT columns
6
+ * so the v8 provenance tier write path can persist proofRefs and traceRefs.
7
+ */
8
+ export const V8_006_LOOP_STAGE_EVENT_PROOF_TRACE_COLUMNS = {
9
+ version: 6,
10
+ label: "v8_loop_stage_event_proof_trace_columns",
11
+ sql: `
12
+ ALTER TABLE loop_stage_event ADD COLUMN proof_refs_json TEXT;
13
+ ALTER TABLE loop_stage_event ADD COLUMN trace_refs_json TEXT;
14
+ `,
15
+ };
@@ -968,6 +968,44 @@ export declare const actionClosureRecord: import("drizzle-orm/sqlite-core").SQLi
968
968
  }, {}, {
969
969
  length: number | undefined;
970
970
  }>;
971
+ proofRefsJson: import("drizzle-orm/sqlite-core").SQLiteColumn<{
972
+ name: "proof_refs_json";
973
+ tableName: "action_closure_record";
974
+ dataType: "string";
975
+ columnType: "SQLiteText";
976
+ data: string;
977
+ driverParam: string;
978
+ notNull: false;
979
+ hasDefault: false;
980
+ isPrimaryKey: false;
981
+ isAutoincrement: false;
982
+ hasRuntimeDefault: false;
983
+ enumValues: [string, ...string[]];
984
+ baseColumn: never;
985
+ identity: undefined;
986
+ generated: undefined;
987
+ }, {}, {
988
+ length: number | undefined;
989
+ }>;
990
+ traceRefsJson: import("drizzle-orm/sqlite-core").SQLiteColumn<{
991
+ name: "trace_refs_json";
992
+ tableName: "action_closure_record";
993
+ dataType: "string";
994
+ columnType: "SQLiteText";
995
+ data: string;
996
+ driverParam: string;
997
+ notNull: false;
998
+ hasDefault: false;
999
+ isPrimaryKey: false;
1000
+ isAutoincrement: false;
1001
+ hasRuntimeDefault: false;
1002
+ enumValues: [string, ...string[]];
1003
+ baseColumn: never;
1004
+ identity: undefined;
1005
+ generated: undefined;
1006
+ }, {}, {
1007
+ length: number | undefined;
1008
+ }>;
971
1009
  redactionClass: import("drizzle-orm/sqlite-core").SQLiteColumn<{
972
1010
  name: "redaction_class";
973
1011
  tableName: "action_closure_record";
@@ -1873,6 +1911,44 @@ export declare const loopStageEvent: import("drizzle-orm/sqlite-core").SQLiteTab
1873
1911
  }, {}, {
1874
1912
  length: number | undefined;
1875
1913
  }>;
1914
+ proofRefsJson: import("drizzle-orm/sqlite-core").SQLiteColumn<{
1915
+ name: "proof_refs_json";
1916
+ tableName: "loop_stage_event";
1917
+ dataType: "string";
1918
+ columnType: "SQLiteText";
1919
+ data: string;
1920
+ driverParam: string;
1921
+ notNull: false;
1922
+ hasDefault: false;
1923
+ isPrimaryKey: false;
1924
+ isAutoincrement: false;
1925
+ hasRuntimeDefault: false;
1926
+ enumValues: [string, ...string[]];
1927
+ baseColumn: never;
1928
+ identity: undefined;
1929
+ generated: undefined;
1930
+ }, {}, {
1931
+ length: number | undefined;
1932
+ }>;
1933
+ traceRefsJson: import("drizzle-orm/sqlite-core").SQLiteColumn<{
1934
+ name: "trace_refs_json";
1935
+ tableName: "loop_stage_event";
1936
+ dataType: "string";
1937
+ columnType: "SQLiteText";
1938
+ data: string;
1939
+ driverParam: string;
1940
+ notNull: false;
1941
+ hasDefault: false;
1942
+ isPrimaryKey: false;
1943
+ isAutoincrement: false;
1944
+ hasRuntimeDefault: false;
1945
+ enumValues: [string, ...string[]];
1946
+ baseColumn: never;
1947
+ identity: undefined;
1948
+ generated: undefined;
1949
+ }, {}, {
1950
+ length: number | undefined;
1951
+ }>;
1876
1952
  redactionClass: import("drizzle-orm/sqlite-core").SQLiteColumn<{
1877
1953
  name: "redaction_class";
1878
1954
  tableName: "loop_stage_event";
@@ -83,6 +83,8 @@ export const actionClosureRecord = sqliteTable("action_closure_record", {
83
83
  reason: text("reason"),
84
84
  nextState: text("next_state"),
85
85
  sourceRefsJson: text("source_refs_json").notNull(),
86
+ proofRefsJson: text("proof_refs_json"),
87
+ traceRefsJson: text("trace_refs_json"),
86
88
  redactionClass: text("redaction_class").notNull().default("none"),
87
89
  payloadJson: text("payload_json"),
88
90
  });
@@ -154,6 +156,8 @@ export const loopStageEvent = sqliteTable("loop_stage_event", {
154
156
  status: text("status").notNull(),
155
157
  reason: text("reason"),
156
158
  sourceRefsJson: text("source_refs_json").notNull(),
159
+ proofRefsJson: text("proof_refs_json"),
160
+ traceRefsJson: text("trace_refs_json"),
157
161
  redactionClass: text("redaction_class").notNull().default("none"),
158
162
  occurredAt: text("occurred_at").notNull(),
159
163
  expectedDownstreamByCycle: integer("expected_downstream_by_cycle"),
@@ -115,7 +115,7 @@ const IDENTIFIER_FIELD_NAMES = new Set([
115
115
  "id",
116
116
  "runId",
117
117
  "run_id",
118
- "SourceRefTuple",
118
+ "sourceRef",
119
119
  "source_ref",
120
120
  "sourceRefs",
121
121
  "source_refs_json",
@@ -82,8 +82,11 @@ export declare function readJudgmentVerdictById(db: StateDatabase, id: string):
82
82
  row?: JudgmentVerdictRecord;
83
83
  degraded?: DegradedOperationResult;
84
84
  }>;
85
- export declare function writeActionClosureRecord(db: StateDatabase, row: Omit<ActionClosureRecordInsert, "sourceRefsJson"> & {
85
+ export declare function writeActionClosureRecord(db: StateDatabase, row: Omit<ActionClosureRecordInsert, "sourceRefsJson" | "proofRefsJson" | "traceRefsJson" | "payloadJson"> & {
86
86
  sourceRefs: SourceRef[];
87
+ proofRefs?: SourceRef[];
88
+ traceRefs?: SourceRef[];
89
+ payload?: Record<string, unknown>;
87
90
  }): Promise<{
88
91
  id: string;
89
92
  } | DegradedOperationResult>;
@@ -173,8 +176,10 @@ export declare function readHeartbeatCycleTraces(db: StateDatabase, limit?: numb
173
176
  rows: HeartbeatCycleTraceRecord[];
174
177
  degraded?: DegradedOperationResult;
175
178
  }>;
176
- export declare function writeLoopStageEvent(db: StateDatabase, row: Omit<NewLoopStageEventRecord, "sourceRefsJson"> & {
179
+ export declare function writeLoopStageEvent(db: StateDatabase, row: Omit<NewLoopStageEventRecord, "sourceRefsJson" | "proofRefsJson" | "traceRefsJson"> & {
177
180
  sourceRefs: SourceRef[];
181
+ proofRefs?: SourceRef[];
182
+ traceRefs?: SourceRef[];
178
183
  }): Promise<{
179
184
  id: string;
180
185
  } | DegradedOperationResult>;