thinkwork-cli 0.13.0 → 0.13.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (178) hide show
  1. package/dist/{api-client-JUBCQQDF.js → api-client-JYZXYQJR.js} +3 -1
  2. package/dist/bowser-6Z6JFAIR.js +2822 -0
  3. package/dist/chunk-DV3MRBR5.js +43 -0
  4. package/dist/chunk-DVPBI5HM.js +1728 -0
  5. package/dist/chunk-EI5ZX7CN.js +522 -0
  6. package/dist/chunk-EUJ7X6YD.js +126 -0
  7. package/dist/chunk-GG5WKBOX.js +436 -0
  8. package/dist/chunk-I64EZSU5.js +358 -0
  9. package/dist/chunk-ILZKG5WV.js +6151 -0
  10. package/dist/chunk-KMIJ5KGT.js +128 -0
  11. package/dist/chunk-OCPHU34C.js +996 -0
  12. package/dist/chunk-QOERT44A.js +3286 -0
  13. package/dist/chunk-XYM7PE2A.js +2264 -0
  14. package/dist/{chunk-STY44FQO.js → chunk-Z2F6RJFR.js} +12 -18
  15. package/dist/cli.js +72564 -18884
  16. package/dist/dist-es-CRV46D5B.js +315 -0
  17. package/dist/dist-es-DCY4IC3Y.js +2000 -0
  18. package/dist/dist-es-ENBUC3JP.js +14726 -0
  19. package/dist/dist-es-G54LBMRN.js +48 -0
  20. package/dist/dist-es-G7PTG75M.js +176 -0
  21. package/dist/dist-es-GKDBE7E6.js +88 -0
  22. package/dist/dist-es-HY3535OI.js +70 -0
  23. package/dist/dist-es-KL7Y5NB2.js +377 -0
  24. package/dist/dist-es-LDE437AM.js +170 -0
  25. package/dist/dist-es-P26FWFLT.js +485 -0
  26. package/dist/dist-es-Q57SZXZ7.js +70 -0
  27. package/dist/dist-es-R7FGL2IB.js +88 -0
  28. package/dist/dist-es-USORBXZ5.js +318 -0
  29. package/dist/dist-es-ZKC2QKD2.js +377 -0
  30. package/dist/drizzle/0076_scheduled_jobs_marco_backfill.sql +2 -1
  31. package/dist/drizzle/0079_seed_tenant_customize_catalog.sql +1 -0
  32. package/dist/drizzle/0090_brain_schema_extraction.sql +10 -0
  33. package/dist/drizzle/0132_drop_computer_tables.sql +3 -0
  34. package/dist/drizzle/0160_compliance_event_types_plugins.sql +2 -0
  35. package/dist/drizzle/0214_think137_drop_judge_evidence_roi.sql +1 -0
  36. package/dist/drizzle/0216_drop_agent_loop_versions_goal_worker_policy.sql +1 -0
  37. package/dist/drizzle/0227_analyst_reader_role.sql +106 -38
  38. package/dist/drizzle/0230_analyst_rls.sql +192 -66
  39. package/dist/drizzle/0232_memory_source_thin_ledger.sql +176 -0
  40. package/dist/drizzle/0232_message_source_event_id.sql +9 -0
  41. package/dist/drizzle/0233_msteams_install_and_links.sql +151 -0
  42. package/dist/drizzle/0233_workflow_memory_stage_tokens.sql +20 -0
  43. package/dist/drizzle/0234_memory_claim_lifecycle.sql +160 -0
  44. package/dist/drizzle/0235_workflow_token_execution_claim.sql +34 -0
  45. package/dist/drizzle/0236_memory_retraction_fencing.sql +50 -0
  46. package/dist/drizzle/0237_memory_claims_active_value_uidx.sql +172 -0
  47. package/dist/drizzle/0238_memory_erase_generation_fence.sql +97 -0
  48. package/dist/drizzle/0239_canonical_entity_identity.sql +257 -0
  49. package/dist/drizzle/0240_memory_personal_scope.sql +45 -0
  50. package/dist/drizzle/0241_knowledge_base_document_manifest.sql +67 -0
  51. package/dist/drizzle/0242_search_queries.sql +28 -0
  52. package/dist/drizzle/0243_section_sources_thread_refs.sql +12 -0
  53. package/dist/drizzle/0244_system_automations_and_memory_stage_overrides.sql +45 -0
  54. package/dist/drizzle/0245_wiki_page_render.sql +21 -0
  55. package/dist/drizzle/0246_automation_workflow_ownership.sql +30 -0
  56. package/dist/drizzle/0247_capability_runtime.sql +402 -0
  57. package/dist/drizzle/0248_capability_private_interpreter.sql +13 -0
  58. package/dist/drizzle/0249_capability_headless_execution_evidence.sql +40 -0
  59. package/dist/drizzle/0250_kg_schema_extraction.sql +576 -0
  60. package/dist/drizzle/0251_agents_json_render_ui.sql +25 -0
  61. package/dist/drizzle/0251_brain_stragglers.sql +263 -0
  62. package/dist/drizzle/0252_drop_kg_and_straggler_compat_views.sql +100 -0
  63. package/dist/drizzle/0253_drop_brain_substrate.sql +93 -0
  64. package/dist/drizzle/0254_capability_autonomous_admission.sql +29 -0
  65. package/dist/drizzle/0255_capability_autonomous_approval_mode.sql +16 -0
  66. package/dist/drizzle/0256_agent_profile_manifest_authority.sql +18 -0
  67. package/dist/drizzle/0257_agents_runtime_allow_harness.sql +24 -0
  68. package/dist/drizzle/0257_capability_approvals.sql +53 -0
  69. package/dist/drizzle/0258_pending_tool_approvals.sql +84 -0
  70. package/dist/drizzle/0259_tenant_capability_registry_trust.sql +19 -0
  71. package/dist/drizzle/0260_scheduled_jobs_run_as_user.sql +20 -0
  72. package/dist/drizzle/0261_managed_harness_multiplayer.sql +313 -0
  73. package/dist/drizzle/0261_native_auth_control_plane.sql +328 -0
  74. package/dist/drizzle/0262_auth_subscription_tickets.sql +59 -0
  75. package/dist/drizzle/0262_parallel_harness_threads.sql +9 -0
  76. package/dist/drizzle/0263_agentcore_runtime_identifier.sql +69 -0
  77. package/dist/drizzle/0263_drop_workos_auth_runtime.sql +236 -0
  78. package/dist/drizzle/0264_auth_enrollment_attempt_limits.sql +15 -0
  79. package/dist/drizzle/0264_harness_tool_execution_ledger.sql +113 -0
  80. package/dist/drizzle/0265_eval_runs_requester_identity.sql +28 -0
  81. package/dist/drizzle/0265_require_fully_valid_auth_publication.sql +27 -0
  82. package/dist/drizzle/0266_auth_identity_recovery_grants.sql +9 -0
  83. package/dist/drizzle/0266_eval_profiles_runtime_type.sql +12 -0
  84. package/dist/drizzle/0267_ontology_candidate_rejections.sql +53 -0
  85. package/dist/drizzle/0268_identity_crosswalk_routing.sql +182 -0
  86. package/dist/drizzle/0269_ontology_system_map.sql +31 -0
  87. package/dist/event-streams-7JNLJEEL.js +894 -0
  88. package/dist/event-streams-KDF5RWR6.js +1515 -0
  89. package/dist/loadSso-DJVB7BXE.js +576 -0
  90. package/dist/loadSso-JAMNA3WY.js +583 -0
  91. package/dist/plugins/catalog/package.json +1 -2
  92. package/dist/plugins/catalog/src/__tests__/build-catalog.test.ts +0 -1
  93. package/dist/plugins/catalog/src/__tests__/contracts.test.ts +0 -69
  94. package/dist/plugins/catalog/src/__tests__/plugin-package.test.ts +0 -2
  95. package/dist/plugins/catalog/src/__tests__/plugin-registry.test.ts +0 -5
  96. package/dist/plugins/catalog/src/contracts.ts +2 -179
  97. package/dist/plugins/catalog/src/registry/generated-first-party.ts +0 -6
  98. package/dist/signin-UGDWTGS4.js +821 -0
  99. package/dist/sso-oidc-Q4VXANXY.js +837 -0
  100. package/dist/sts-CWLSE3GH.js +1241 -0
  101. package/dist/sts-DNZLNVOV.js +1245 -0
  102. package/dist/terraform/examples/greenfield/main.tf +247 -50
  103. package/dist/terraform/examples/greenfield/terraform.tfvars.example +15 -1
  104. package/dist/terraform/modules/app/agentcore-admin/main.tf +341 -0
  105. package/dist/terraform/modules/app/agentcore-admin/outputs.tf +20 -0
  106. package/dist/terraform/modules/app/agentcore-code-interpreter/main.tf +61 -0
  107. package/dist/terraform/modules/app/agentcore-gateway/main.tf +305 -0
  108. package/dist/terraform/modules/app/agentcore-gateway/outputs.tf +44 -0
  109. package/dist/terraform/modules/app/agentcore-gateway/scripts/delete_gateway.sh +93 -0
  110. package/dist/terraform/modules/app/agentcore-gateway/scripts/read_gateway.sh +33 -0
  111. package/dist/terraform/modules/app/agentcore-gateway/scripts/reconcile_gateway.sh +543 -0
  112. package/dist/terraform/modules/app/agentcore-gateway/variables.tf +70 -0
  113. package/dist/terraform/modules/app/agentcore-harness/main.tf +330 -0
  114. package/dist/terraform/modules/app/agentcore-harness/outputs.tf +72 -0
  115. package/dist/terraform/modules/app/agentcore-harness/scripts/delete_harness.sh +5 -0
  116. package/dist/terraform/modules/app/agentcore-harness/scripts/harness-lifecycle.mjs +430 -0
  117. package/dist/terraform/modules/app/agentcore-harness/scripts/harness-readback.mjs +180 -0
  118. package/dist/terraform/modules/app/agentcore-harness/scripts/harness-tool-contract.mjs +193 -0
  119. package/dist/terraform/modules/app/agentcore-harness/scripts/prune_harness.sh +5 -0
  120. package/dist/terraform/modules/app/agentcore-harness/scripts/read_harness.sh +5 -0
  121. package/dist/terraform/modules/app/agentcore-harness/scripts/reconcile_harness.sh +5 -0
  122. package/dist/terraform/modules/app/agentcore-harness/variables.tf +96 -0
  123. package/dist/terraform/modules/app/agentcore-identity/main.tf +173 -0
  124. package/dist/terraform/modules/app/agentcore-identity/outputs.tf +51 -0
  125. package/dist/terraform/modules/app/agentcore-identity/scripts/bootstrap_twenty_oauth_client.sh +122 -0
  126. package/dist/terraform/modules/app/agentcore-identity/scripts/delete_identity.sh +25 -0
  127. package/dist/terraform/modules/app/agentcore-identity/scripts/delete_twenty_identity.sh +16 -0
  128. package/dist/terraform/modules/app/agentcore-identity/scripts/read_identity.sh +40 -0
  129. package/dist/terraform/modules/app/agentcore-identity/scripts/reconcile_identity.sh +73 -0
  130. package/dist/terraform/modules/app/agentcore-identity/scripts/reconcile_twenty_identity.sh +74 -0
  131. package/dist/terraform/modules/app/agentcore-identity/scripts/reconcile_twenty_provider.mjs +61 -0
  132. package/dist/terraform/modules/app/agentcore-identity/variables.tf +54 -0
  133. package/dist/terraform/modules/app/agentcore-pi/main.tf +7 -0
  134. package/dist/terraform/modules/app/appsync-subscriptions/main.tf +127 -21
  135. package/dist/terraform/modules/app/appsync-subscriptions/outputs.tf +0 -6
  136. package/dist/terraform/modules/app/appsync-subscriptions/variables.tf +5 -0
  137. package/dist/terraform/modules/app/capability-broker/main.tf +393 -0
  138. package/dist/terraform/modules/app/capability-broker/outputs.tf +54 -0
  139. package/dist/terraform/modules/app/capability-broker/variables.tf +98 -0
  140. package/dist/terraform/modules/app/deployment-control-plane/runner.py +1011 -31
  141. package/dist/terraform/modules/app/deployment-control-plane/test_runner_bundle.py +655 -2
  142. package/dist/terraform/modules/app/lambda-api/agentcore-harness-alarms.tf +88 -0
  143. package/dist/terraform/modules/app/lambda-api/agentcore-identity-alarms.tf +91 -0
  144. package/dist/terraform/modules/app/lambda-api/capability-search-alarms.tf +60 -0
  145. package/dist/terraform/modules/app/lambda-api/handlers.tf +606 -37
  146. package/dist/terraform/modules/app/lambda-api/iam-grouped.tf +192 -21
  147. package/dist/terraform/modules/app/lambda-api/main.tf +35 -0
  148. package/dist/terraform/modules/app/lambda-api/mcp-oauth.tf +181 -4
  149. package/dist/terraform/modules/app/lambda-api/memory-alarms.tf +92 -0
  150. package/dist/terraform/modules/app/lambda-api/msteams-app-secrets.tf +46 -0
  151. package/dist/terraform/modules/app/lambda-api/outputs.tf +35 -0
  152. package/dist/terraform/modules/app/lambda-api/runtime-config.tf +3 -21
  153. package/dist/terraform/modules/app/lambda-api/variables.tf +188 -3
  154. package/dist/terraform/modules/app/workflow-interpreter-stepfunctions/alarms.tf +47 -0
  155. package/dist/terraform/modules/app/workflow-interpreter-stepfunctions/main.tf +43 -2
  156. package/dist/terraform/modules/foundation/cognito/main.tf +319 -73
  157. package/dist/terraform/modules/foundation/cognito/outputs.tf +42 -0
  158. package/dist/terraform/modules/foundation/cognito/variables.tf +124 -2
  159. package/dist/terraform/modules/foundation/vpc/outputs.tf +5 -0
  160. package/dist/terraform/modules/thinkwork/main.tf +396 -26
  161. package/dist/terraform/modules/thinkwork/outputs.tf +188 -5
  162. package/dist/terraform/modules/thinkwork/variables.tf +154 -5
  163. package/dist/terraform/schema.graphql +69 -36
  164. package/dist/workspace-defaults/files/TOOLS.md +39 -0
  165. package/dist/workspace-defaults/files/USER.md +1 -0
  166. package/dist/workspace-defaults/files/agents/analyst/INSTRUCTIONS.md +18 -0
  167. package/dist/workspace-defaults/files/agents/coding/INSTRUCTIONS.md +11 -0
  168. package/dist/workspace-defaults/files/agents/research/INSTRUCTIONS.md +12 -0
  169. package/dist/workspace-defaults/files/agents/reviewer/INSTRUCTIONS.md +15 -0
  170. package/dist/workspace-defaults/files/skills/document-composer/SKILL.md +6 -2
  171. package/package.json +6 -3
  172. package/dist/plugins/workos-auth/package.json +0 -22
  173. package/dist/plugins/workos-auth/src/index.ts +0 -30
  174. package/dist/plugins/workos-auth/src/manifest.ts +0 -40
  175. package/dist/plugins/workos-auth/src/provider-contract.ts +0 -39
  176. package/dist/plugins/workos-auth/test/manifest.test.ts +0 -94
  177. package/dist/plugins/workos-auth/tsconfig.json +0 -8
  178. /package/dist/workspace-defaults/files/{AGENTS.md → INSTRUCTIONS.md} +0 -0
@@ -0,0 +1,263 @@
1
+ -- 0251_brain_stragglers.sql
2
+ --
3
+ -- Phase A of the brain-straggler move (THINK-290 U3). Moves the three
4
+ -- remaining public brain-domain tables into the existing `brain.*` Postgres
5
+ -- schema, drops the redundant prefixes from table, index, and constraint
6
+ -- names, and creates compat views in public.* so old bundled Lambda code
7
+ -- keeps reading during the deploy bridge window.
8
+ --
9
+ -- Tables moved:
10
+ -- public.brain_dream_runs → brain.dream_runs
11
+ -- public.brain_dream_actions → brain.dream_actions
12
+ -- public.memory_retain_attempts → brain.retain_attempts
13
+ --
14
+ -- Unlike the kg tables (whose idx_kg_* names were already schema-shorthand),
15
+ -- these indexes embed the old table names, so they are renamed to the new
16
+ -- stems. FK constraint names keep their original prefixes — cosmetic cleanup
17
+ -- deferred, same as the 0089/0090/0250 precedent.
18
+ --
19
+ -- Writers that cannot go through compat views (ON CONFLICT is rejected at
20
+ -- parse time): the dream ledger (raw ON CONFLICT on dream_runs.dedupe_key
21
+ -- and dream_actions (run_id, ordinal)) and memory-retain's
22
+ -- onConflictDoUpdate on retain_attempts. The apply runbook pauses the
23
+ -- brain-dream-state schedule AND the memory-retain Lambda (reserved
24
+ -- concurrency 0) for the apply→redeploy window — see the PR body.
25
+ --
26
+ -- Analyst surface: these tables leave SCHEMA.md and the 0227/0230 generated
27
+ -- grant/RLS blocks (analyst model is public-only by design, THINK-283).
28
+ --
29
+ -- Plan reference: docs/plans/2026-07-14-001-refactor-kg-schema-extraction-and-brain-cleanup-plan.md
30
+ -- Pattern doc: docs/solutions/database-issues/feature-schema-extraction-pattern.md
31
+ --
32
+ -- Apply manually (pause the dream schedule + memory-retain first):
33
+ -- psql "$DATABASE_URL" -f packages/database-pg/drizzle/0251_brain_stragglers.sql
34
+ -- Then verify:
35
+ -- bash scripts/db-migrate-manual.sh packages/database-pg/drizzle/0251_brain_stragglers.sql
36
+ -- psql -c "\dt brain.dream_runs brain.dream_actions brain.retain_attempts"
37
+ -- psql -c "\dv public.brain_dream_* public.memory_retain_attempts" -- 3 compat views
38
+ --
39
+ -- Inverse runbook (rollback): drop the 3 views, SET SCHEMA back, RENAME
40
+ -- tables/indexes/constraints back to the prefixed names (leaf-first:
41
+ -- dream_actions before dream_runs), then nothing else — no functions
42
+ -- reference these tables.
43
+ --
44
+ -- Markers (consumed by scripts/db-migrate-manual.sh):
45
+ --
46
+ -- moves-owner: public.brain_dream_runs -> brain.dream_runs
47
+ -- moves-owner: public.brain_dream_actions -> brain.dream_actions
48
+ -- moves-owner: public.memory_retain_attempts -> brain.retain_attempts
49
+ -- drops: public.brain_dream_runs_dedupe_key_uidx
50
+ -- drops: public.brain_dream_runs_tenant_bank_idx
51
+ -- drops: public.brain_dream_runs_tenant_status_idx
52
+ -- drops: public.brain_dream_actions_run_ordinal_uidx
53
+ -- drops: public.brain_dream_actions_run_status_idx
54
+ -- drops: public.memory_retain_attempts_source_event_uidx
55
+ -- drops: public.memory_retain_attempts_due_idx
56
+ -- drops: public.memory_retain_attempts_tenant_status_idx
57
+ -- drops: public.memory_retain_attempts_thread_idx
58
+ -- drops: public.memory_retain_attempts_user_idx
59
+ -- drops: public.memory_retain_attempts_space_idx
60
+ -- drops: public.memory_retain_attempts_turn_idx
61
+ -- drops-constraint: public.brain_dream_runs.brain_dream_runs_status_check
62
+ -- drops-constraint: public.brain_dream_actions.brain_dream_actions_type_check
63
+ -- drops-constraint: public.brain_dream_actions.brain_dream_actions_status_check
64
+ -- drops-constraint: public.memory_retain_attempts.memory_retain_attempts_status_allowed
65
+ -- drops-constraint: public.memory_retain_attempts.memory_retain_attempts_attempt_count_nonnegative
66
+ -- drops-constraint: public.memory_retain_attempts.memory_retain_attempts_max_attempts_positive
67
+ -- creates: brain.dream_runs
68
+ -- creates: brain.dream_actions
69
+ -- creates: brain.retain_attempts
70
+ -- creates: brain.dream_runs_dedupe_key_uidx
71
+ -- creates: brain.dream_runs_tenant_bank_idx
72
+ -- creates: brain.dream_runs_tenant_status_idx
73
+ -- creates: brain.dream_actions_run_ordinal_uidx
74
+ -- creates: brain.dream_actions_run_status_idx
75
+ -- creates: brain.retain_attempts_source_event_uidx
76
+ -- creates: brain.retain_attempts_due_idx
77
+ -- creates: brain.retain_attempts_tenant_status_idx
78
+ -- creates: brain.retain_attempts_thread_idx
79
+ -- creates: brain.retain_attempts_user_idx
80
+ -- creates: brain.retain_attempts_space_idx
81
+ -- creates: brain.retain_attempts_turn_idx
82
+ -- creates-constraint: brain.dream_runs.dream_runs_status_check
83
+ -- creates-constraint: brain.dream_actions.dream_actions_type_check
84
+ -- creates-constraint: brain.dream_actions.dream_actions_status_check
85
+ -- creates-constraint: brain.retain_attempts.retain_attempts_status_allowed
86
+ -- creates-constraint: brain.retain_attempts.retain_attempts_attempt_count_nonnegative
87
+ -- creates-constraint: brain.retain_attempts.retain_attempts_max_attempts_positive
88
+ -- creates: public.brain_dream_runs
89
+ -- creates: public.brain_dream_actions
90
+ -- creates: public.memory_retain_attempts
91
+
92
+ \set ON_ERROR_STOP on
93
+
94
+ BEGIN;
95
+
96
+ SET LOCAL lock_timeout = '30s';
97
+ SET LOCAL statement_timeout = '300s';
98
+
99
+ SELECT pg_advisory_xact_lock(hashtext('brain_stragglers_extraction'));
100
+
101
+ DO $$
102
+ BEGIN
103
+ IF current_database() != 'thinkwork' THEN
104
+ RAISE EXCEPTION 'wrong database: %, expected thinkwork', current_database();
105
+ END IF;
106
+ END $$;
107
+
108
+ -- Pre-flight: the brain schema itself must exist (created by 0090).
109
+ DO $$
110
+ BEGIN
111
+ IF to_regnamespace('brain') IS NULL THEN
112
+ RAISE EXCEPTION 'pre-flight: brain schema does not exist — apply 0090 first';
113
+ END IF;
114
+ END $$;
115
+
116
+ -- Pre-flight invariants, with a clean short-circuit when already applied so
117
+ -- the customer runner's unattended re-sweep is a no-op.
118
+ DO $$
119
+ BEGIN
120
+ IF to_regclass('brain.dream_runs') IS NOT NULL
121
+ AND to_regclass('brain.dream_actions') IS NOT NULL
122
+ AND to_regclass('brain.retain_attempts') IS NOT NULL
123
+ AND to_regclass('public.brain_dream_runs') IS NOT NULL THEN
124
+ RETURN; -- already applied (views present at the old names)
125
+ END IF;
126
+
127
+ IF to_regclass('public.brain_dream_runs') IS NULL THEN
128
+ RAISE EXCEPTION 'pre-flight: public.brain_dream_runs does not exist';
129
+ END IF;
130
+ IF to_regclass('brain.dream_runs') IS NOT NULL THEN
131
+ RAISE EXCEPTION 'pre-flight: brain.dream_runs already exists — refusing to re-apply';
132
+ END IF;
133
+ IF to_regclass('public.brain_dream_actions') IS NULL THEN
134
+ RAISE EXCEPTION 'pre-flight: public.brain_dream_actions does not exist';
135
+ END IF;
136
+ IF to_regclass('brain.dream_actions') IS NOT NULL THEN
137
+ RAISE EXCEPTION 'pre-flight: brain.dream_actions already exists — refusing to re-apply';
138
+ END IF;
139
+ IF to_regclass('public.memory_retain_attempts') IS NULL THEN
140
+ RAISE EXCEPTION 'pre-flight: public.memory_retain_attempts does not exist';
141
+ END IF;
142
+ IF to_regclass('brain.retain_attempts') IS NOT NULL THEN
143
+ RAISE EXCEPTION 'pre-flight: brain.retain_attempts already exists — refusing to re-apply';
144
+ END IF;
145
+ END $$;
146
+
147
+ -- ── Move and rename tables (leaf-first: dream_actions FKs dream_runs) ────
148
+
149
+ DO $$
150
+ BEGIN
151
+ IF to_regclass('public.brain_dream_actions') IS NOT NULL
152
+ AND to_regclass('brain.dream_actions') IS NULL THEN
153
+ ALTER TABLE public.brain_dream_actions SET SCHEMA brain;
154
+ ALTER TABLE brain.brain_dream_actions RENAME TO dream_actions;
155
+ END IF;
156
+
157
+ IF to_regclass('public.brain_dream_runs') IS NOT NULL
158
+ AND to_regclass('brain.dream_runs') IS NULL THEN
159
+ ALTER TABLE public.brain_dream_runs SET SCHEMA brain;
160
+ ALTER TABLE brain.brain_dream_runs RENAME TO dream_runs;
161
+ END IF;
162
+
163
+ IF to_regclass('public.memory_retain_attempts') IS NOT NULL
164
+ AND to_regclass('brain.retain_attempts') IS NULL THEN
165
+ ALTER TABLE public.memory_retain_attempts SET SCHEMA brain;
166
+ ALTER TABLE brain.memory_retain_attempts RENAME TO retain_attempts;
167
+ END IF;
168
+ END $$;
169
+
170
+ -- ── Rename indexes to the new stems ─────────────────────────────────────
171
+
172
+ DO $$
173
+ DECLARE
174
+ pair record;
175
+ BEGIN
176
+ FOR pair IN
177
+ SELECT * FROM (VALUES
178
+ ('brain_dream_runs_dedupe_key_uidx', 'dream_runs_dedupe_key_uidx'),
179
+ ('brain_dream_runs_tenant_bank_idx', 'dream_runs_tenant_bank_idx'),
180
+ ('brain_dream_runs_tenant_status_idx', 'dream_runs_tenant_status_idx'),
181
+ ('brain_dream_actions_run_ordinal_uidx', 'dream_actions_run_ordinal_uidx'),
182
+ ('brain_dream_actions_run_status_idx', 'dream_actions_run_status_idx'),
183
+ ('memory_retain_attempts_source_event_uidx', 'retain_attempts_source_event_uidx'),
184
+ ('memory_retain_attempts_due_idx', 'retain_attempts_due_idx'),
185
+ ('memory_retain_attempts_tenant_status_idx', 'retain_attempts_tenant_status_idx'),
186
+ ('memory_retain_attempts_thread_idx', 'retain_attempts_thread_idx'),
187
+ ('memory_retain_attempts_user_idx', 'retain_attempts_user_idx'),
188
+ ('memory_retain_attempts_space_idx', 'retain_attempts_space_idx'),
189
+ ('memory_retain_attempts_turn_idx', 'retain_attempts_turn_idx')
190
+ ) AS v(old_name, new_name)
191
+ LOOP
192
+ IF EXISTS (
193
+ SELECT 1 FROM pg_class c JOIN pg_namespace n ON n.oid = c.relnamespace
194
+ WHERE n.nspname = 'brain' AND c.relname = pair.old_name
195
+ ) THEN
196
+ EXECUTE format('ALTER INDEX brain.%I RENAME TO %I',
197
+ pair.old_name, pair.new_name);
198
+ END IF;
199
+ END LOOP;
200
+ END $$;
201
+
202
+ -- ── Rename CHECK constraints to the new stems ───────────────────────────
203
+
204
+ DO $$
205
+ DECLARE
206
+ pair record;
207
+ BEGIN
208
+ FOR pair IN
209
+ SELECT * FROM (VALUES
210
+ ('brain.dream_runs', 'brain_dream_runs_status_check', 'dream_runs_status_check'),
211
+ ('brain.dream_actions', 'brain_dream_actions_type_check', 'dream_actions_type_check'),
212
+ ('brain.dream_actions', 'brain_dream_actions_status_check', 'dream_actions_status_check'),
213
+ ('brain.retain_attempts', 'memory_retain_attempts_status_allowed', 'retain_attempts_status_allowed'),
214
+ ('brain.retain_attempts', 'memory_retain_attempts_attempt_count_nonnegative', 'retain_attempts_attempt_count_nonnegative'),
215
+ ('brain.retain_attempts', 'memory_retain_attempts_max_attempts_positive', 'retain_attempts_max_attempts_positive')
216
+ ) AS v(tbl, old_name, new_name)
217
+ LOOP
218
+ IF EXISTS (
219
+ SELECT 1 FROM pg_constraint
220
+ WHERE conrelid = to_regclass(pair.tbl) AND conname = pair.old_name
221
+ ) THEN
222
+ EXECUTE format('ALTER TABLE %s RENAME CONSTRAINT %I TO %I',
223
+ pair.tbl, pair.old_name, pair.new_name);
224
+ END IF;
225
+ END LOOP;
226
+ END $$;
227
+
228
+ -- ── Compat views in public.* ────────────────────────────────────────────
229
+ -- Column-enumerated per R6. No generated columns on any of the three
230
+ -- tables. The dream ledger's raw ON CONFLICT and memory-retain's
231
+ -- onConflictDoUpdate cannot pass through views — both writers are paused
232
+ -- for the window per the runbook. The U4 PR drops these.
233
+
234
+ DO $$
235
+ BEGIN
236
+ IF to_regclass('public.brain_dream_runs') IS NULL THEN
237
+ CREATE VIEW public.brain_dream_runs AS
238
+ SELECT id, tenant_id, bank_id, dedupe_key, status, planned_counts,
239
+ applied_counts, error_message, started_at, finished_at,
240
+ created_at, updated_at
241
+ FROM brain.dream_runs;
242
+ END IF;
243
+
244
+ IF to_regclass('public.brain_dream_actions') IS NULL THEN
245
+ CREATE VIEW public.brain_dream_actions AS
246
+ SELECT id, run_id, ordinal, action_type, status, target, reason,
247
+ applied_at, error_message, created_at
248
+ FROM brain.dream_actions;
249
+ END IF;
250
+
251
+ IF to_regclass('public.memory_retain_attempts') IS NULL THEN
252
+ CREATE VIEW public.memory_retain_attempts AS
253
+ SELECT id, tenant_id, user_id, space_id, thread_id, thread_turn_id,
254
+ source_event_key, source_event_type, provider, status,
255
+ attempt_count, max_attempts, next_retry_at, locked_at,
256
+ locked_by, started_at, finished_at, backend_latency_ms,
257
+ provider_document_id, provider_result, error_class,
258
+ error_message, metadata, created_at, updated_at
259
+ FROM brain.retain_attempts;
260
+ END IF;
261
+ END $$;
262
+
263
+ COMMIT;
@@ -0,0 +1,100 @@
1
+ -- 0252_drop_kg_and_straggler_compat_views.sql
2
+ --
3
+ -- Phase C of the THINK-290 arc. Drops the 8 compatibility views in
4
+ -- `public.*` that 0250 (kg extraction) and 0251 (brain stragglers) created
5
+ -- as a deploy bridge. The views protected old bundled Lambda READ paths
6
+ -- during the window between psql apply and Lambda redeploy; once every
7
+ -- deployed stage has recorded 0250 + 0251 as applied AND redeployed its
8
+ -- Lambdas, no consumer reads through these names and the views come down.
9
+ --
10
+ -- Views dropped:
11
+ -- public.knowledge_graph_ingest_runs, public.knowledge_graph_entities,
12
+ -- public.knowledge_graph_relationships, public.knowledge_graph_evidence,
13
+ -- public.knowledge_graph_observation_cursors,
14
+ -- public.brain_dream_runs, public.brain_dream_actions,
15
+ -- public.memory_retain_attempts
16
+ --
17
+ -- Merge gate (recorded in the PR body): per-stage scoped
18
+ -- `db:migrate-manual` output showing 0250/0251 applied on every deployed
19
+ -- stage, plus a pg_stat_statements (or short-window statement-log) check
20
+ -- that no statements reference the old names. Views do not appear in
21
+ -- pg_stat_user_tables, so table-stat checks are not usable here.
22
+ --
23
+ -- Plan reference: docs/plans/2026-07-14-001-refactor-kg-schema-extraction-and-brain-cleanup-plan.md
24
+ -- Pattern doc: docs/solutions/database-issues/feature-schema-extraction-pattern.md
25
+ -- kg PR (merged): #3757
26
+ -- Stragglers PR: #3760
27
+ --
28
+ -- Apply manually:
29
+ -- psql "$DATABASE_URL" -f packages/database-pg/drizzle/0252_drop_kg_and_straggler_compat_views.sql
30
+ -- Then verify:
31
+ -- bash scripts/db-migrate-manual.sh packages/database-pg/drizzle/0252_drop_kg_and_straggler_compat_views.sql
32
+ -- psql -c "\dv public.knowledge_graph_*" -- 0 views expected
33
+ -- psql -c "\dv public.brain_dream_*" -- 0 views expected
34
+ -- psql -c "\dv public.memory_retain_*" -- 0 views expected
35
+ -- psql -c "\dt kg.*" -- 5 tables still present
36
+ --
37
+ -- Inverse runbook (rollback): re-create each view — mirror of the CREATE
38
+ -- VIEW statements in 0250/0251 (column-enumerated; see those files).
39
+ --
40
+ -- Markers (consumed by scripts/db-migrate-manual.sh):
41
+ --
42
+ -- drops: public.knowledge_graph_ingest_runs
43
+ -- drops: public.knowledge_graph_entities
44
+ -- drops: public.knowledge_graph_relationships
45
+ -- drops: public.knowledge_graph_evidence
46
+ -- drops: public.knowledge_graph_observation_cursors
47
+ -- drops: public.brain_dream_runs
48
+ -- drops: public.brain_dream_actions
49
+ -- drops: public.memory_retain_attempts
50
+
51
+ \set ON_ERROR_STOP on
52
+
53
+ BEGIN;
54
+
55
+ SET LOCAL lock_timeout = '30s';
56
+ SET LOCAL statement_timeout = '300s';
57
+
58
+ SELECT pg_advisory_xact_lock(hashtext('drop_kg_and_straggler_compat_views'));
59
+
60
+ DO $$
61
+ BEGIN
62
+ IF current_database() != 'thinkwork' THEN
63
+ RAISE EXCEPTION 'wrong database: %, expected thinkwork', current_database();
64
+ END IF;
65
+ END $$;
66
+
67
+ -- Pre-flight: refuse to run if any old name still resolves to a TABLE
68
+ -- (i.e., 0250/0251 were never applied here) — dropping would then be data
69
+ -- loss, not view cleanup. A missing view (already dropped) is fine.
70
+ DO $$
71
+ DECLARE
72
+ name text;
73
+ BEGIN
74
+ FOREACH name IN ARRAY ARRAY[
75
+ 'knowledge_graph_ingest_runs', 'knowledge_graph_entities',
76
+ 'knowledge_graph_relationships', 'knowledge_graph_evidence',
77
+ 'knowledge_graph_observation_cursors', 'brain_dream_runs',
78
+ 'brain_dream_actions', 'memory_retain_attempts'
79
+ ] LOOP
80
+ IF EXISTS (
81
+ SELECT 1 FROM pg_class c
82
+ JOIN pg_namespace n ON n.oid = c.relnamespace
83
+ WHERE n.nspname = 'public' AND c.relname = name AND c.relkind = 'r'
84
+ ) THEN
85
+ RAISE EXCEPTION 'pre-flight: public.% is still a TABLE — apply 0250/0251 first', name;
86
+ END IF;
87
+ END LOOP;
88
+ END $$;
89
+
90
+ DROP VIEW IF EXISTS
91
+ public.knowledge_graph_ingest_runs,
92
+ public.knowledge_graph_entities,
93
+ public.knowledge_graph_relationships,
94
+ public.knowledge_graph_evidence,
95
+ public.knowledge_graph_observation_cursors,
96
+ public.brain_dream_runs,
97
+ public.brain_dream_actions,
98
+ public.memory_retain_attempts;
99
+
100
+ COMMIT;
@@ -0,0 +1,93 @@
1
+ -- 0253_drop_brain_substrate.sql
2
+ --
3
+ -- THINK-290 U5 PR B. Drops the retired graph-substrate residue:
4
+ -- `brain.substrate_states`, `brain.substrate_migrations`,
5
+ -- `brain.substrate_events`, and the dead `substrate_id` / `migration_id`
6
+ -- columns on `brain.artifact_manifests` (verified all-NULL across every
7
+ -- row on dev; no readers or writers remain — the Drizzle defs, relations,
8
+ -- enum constants, and tests were removed in U5 PR A, #3761, which is
9
+ -- deployed everywhere this migration may run).
10
+ --
11
+ -- ARCHIVE FIRST (procedural, per-stage, recorded in the PR body before
12
+ -- that stage applies this file):
13
+ -- pg_dump --no-owner --no-privileges --table='brain.substrate_*' \
14
+ -- -f substrate-archive-<stage>-<date>.sql
15
+ -- aws s3 cp substrate-archive-<stage>-<date>.sql \
16
+ -- s3://thinkwork-<stage>-backups/think-290/
17
+ --
18
+ -- Idempotent: every statement is guarded, so re-apply (including the
19
+ -- unattended runner sweep) is a clean no-op. Column drops cascade their
20
+ -- FK constraints (artifact_manifests_substrate_id_fk / _migration_id_fk)
21
+ -- and column-local indexes (brain_artifact_manifests_substrate_kind_idx /
22
+ -- brain_artifact_manifests_migration_idx) automatically.
23
+ --
24
+ -- Plan reference: docs/plans/2026-07-14-001-refactor-kg-schema-extraction-and-brain-cleanup-plan.md (U5)
25
+ -- PR A (code removal, merged): #3761
26
+ --
27
+ -- Apply manually:
28
+ -- psql "$DATABASE_URL" -f packages/database-pg/drizzle/0253_drop_brain_substrate.sql
29
+ -- Then verify:
30
+ -- bash scripts/db-migrate-manual.sh packages/database-pg/drizzle/0253_drop_brain_substrate.sql
31
+ --
32
+ -- Inverse runbook (rollback): restore from the stage's archival dump
33
+ -- (schema + data), then re-add the two artifact_manifests columns and
34
+ -- FKs from the dump's DDL.
35
+ --
36
+ -- Markers (consumed by scripts/db-migrate-manual.sh):
37
+ --
38
+ -- drops: brain.substrate_events
39
+ -- drops: brain.substrate_migrations
40
+ -- drops: brain.substrate_states
41
+ -- drops-column: brain.artifact_manifests.substrate_id
42
+ -- drops-column: brain.artifact_manifests.migration_id
43
+ -- drops-constraint: brain.artifact_manifests.artifact_manifests_substrate_id_fk
44
+ -- drops-constraint: brain.artifact_manifests.artifact_manifests_migration_id_fk
45
+ -- drops: brain.brain_artifact_manifests_substrate_kind_idx
46
+ -- drops: brain.brain_artifact_manifests_migration_idx
47
+
48
+ \set ON_ERROR_STOP on
49
+
50
+ BEGIN;
51
+
52
+ SET LOCAL lock_timeout = '30s';
53
+ SET LOCAL statement_timeout = '300s';
54
+
55
+ SELECT pg_advisory_xact_lock(hashtext('drop_brain_substrate'));
56
+
57
+ DO $$
58
+ BEGIN
59
+ IF current_database() != 'thinkwork' THEN
60
+ RAISE EXCEPTION 'wrong database: %, expected thinkwork', current_database();
61
+ END IF;
62
+ END $$;
63
+
64
+ -- Visibility: record what is being dropped in the apply log. Archival is
65
+ -- enforced procedurally (PR-body checklist per stage), not here — a header
66
+ -- note cannot constrain the unattended runner, so the two-PR split plus
67
+ -- idempotent guards carry the safety instead.
68
+ DO $$
69
+ DECLARE
70
+ t text;
71
+ n bigint;
72
+ BEGIN
73
+ FOREACH t IN ARRAY ARRAY['substrate_states', 'substrate_migrations', 'substrate_events'] LOOP
74
+ IF to_regclass('brain.' || t) IS NOT NULL THEN
75
+ EXECUTE format('SELECT count(*) FROM brain.%I', t) INTO n;
76
+ RAISE NOTICE 'dropping brain.% (% rows)', t, n;
77
+ ELSE
78
+ RAISE NOTICE 'brain.% already absent — skipping', t;
79
+ END IF;
80
+ END LOOP;
81
+ END $$;
82
+
83
+ -- FK dependency order: artifact_manifests references states + migrations
84
+ -- (columns must go first, taking their FKs and indexes with them); events
85
+ -- references states + migrations; migrations references states.
86
+ ALTER TABLE brain.artifact_manifests DROP COLUMN IF EXISTS substrate_id;
87
+ ALTER TABLE brain.artifact_manifests DROP COLUMN IF EXISTS migration_id;
88
+
89
+ DROP TABLE IF EXISTS brain.substrate_events;
90
+ DROP TABLE IF EXISTS brain.substrate_migrations;
91
+ DROP TABLE IF EXISTS brain.substrate_states;
92
+
93
+ COMMIT;
@@ -0,0 +1,29 @@
1
+ -- Autonomous capability self-extension — admission provenance.
2
+ --
3
+ -- Adds two columns to capability_definition_versions so an agent-admitted
4
+ -- (autonomous) version is distinguishable from an operator-admitted one and
5
+ -- stays fully attributable:
6
+ --
7
+ -- * admission_mode — 'operator' (human admitted, the default for every
8
+ -- existing row) | 'autonomous' (an agent self-admitted an auto-tier
9
+ -- public/read-only/no-credential capability with no human).
10
+ -- * admitted_by_agent_id — the composing agent for autonomous admissions;
11
+ -- null for operator admissions.
12
+ --
13
+ -- Hand-rolled (additive, nullable/defaulted — safe on live rows). Applied to
14
+ -- dev via psql; the deploy migration-drift gate checks the markers below.
15
+ --
16
+ -- creates-column: public.capability_definition_versions.admission_mode
17
+ -- creates-column: public.capability_definition_versions.admitted_by_agent_id
18
+
19
+ ALTER TABLE public.capability_definition_versions
20
+ ADD COLUMN IF NOT EXISTS admission_mode text NOT NULL DEFAULT 'operator';
21
+
22
+ ALTER TABLE public.capability_definition_versions
23
+ ADD COLUMN IF NOT EXISTS admitted_by_agent_id uuid;
24
+
25
+ ALTER TABLE public.capability_definition_versions
26
+ DROP CONSTRAINT IF EXISTS capability_definition_versions_admission_mode_check;
27
+ ALTER TABLE public.capability_definition_versions
28
+ ADD CONSTRAINT capability_definition_versions_admission_mode_check
29
+ CHECK (admission_mode IN ('operator', 'autonomous'));
@@ -0,0 +1,16 @@
1
+ -- Governed autonomy U3 follow-up: the autonomous self-promotion path stamps
2
+ -- approval_mode='autonomous', but 0247's CHECK only allowed
3
+ -- ('operator','repair') — every live self_promote_routine failed with a
4
+ -- check-constraint violation (first observed dev 2026-07-15, proposal
5
+ -- 88225e66). Recreate the CHECK with the autonomous mode included.
6
+ --
7
+ -- Hand-rolled (constraint recreation): apply via
8
+ -- psql "$DATABASE_URL" -f drizzle/0255_capability_autonomous_approval_mode.sql
9
+ -- creates-constraint: public.capability_routine_proposals.capability_routine_proposals_approval_mode_check
10
+
11
+ ALTER TABLE public.capability_routine_proposals
12
+ DROP CONSTRAINT IF EXISTS capability_routine_proposals_approval_mode_check;
13
+
14
+ ALTER TABLE public.capability_routine_proposals
15
+ ADD CONSTRAINT capability_routine_proposals_approval_mode_check
16
+ CHECK (approval_mode IS NULL OR approval_mode IN ('operator', 'repair', 'autonomous'));
@@ -0,0 +1,18 @@
1
+ -- 0256_agent_profile_manifest_authority.sql
2
+ --
3
+ -- Subagent-folders plan 2026-07-15-001 U10 (R17 flip half): per-agent
4
+ -- authority flip mirroring capability_folder_dispatch. When true, the
5
+ -- compiled capabilities manifest (agent entries + synced agents/<slug>/
6
+ -- folders) is the sub-agent profile truth: the dispatch payload carries
7
+ -- only space-local profiles in full and Pi assembles central profiles
8
+ -- from the manifest. Flipped per agent after the dual-read soak's
9
+ -- two-sided gate passes.
10
+ --
11
+ -- Hand-rolled (not in meta/_journal.json): drizzle-kit generate is
12
+ -- blocked on an unrelated interactive table-conflict prompt. Apply with:
13
+ -- psql "$DATABASE_URL" -f packages/database-pg/drizzle/0256_agent_profile_manifest_authority.sql
14
+ --
15
+ -- creates-column: public.agents.agent_profile_manifest_authority
16
+
17
+ ALTER TABLE "agents"
18
+ ADD COLUMN IF NOT EXISTS "agent_profile_manifest_authority" boolean NOT NULL DEFAULT false;
@@ -0,0 +1,24 @@
1
+ -- THINK-311 (AgentCore trial): loosen the agents.runtime CHECK constraint
2
+ -- so the Agent-configuration Runtime dropdown can persist the internal
3
+ -- 'harness' value (surfaced to users as "AgentCore"). Without this, the
4
+ -- updateTenantAgent mutation dies on agents_runtime_check and the UI
5
+ -- shows "[GraphQL] Unexpected error.".
6
+ --
7
+ -- Hand-rolled (NOT registered in meta/_journal.json) — apply via psql:
8
+ -- psql "$DATABASE_URL" -f packages/database-pg/drizzle/0257_agents_runtime_allow_harness.sql
9
+ -- Already applied to dev via RDS Data API on 2026-07-16.
10
+ --
11
+ -- agent_templates.runtime intentionally untouched: the AgentCore trial is
12
+ -- scoped to the ONE platform agent per tenant; no template carries it.
13
+ --
14
+ -- Marker for the db:migrate-manual drift-reporter:
15
+ -- creates-constraint: public.agents.agents_runtime_check
16
+
17
+ \echo '== THINK-311: allow harness in agents_runtime_check =='
18
+
19
+ ALTER TABLE agents
20
+ DROP CONSTRAINT IF EXISTS agents_runtime_check;
21
+
22
+ ALTER TABLE agents
23
+ ADD CONSTRAINT agents_runtime_check
24
+ CHECK (runtime IN ('strands', 'flue', 'pi', 'harness'));
@@ -0,0 +1,53 @@
1
+ -- THINK-302 U1: capability approval registry — scope-qualified bindings.
2
+ --
3
+ -- A row authorizes SPECIFIC definition bytes (marker sha + whole-folder
4
+ -- content-sha attestation) at ONE scope_ref (agent:<id>, agent:<id>/sub:<slug>,
5
+ -- space:<id>, or user:<id>). Identical bytes at any other scope are
6
+ -- unauthorized until separately bound (AE10 — copy-to-root escalation stays
7
+ -- inert). Append-only history: re-approval inserts a new row; compile trusts
8
+ -- the latest binding per (tenant, scope_ref, class, slug).
9
+ --
10
+ -- Ships inert: no production code path consults the table until compile v6
11
+ -- (THINK-302 U3) wires it behind the per-tenant registry-trust flag.
12
+ --
13
+ -- Hand-rolled (CHECK constraint); not in meta/_journal.json. Apply with:
14
+ -- psql "$DATABASE_URL" -f drizzle/0257_capability_approvals.sql
15
+ -- creates: public.capability_approvals
16
+
17
+ BEGIN;
18
+
19
+ CREATE TABLE IF NOT EXISTS public.capability_approvals (
20
+ id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
21
+ tenant_id uuid NOT NULL REFERENCES public.tenants(id) ON DELETE CASCADE,
22
+ -- Binding location. Part of the key: approval at one scope authorizes
23
+ -- nothing anywhere else.
24
+ scope_ref text NOT NULL,
25
+ -- Capability class segment: 'skill' | 'tool' | 'connection' | 'mcp'.
26
+ class text NOT NULL,
27
+ slug text NOT NULL,
28
+ -- sha256 hex of the marker file bytes (frontmatter + body).
29
+ marker_sha text NOT NULL,
30
+ -- Deterministic whole-folder manifest hash: sha256 over the sorted
31
+ -- (folder-relative path, per-file content sha256) pairs.
32
+ folder_attestation_sha text NOT NULL,
33
+ -- Zero-read fast-path snapshot: the script-trust-style digest over sorted
34
+ -- (path, S3 ETag) pairs at binding time. Nullable — content shas are the
35
+ -- approval authority; this only lets compile skip re-reading bytes.
36
+ files_etag_signature text,
37
+ definition_id uuid REFERENCES public.capability_definitions(id) ON DELETE SET NULL,
38
+ -- CapabilitySignedBy provenance: operator:<id> | autonomous:<agentId> | backfill | ...
39
+ signed_by text NOT NULL,
40
+ signed_at timestamptz NOT NULL DEFAULT now(),
41
+ created_at timestamptz NOT NULL DEFAULT now(),
42
+ CONSTRAINT capability_approvals_scope_ref_check
43
+ CHECK (scope_ref ~ '^(agent:[^/]+(/sub:[^/]+)?|space:[^/]+|user:[^/]+)$'),
44
+ CONSTRAINT capability_approvals_sha_check
45
+ CHECK (marker_sha ~ '^[0-9a-f]{64}$' AND folder_attestation_sha ~ '^[0-9a-f]{64}$')
46
+ );
47
+
48
+ CREATE INDEX IF NOT EXISTS idx_capability_approvals_lookup
49
+ ON public.capability_approvals (tenant_id, scope_ref, class, slug);
50
+ CREATE INDEX IF NOT EXISTS idx_capability_approvals_definition
51
+ ON public.capability_approvals (definition_id);
52
+
53
+ COMMIT;