thinkwork-cli 0.13.0 → 0.13.1

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 (74) hide show
  1. package/dist/{api-client-JUBCQQDF.js → api-client-4DZ266J5.js} +1 -1
  2. package/dist/{chunk-STY44FQO.js → chunk-Y2WHJECR.js} +44 -12
  3. package/dist/cli.js +36715 -12965
  4. package/dist/drizzle/0227_analyst_reader_role.sql +100 -38
  5. package/dist/drizzle/0230_analyst_rls.sql +183 -66
  6. package/dist/drizzle/0232_memory_source_thin_ledger.sql +176 -0
  7. package/dist/drizzle/0232_message_source_event_id.sql +9 -0
  8. package/dist/drizzle/0233_msteams_install_and_links.sql +151 -0
  9. package/dist/drizzle/0233_workflow_memory_stage_tokens.sql +20 -0
  10. package/dist/drizzle/0234_memory_claim_lifecycle.sql +160 -0
  11. package/dist/drizzle/0235_workflow_token_execution_claim.sql +34 -0
  12. package/dist/drizzle/0236_memory_retraction_fencing.sql +50 -0
  13. package/dist/drizzle/0237_memory_claims_active_value_uidx.sql +172 -0
  14. package/dist/drizzle/0238_memory_erase_generation_fence.sql +97 -0
  15. package/dist/drizzle/0239_canonical_entity_identity.sql +257 -0
  16. package/dist/drizzle/0240_memory_personal_scope.sql +45 -0
  17. package/dist/drizzle/0241_knowledge_base_document_manifest.sql +67 -0
  18. package/dist/drizzle/0242_search_queries.sql +28 -0
  19. package/dist/drizzle/0243_section_sources_thread_refs.sql +12 -0
  20. package/dist/drizzle/0244_system_automations_and_memory_stage_overrides.sql +45 -0
  21. package/dist/drizzle/0245_wiki_page_render.sql +21 -0
  22. package/dist/drizzle/0246_automation_workflow_ownership.sql +30 -0
  23. package/dist/drizzle/0247_capability_runtime.sql +402 -0
  24. package/dist/drizzle/0248_capability_private_interpreter.sql +13 -0
  25. package/dist/drizzle/0249_capability_headless_execution_evidence.sql +40 -0
  26. package/dist/drizzle/0250_kg_schema_extraction.sql +549 -0
  27. package/dist/drizzle/0251_agents_json_render_ui.sql +25 -0
  28. package/dist/drizzle/0251_brain_stragglers.sql +242 -0
  29. package/dist/drizzle/0252_drop_kg_and_straggler_compat_views.sql +100 -0
  30. package/dist/drizzle/0253_drop_brain_substrate.sql +91 -0
  31. package/dist/drizzle/0254_capability_autonomous_admission.sql +29 -0
  32. package/dist/drizzle/0255_capability_autonomous_approval_mode.sql +16 -0
  33. package/dist/drizzle/0256_agent_profile_manifest_authority.sql +18 -0
  34. package/dist/drizzle/0257_capability_approvals.sql +53 -0
  35. package/dist/drizzle/0258_pending_tool_approvals.sql +84 -0
  36. package/dist/drizzle/0259_tenant_capability_registry_trust.sql +19 -0
  37. package/dist/drizzle/0260_scheduled_jobs_run_as_user.sql +20 -0
  38. package/dist/drizzle/0261_thread_turns_origin_turn_index.sql +11 -0
  39. package/dist/terraform/examples/greenfield/main.tf +40 -0
  40. package/dist/terraform/modules/app/agentcore-admin/main.tf +341 -0
  41. package/dist/terraform/modules/app/agentcore-admin/outputs.tf +20 -0
  42. package/dist/terraform/modules/app/agentcore-code-interpreter/main.tf +61 -0
  43. package/dist/terraform/modules/app/agentcore-harness/main.tf +101 -0
  44. package/dist/terraform/modules/app/agentcore-harness/outputs.tf +9 -0
  45. package/dist/terraform/modules/app/agentcore-harness/variables.tf +25 -0
  46. package/dist/terraform/modules/app/agentcore-pi/main.tf +7 -0
  47. package/dist/terraform/modules/app/capability-broker/main.tf +393 -0
  48. package/dist/terraform/modules/app/capability-broker/outputs.tf +54 -0
  49. package/dist/terraform/modules/app/capability-broker/variables.tf +98 -0
  50. package/dist/terraform/modules/app/deployment-control-plane/runner.py +46 -5
  51. package/dist/terraform/modules/app/deployment-control-plane/test_runner_bundle.py +94 -0
  52. package/dist/terraform/modules/app/lambda-api/capability-search-alarms.tf +60 -0
  53. package/dist/terraform/modules/app/lambda-api/handlers.tf +361 -16
  54. package/dist/terraform/modules/app/lambda-api/iam-grouped.tf +131 -5
  55. package/dist/terraform/modules/app/lambda-api/main.tf +11 -0
  56. package/dist/terraform/modules/app/lambda-api/memory-alarms.tf +92 -0
  57. package/dist/terraform/modules/app/lambda-api/msteams-app-secrets.tf +46 -0
  58. package/dist/terraform/modules/app/lambda-api/variables.tf +92 -0
  59. package/dist/terraform/modules/app/workflow-interpreter-stepfunctions/alarms.tf +47 -0
  60. package/dist/terraform/modules/app/workflow-interpreter-stepfunctions/main.tf +43 -2
  61. package/dist/terraform/modules/foundation/cognito/main.tf +32 -8
  62. package/dist/terraform/modules/foundation/cognito/variables.tf +12 -0
  63. package/dist/terraform/modules/foundation/vpc/outputs.tf +5 -0
  64. package/dist/terraform/modules/thinkwork/main.tf +152 -5
  65. package/dist/terraform/modules/thinkwork/outputs.tf +55 -0
  66. package/dist/terraform/modules/thinkwork/variables.tf +42 -0
  67. package/dist/workspace-defaults/files/TOOLS.md +39 -0
  68. package/dist/workspace-defaults/files/agents/analyst/INSTRUCTIONS.md +18 -0
  69. package/dist/workspace-defaults/files/agents/coding/INSTRUCTIONS.md +11 -0
  70. package/dist/workspace-defaults/files/agents/research/INSTRUCTIONS.md +12 -0
  71. package/dist/workspace-defaults/files/agents/reviewer/INSTRUCTIONS.md +15 -0
  72. package/dist/workspace-defaults/files/skills/document-composer/SKILL.md +6 -2
  73. package/package.json +4 -2
  74. /package/dist/workspace-defaults/files/{AGENTS.md → INSTRUCTIONS.md} +0 -0
@@ -0,0 +1,242 @@
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
+ -- creates: brain.dream_runs
47
+ -- creates: brain.dream_actions
48
+ -- creates: brain.retain_attempts
49
+ -- creates: brain.dream_runs_dedupe_key_uidx
50
+ -- creates: brain.dream_runs_tenant_bank_idx
51
+ -- creates: brain.dream_runs_tenant_status_idx
52
+ -- creates: brain.dream_actions_run_ordinal_uidx
53
+ -- creates: brain.dream_actions_run_status_idx
54
+ -- creates: brain.retain_attempts_source_event_uidx
55
+ -- creates: brain.retain_attempts_due_idx
56
+ -- creates: brain.retain_attempts_tenant_status_idx
57
+ -- creates: brain.retain_attempts_thread_idx
58
+ -- creates: brain.retain_attempts_user_idx
59
+ -- creates: brain.retain_attempts_space_idx
60
+ -- creates: brain.retain_attempts_turn_idx
61
+ -- creates-constraint: brain.dream_runs.dream_runs_status_check
62
+ -- creates-constraint: brain.dream_actions.dream_actions_type_check
63
+ -- creates-constraint: brain.dream_actions.dream_actions_status_check
64
+ -- creates-constraint: brain.retain_attempts.retain_attempts_status_allowed
65
+ -- creates-constraint: brain.retain_attempts.retain_attempts_attempt_count_nonnegative
66
+ -- creates-constraint: brain.retain_attempts.retain_attempts_max_attempts_positive
67
+ -- creates: public.brain_dream_runs
68
+ -- creates: public.brain_dream_actions
69
+ -- creates: public.memory_retain_attempts
70
+
71
+ \set ON_ERROR_STOP on
72
+
73
+ BEGIN;
74
+
75
+ SET LOCAL lock_timeout = '30s';
76
+ SET LOCAL statement_timeout = '300s';
77
+
78
+ SELECT pg_advisory_xact_lock(hashtext('brain_stragglers_extraction'));
79
+
80
+ DO $$
81
+ BEGIN
82
+ IF current_database() != 'thinkwork' THEN
83
+ RAISE EXCEPTION 'wrong database: %, expected thinkwork', current_database();
84
+ END IF;
85
+ END $$;
86
+
87
+ -- Pre-flight: the brain schema itself must exist (created by 0090).
88
+ DO $$
89
+ BEGIN
90
+ IF to_regnamespace('brain') IS NULL THEN
91
+ RAISE EXCEPTION 'pre-flight: brain schema does not exist — apply 0090 first';
92
+ END IF;
93
+ END $$;
94
+
95
+ -- Pre-flight invariants, with a clean short-circuit when already applied so
96
+ -- the customer runner's unattended re-sweep is a no-op.
97
+ DO $$
98
+ BEGIN
99
+ IF to_regclass('brain.dream_runs') IS NOT NULL
100
+ AND to_regclass('brain.dream_actions') IS NOT NULL
101
+ AND to_regclass('brain.retain_attempts') IS NOT NULL
102
+ AND to_regclass('public.brain_dream_runs') IS NOT NULL THEN
103
+ RETURN; -- already applied (views present at the old names)
104
+ END IF;
105
+
106
+ IF to_regclass('public.brain_dream_runs') IS NULL THEN
107
+ RAISE EXCEPTION 'pre-flight: public.brain_dream_runs does not exist';
108
+ END IF;
109
+ IF to_regclass('brain.dream_runs') IS NOT NULL THEN
110
+ RAISE EXCEPTION 'pre-flight: brain.dream_runs already exists — refusing to re-apply';
111
+ END IF;
112
+ IF to_regclass('public.brain_dream_actions') IS NULL THEN
113
+ RAISE EXCEPTION 'pre-flight: public.brain_dream_actions does not exist';
114
+ END IF;
115
+ IF to_regclass('brain.dream_actions') IS NOT NULL THEN
116
+ RAISE EXCEPTION 'pre-flight: brain.dream_actions already exists — refusing to re-apply';
117
+ END IF;
118
+ IF to_regclass('public.memory_retain_attempts') IS NULL THEN
119
+ RAISE EXCEPTION 'pre-flight: public.memory_retain_attempts does not exist';
120
+ END IF;
121
+ IF to_regclass('brain.retain_attempts') IS NOT NULL THEN
122
+ RAISE EXCEPTION 'pre-flight: brain.retain_attempts already exists — refusing to re-apply';
123
+ END IF;
124
+ END $$;
125
+
126
+ -- ── Move and rename tables (leaf-first: dream_actions FKs dream_runs) ────
127
+
128
+ DO $$
129
+ BEGIN
130
+ IF to_regclass('public.brain_dream_actions') IS NOT NULL
131
+ AND to_regclass('brain.dream_actions') IS NULL THEN
132
+ ALTER TABLE public.brain_dream_actions SET SCHEMA brain;
133
+ ALTER TABLE brain.brain_dream_actions RENAME TO dream_actions;
134
+ END IF;
135
+
136
+ IF to_regclass('public.brain_dream_runs') IS NOT NULL
137
+ AND to_regclass('brain.dream_runs') IS NULL THEN
138
+ ALTER TABLE public.brain_dream_runs SET SCHEMA brain;
139
+ ALTER TABLE brain.brain_dream_runs RENAME TO dream_runs;
140
+ END IF;
141
+
142
+ IF to_regclass('public.memory_retain_attempts') IS NOT NULL
143
+ AND to_regclass('brain.retain_attempts') IS NULL THEN
144
+ ALTER TABLE public.memory_retain_attempts SET SCHEMA brain;
145
+ ALTER TABLE brain.memory_retain_attempts RENAME TO retain_attempts;
146
+ END IF;
147
+ END $$;
148
+
149
+ -- ── Rename indexes to the new stems ─────────────────────────────────────
150
+
151
+ DO $$
152
+ DECLARE
153
+ pair record;
154
+ BEGIN
155
+ FOR pair IN
156
+ SELECT * FROM (VALUES
157
+ ('brain_dream_runs_dedupe_key_uidx', 'dream_runs_dedupe_key_uidx'),
158
+ ('brain_dream_runs_tenant_bank_idx', 'dream_runs_tenant_bank_idx'),
159
+ ('brain_dream_runs_tenant_status_idx', 'dream_runs_tenant_status_idx'),
160
+ ('brain_dream_actions_run_ordinal_uidx', 'dream_actions_run_ordinal_uidx'),
161
+ ('brain_dream_actions_run_status_idx', 'dream_actions_run_status_idx'),
162
+ ('memory_retain_attempts_source_event_uidx', 'retain_attempts_source_event_uidx'),
163
+ ('memory_retain_attempts_due_idx', 'retain_attempts_due_idx'),
164
+ ('memory_retain_attempts_tenant_status_idx', 'retain_attempts_tenant_status_idx'),
165
+ ('memory_retain_attempts_thread_idx', 'retain_attempts_thread_idx'),
166
+ ('memory_retain_attempts_user_idx', 'retain_attempts_user_idx'),
167
+ ('memory_retain_attempts_space_idx', 'retain_attempts_space_idx'),
168
+ ('memory_retain_attempts_turn_idx', 'retain_attempts_turn_idx')
169
+ ) AS v(old_name, new_name)
170
+ LOOP
171
+ IF EXISTS (
172
+ SELECT 1 FROM pg_class c JOIN pg_namespace n ON n.oid = c.relnamespace
173
+ WHERE n.nspname = 'brain' AND c.relname = pair.old_name
174
+ ) THEN
175
+ EXECUTE format('ALTER INDEX brain.%I RENAME TO %I',
176
+ pair.old_name, pair.new_name);
177
+ END IF;
178
+ END LOOP;
179
+ END $$;
180
+
181
+ -- ── Rename CHECK constraints to the new stems ───────────────────────────
182
+
183
+ DO $$
184
+ DECLARE
185
+ pair record;
186
+ BEGIN
187
+ FOR pair IN
188
+ SELECT * FROM (VALUES
189
+ ('brain.dream_runs', 'brain_dream_runs_status_check', 'dream_runs_status_check'),
190
+ ('brain.dream_actions', 'brain_dream_actions_type_check', 'dream_actions_type_check'),
191
+ ('brain.dream_actions', 'brain_dream_actions_status_check', 'dream_actions_status_check'),
192
+ ('brain.retain_attempts', 'memory_retain_attempts_status_allowed', 'retain_attempts_status_allowed'),
193
+ ('brain.retain_attempts', 'memory_retain_attempts_attempt_count_nonnegative', 'retain_attempts_attempt_count_nonnegative'),
194
+ ('brain.retain_attempts', 'memory_retain_attempts_max_attempts_positive', 'retain_attempts_max_attempts_positive')
195
+ ) AS v(tbl, old_name, new_name)
196
+ LOOP
197
+ IF EXISTS (
198
+ SELECT 1 FROM pg_constraint
199
+ WHERE conrelid = to_regclass(pair.tbl) AND conname = pair.old_name
200
+ ) THEN
201
+ EXECUTE format('ALTER TABLE %s RENAME CONSTRAINT %I TO %I',
202
+ pair.tbl, pair.old_name, pair.new_name);
203
+ END IF;
204
+ END LOOP;
205
+ END $$;
206
+
207
+ -- ── Compat views in public.* ────────────────────────────────────────────
208
+ -- Column-enumerated per R6. No generated columns on any of the three
209
+ -- tables. The dream ledger's raw ON CONFLICT and memory-retain's
210
+ -- onConflictDoUpdate cannot pass through views — both writers are paused
211
+ -- for the window per the runbook. The U4 PR drops these.
212
+
213
+ DO $$
214
+ BEGIN
215
+ IF to_regclass('public.brain_dream_runs') IS NULL THEN
216
+ CREATE VIEW public.brain_dream_runs AS
217
+ SELECT id, tenant_id, bank_id, dedupe_key, status, planned_counts,
218
+ applied_counts, error_message, started_at, finished_at,
219
+ created_at, updated_at
220
+ FROM brain.dream_runs;
221
+ END IF;
222
+
223
+ IF to_regclass('public.brain_dream_actions') IS NULL THEN
224
+ CREATE VIEW public.brain_dream_actions AS
225
+ SELECT id, run_id, ordinal, action_type, status, target, reason,
226
+ applied_at, error_message, created_at
227
+ FROM brain.dream_actions;
228
+ END IF;
229
+
230
+ IF to_regclass('public.memory_retain_attempts') IS NULL THEN
231
+ CREATE VIEW public.memory_retain_attempts AS
232
+ SELECT id, tenant_id, user_id, space_id, thread_id, thread_turn_id,
233
+ source_event_key, source_event_type, provider, status,
234
+ attempt_count, max_attempts, next_retry_at, locked_at,
235
+ locked_by, started_at, finished_at, backend_latency_ms,
236
+ provider_document_id, provider_result, error_class,
237
+ error_message, metadata, created_at, updated_at
238
+ FROM brain.retain_attempts;
239
+ END IF;
240
+ END $$;
241
+
242
+ 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,91 @@
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
+
46
+ \set ON_ERROR_STOP on
47
+
48
+ BEGIN;
49
+
50
+ SET LOCAL lock_timeout = '30s';
51
+ SET LOCAL statement_timeout = '300s';
52
+
53
+ SELECT pg_advisory_xact_lock(hashtext('drop_brain_substrate'));
54
+
55
+ DO $$
56
+ BEGIN
57
+ IF current_database() != 'thinkwork' THEN
58
+ RAISE EXCEPTION 'wrong database: %, expected thinkwork', current_database();
59
+ END IF;
60
+ END $$;
61
+
62
+ -- Visibility: record what is being dropped in the apply log. Archival is
63
+ -- enforced procedurally (PR-body checklist per stage), not here — a header
64
+ -- note cannot constrain the unattended runner, so the two-PR split plus
65
+ -- idempotent guards carry the safety instead.
66
+ DO $$
67
+ DECLARE
68
+ t text;
69
+ n bigint;
70
+ BEGIN
71
+ FOREACH t IN ARRAY ARRAY['substrate_states', 'substrate_migrations', 'substrate_events'] LOOP
72
+ IF to_regclass('brain.' || t) IS NOT NULL THEN
73
+ EXECUTE format('SELECT count(*) FROM brain.%I', t) INTO n;
74
+ RAISE NOTICE 'dropping brain.% (% rows)', t, n;
75
+ ELSE
76
+ RAISE NOTICE 'brain.% already absent — skipping', t;
77
+ END IF;
78
+ END LOOP;
79
+ END $$;
80
+
81
+ -- FK dependency order: artifact_manifests references states + migrations
82
+ -- (columns must go first, taking their FKs and indexes with them); events
83
+ -- references states + migrations; migrations references states.
84
+ ALTER TABLE brain.artifact_manifests DROP COLUMN IF EXISTS substrate_id;
85
+ ALTER TABLE brain.artifact_manifests DROP COLUMN IF EXISTS migration_id;
86
+
87
+ DROP TABLE IF EXISTS brain.substrate_events;
88
+ DROP TABLE IF EXISTS brain.substrate_migrations;
89
+ DROP TABLE IF EXISTS brain.substrate_states;
90
+
91
+ 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,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;
@@ -0,0 +1,84 @@
1
+ -- THINK-302 U11: pending_tool_approvals — parked-turn HITL ledger.
2
+ --
3
+ -- A distinct pending kind from pending_user_questions (KTD-5): a gated tool
4
+ -- call parks the turn and this row is the recoverable ledger. Two partial
5
+ -- unique indexes drizzle-kit cannot express live here:
6
+ -- * one `pending` approval per thread (the one-slot invariant, R32) — so
7
+ -- an approval can COEXIST with a pending question (separate tables/slots),
8
+ -- and the intake endpoint returns 409 on a second concurrent park.
9
+ -- * resume-replay uniqueness (thread_turn_id, tool_call_id, manifest
10
+ -- fingerprint) — a stale approval cannot authorize a drifted definition
11
+ -- and a retried intake is idempotent.
12
+ --
13
+ -- Ships INERT: no writer touches this table until U11b; U12 consumes it.
14
+ --
15
+ -- Hand-rolled (partial indices, CHECK constraints); not in meta/_journal.json.
16
+ -- Apply manually:
17
+ -- psql "$DATABASE_URL" -v ON_ERROR_STOP=1 -f drizzle/0258_pending_tool_approvals.sql
18
+ -- creates: public.pending_tool_approvals
19
+ -- creates: public.pending_tool_approvals_one_pending_per_thread
20
+ -- creates: public.pending_tool_approvals_resume_identity
21
+ -- creates: public.idx_pending_tool_approvals_tenant
22
+ -- creates: public.idx_pending_tool_approvals_thread_status
23
+ -- creates: public.idx_pending_tool_approvals_message
24
+ -- creates: public.idx_pending_tool_approvals_purge
25
+
26
+ \set ON_ERROR_STOP on
27
+
28
+ SET lock_timeout = '5s';
29
+ SET statement_timeout = '15min';
30
+
31
+ SELECT pg_advisory_lock(hashtext('migration:0258_pending_tool_approvals'));
32
+
33
+ CREATE TABLE IF NOT EXISTS public.pending_tool_approvals (
34
+ id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
35
+ tenant_id uuid NOT NULL REFERENCES public.tenants(id) ON DELETE CASCADE,
36
+ thread_id uuid NOT NULL REFERENCES public.threads(id) ON DELETE CASCADE,
37
+ thread_turn_id uuid NOT NULL REFERENCES public.thread_turns(id),
38
+ message_id uuid NOT NULL REFERENCES public.messages(id) ON DELETE CASCADE,
39
+ manifest_fingerprint text NOT NULL,
40
+ tool_call_id text NOT NULL,
41
+ class text NOT NULL,
42
+ slug text NOT NULL,
43
+ marker_sha text NOT NULL,
44
+ status text NOT NULL DEFAULT 'pending',
45
+ requesting_user_id uuid REFERENCES public.users(id) ON DELETE SET NULL,
46
+ encrypted_payload text,
47
+ display_summary jsonb NOT NULL,
48
+ approved_by uuid REFERENCES public.users(id) ON DELETE SET NULL,
49
+ answered_via text,
50
+ answered_at timestamptz,
51
+ payload_purged_at timestamptz,
52
+ created_at timestamptz NOT NULL DEFAULT now(),
53
+ CONSTRAINT pending_tool_approvals_status_allowed
54
+ CHECK (status IN ('pending','approved','denied','cancelled')),
55
+ CONSTRAINT pending_tool_approvals_answered_via_allowed
56
+ CHECK (answered_via IS NULL OR answered_via IN ('card','slack','governance','archive','reaper')),
57
+ CONSTRAINT pending_tool_approvals_terminal_consistency
58
+ CHECK ((status = 'pending') = (answered_at IS NULL))
59
+ );
60
+
61
+ -- One pending approval per thread (the one-slot invariant). Partial so
62
+ -- terminal rows never block a new park, and so it is INDEPENDENT of the
63
+ -- pending_user_questions slot (an approval + a question can both be pending).
64
+ CREATE UNIQUE INDEX IF NOT EXISTS pending_tool_approvals_one_pending_per_thread
65
+ ON public.pending_tool_approvals (thread_id)
66
+ WHERE status = 'pending';
67
+
68
+ -- Resume-replay identity: a park is unique per (turn, tool call, pinned
69
+ -- manifest) so a retried intake is idempotent and a stale approval cannot
70
+ -- authorize a drifted definition.
71
+ CREATE UNIQUE INDEX IF NOT EXISTS pending_tool_approvals_resume_identity
72
+ ON public.pending_tool_approvals (thread_turn_id, tool_call_id, manifest_fingerprint);
73
+
74
+ CREATE INDEX IF NOT EXISTS idx_pending_tool_approvals_tenant
75
+ ON public.pending_tool_approvals (tenant_id);
76
+ CREATE INDEX IF NOT EXISTS idx_pending_tool_approvals_thread_status
77
+ ON public.pending_tool_approvals (thread_id, status);
78
+ CREATE INDEX IF NOT EXISTS idx_pending_tool_approvals_message
79
+ ON public.pending_tool_approvals (message_id);
80
+ -- Reaper scan: terminal rows whose payload is not yet purged, by age.
81
+ CREATE INDEX IF NOT EXISTS idx_pending_tool_approvals_purge
82
+ ON public.pending_tool_approvals (status, payload_purged_at);
83
+
84
+ SELECT pg_advisory_unlock(hashtext('migration:0258_pending_tool_approvals'));
@@ -0,0 +1,19 @@
1
+ -- THINK-302 U3b: per-tenant capability registry-trust gate (KTD-8).
2
+ --
3
+ -- Off for every tenant at migration time; flipped on per tenant
4
+ -- (dev → TEI → McPherson) as the capability approval registry replaces
5
+ -- per-folder sidecar signatures. Read by the workspace renderer
6
+ -- (compose-tuple) to decide registry-trust vs legacy sidecar admission.
7
+ --
8
+ -- Additive, idempotent column add. Hand-rolled only so it carries a
9
+ -- drift-gate marker alongside the sibling hand-rolled capability migrations;
10
+ -- db:push would also add it from the ORM definition.
11
+ --
12
+ -- Apply manually:
13
+ -- psql "$DATABASE_URL" -v ON_ERROR_STOP=1 -f drizzle/0259_tenant_capability_registry_trust.sql
14
+ -- creates-column: public.tenants.capability_registry_trust
15
+
16
+ \set ON_ERROR_STOP on
17
+
18
+ ALTER TABLE public.tenants
19
+ ADD COLUMN IF NOT EXISTS capability_registry_trust boolean NOT NULL DEFAULT false;