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.
- package/dist/{api-client-JUBCQQDF.js → api-client-4DZ266J5.js} +1 -1
- package/dist/{chunk-STY44FQO.js → chunk-Y2WHJECR.js} +44 -12
- package/dist/cli.js +36715 -12965
- package/dist/drizzle/0227_analyst_reader_role.sql +100 -38
- package/dist/drizzle/0230_analyst_rls.sql +183 -66
- package/dist/drizzle/0232_memory_source_thin_ledger.sql +176 -0
- package/dist/drizzle/0232_message_source_event_id.sql +9 -0
- package/dist/drizzle/0233_msteams_install_and_links.sql +151 -0
- package/dist/drizzle/0233_workflow_memory_stage_tokens.sql +20 -0
- package/dist/drizzle/0234_memory_claim_lifecycle.sql +160 -0
- package/dist/drizzle/0235_workflow_token_execution_claim.sql +34 -0
- package/dist/drizzle/0236_memory_retraction_fencing.sql +50 -0
- package/dist/drizzle/0237_memory_claims_active_value_uidx.sql +172 -0
- package/dist/drizzle/0238_memory_erase_generation_fence.sql +97 -0
- package/dist/drizzle/0239_canonical_entity_identity.sql +257 -0
- package/dist/drizzle/0240_memory_personal_scope.sql +45 -0
- package/dist/drizzle/0241_knowledge_base_document_manifest.sql +67 -0
- package/dist/drizzle/0242_search_queries.sql +28 -0
- package/dist/drizzle/0243_section_sources_thread_refs.sql +12 -0
- package/dist/drizzle/0244_system_automations_and_memory_stage_overrides.sql +45 -0
- package/dist/drizzle/0245_wiki_page_render.sql +21 -0
- package/dist/drizzle/0246_automation_workflow_ownership.sql +30 -0
- package/dist/drizzle/0247_capability_runtime.sql +402 -0
- package/dist/drizzle/0248_capability_private_interpreter.sql +13 -0
- package/dist/drizzle/0249_capability_headless_execution_evidence.sql +40 -0
- package/dist/drizzle/0250_kg_schema_extraction.sql +549 -0
- package/dist/drizzle/0251_agents_json_render_ui.sql +25 -0
- package/dist/drizzle/0251_brain_stragglers.sql +242 -0
- package/dist/drizzle/0252_drop_kg_and_straggler_compat_views.sql +100 -0
- package/dist/drizzle/0253_drop_brain_substrate.sql +91 -0
- package/dist/drizzle/0254_capability_autonomous_admission.sql +29 -0
- package/dist/drizzle/0255_capability_autonomous_approval_mode.sql +16 -0
- package/dist/drizzle/0256_agent_profile_manifest_authority.sql +18 -0
- package/dist/drizzle/0257_capability_approvals.sql +53 -0
- package/dist/drizzle/0258_pending_tool_approvals.sql +84 -0
- package/dist/drizzle/0259_tenant_capability_registry_trust.sql +19 -0
- package/dist/drizzle/0260_scheduled_jobs_run_as_user.sql +20 -0
- package/dist/drizzle/0261_thread_turns_origin_turn_index.sql +11 -0
- package/dist/terraform/examples/greenfield/main.tf +40 -0
- package/dist/terraform/modules/app/agentcore-admin/main.tf +341 -0
- package/dist/terraform/modules/app/agentcore-admin/outputs.tf +20 -0
- package/dist/terraform/modules/app/agentcore-code-interpreter/main.tf +61 -0
- package/dist/terraform/modules/app/agentcore-harness/main.tf +101 -0
- package/dist/terraform/modules/app/agentcore-harness/outputs.tf +9 -0
- package/dist/terraform/modules/app/agentcore-harness/variables.tf +25 -0
- package/dist/terraform/modules/app/agentcore-pi/main.tf +7 -0
- package/dist/terraform/modules/app/capability-broker/main.tf +393 -0
- package/dist/terraform/modules/app/capability-broker/outputs.tf +54 -0
- package/dist/terraform/modules/app/capability-broker/variables.tf +98 -0
- package/dist/terraform/modules/app/deployment-control-plane/runner.py +46 -5
- package/dist/terraform/modules/app/deployment-control-plane/test_runner_bundle.py +94 -0
- package/dist/terraform/modules/app/lambda-api/capability-search-alarms.tf +60 -0
- package/dist/terraform/modules/app/lambda-api/handlers.tf +361 -16
- package/dist/terraform/modules/app/lambda-api/iam-grouped.tf +131 -5
- package/dist/terraform/modules/app/lambda-api/main.tf +11 -0
- package/dist/terraform/modules/app/lambda-api/memory-alarms.tf +92 -0
- package/dist/terraform/modules/app/lambda-api/msteams-app-secrets.tf +46 -0
- package/dist/terraform/modules/app/lambda-api/variables.tf +92 -0
- package/dist/terraform/modules/app/workflow-interpreter-stepfunctions/alarms.tf +47 -0
- package/dist/terraform/modules/app/workflow-interpreter-stepfunctions/main.tf +43 -2
- package/dist/terraform/modules/foundation/cognito/main.tf +32 -8
- package/dist/terraform/modules/foundation/cognito/variables.tf +12 -0
- package/dist/terraform/modules/foundation/vpc/outputs.tf +5 -0
- package/dist/terraform/modules/thinkwork/main.tf +152 -5
- package/dist/terraform/modules/thinkwork/outputs.tf +55 -0
- package/dist/terraform/modules/thinkwork/variables.tf +42 -0
- package/dist/workspace-defaults/files/TOOLS.md +39 -0
- package/dist/workspace-defaults/files/agents/analyst/INSTRUCTIONS.md +18 -0
- package/dist/workspace-defaults/files/agents/coding/INSTRUCTIONS.md +11 -0
- package/dist/workspace-defaults/files/agents/research/INSTRUCTIONS.md +12 -0
- package/dist/workspace-defaults/files/agents/reviewer/INSTRUCTIONS.md +15 -0
- package/dist/workspace-defaults/files/skills/document-composer/SKILL.md +6 -2
- package/package.json +4 -2
- /package/dist/workspace-defaults/files/{AGENTS.md → INSTRUCTIONS.md} +0 -0
|
@@ -0,0 +1,549 @@
|
|
|
1
|
+
-- 0250_kg_schema_extraction.sql
|
|
2
|
+
--
|
|
3
|
+
-- Phase A of the knowledge-graph schema extraction (PR 1 of the THINK-290
|
|
4
|
+
-- arc). Moves the five public.knowledge_graph_* tables into the new `kg.*`
|
|
5
|
+
-- Postgres schema, drops the redundant `knowledge_graph_` prefix from table
|
|
6
|
+
-- and CHECK-constraint names, re-points the scope-guard trigger functions at
|
|
7
|
+
-- the new schema-qualified names, and creates compat views in public.* so
|
|
8
|
+
-- old bundled Lambda code keeps reading during the deploy bridge window.
|
|
9
|
+
--
|
|
10
|
+
-- Tables moved:
|
|
11
|
+
-- public.knowledge_graph_ingest_runs → kg.ingest_runs
|
|
12
|
+
-- public.knowledge_graph_entities → kg.entities
|
|
13
|
+
-- public.knowledge_graph_relationships → kg.relationships
|
|
14
|
+
-- public.knowledge_graph_evidence → kg.evidence
|
|
15
|
+
-- public.knowledge_graph_observation_cursors → kg.observation_cursors
|
|
16
|
+
--
|
|
17
|
+
-- Index names already use the `idx_kg_*` / `uq_kg_*` shorthand and are kept
|
|
18
|
+
-- verbatim; they move with their tables via SET SCHEMA. FK constraint names
|
|
19
|
+
-- and the `knowledge_graph_*_scope_guard` trigger names keep their original
|
|
20
|
+
-- prefixes — cosmetic cleanup deferred, same as the 0089/0090 precedent.
|
|
21
|
+
-- CHECK constraint names embed the table name in Drizzle's naming, so they
|
|
22
|
+
-- are renamed to the new stems to keep the Drizzle source and DB aligned.
|
|
23
|
+
--
|
|
24
|
+
-- The scope-guard trigger functions (0146/0147) query
|
|
25
|
+
-- public.knowledge_graph_* schema-qualified inside their plpgsql bodies.
|
|
26
|
+
-- Left alone they would resolve to the compat views (works during the
|
|
27
|
+
-- bridge) and break when the views drop, so this migration CREATE OR
|
|
28
|
+
-- REPLACEs the three functions that reference the moved tables with kg.*
|
|
29
|
+
-- qualified queries. enforce_knowledge_graph_ingest_run_scope references
|
|
30
|
+
-- only public.threads and is untouched.
|
|
31
|
+
--
|
|
32
|
+
-- Analyst surface: the semantic model deliberately includes public-schema
|
|
33
|
+
-- tables only (THINK-283), so the moved tables leave the analyst grants/RLS
|
|
34
|
+
-- surface, matching the wiki/ontology/brain extractions. Stale table-level
|
|
35
|
+
-- grants and analyst_tenant_isolation policies ride along harmlessly (the
|
|
36
|
+
-- app role owns the tables and bypasses RLS; analyst_reader has no USAGE on
|
|
37
|
+
-- kg).
|
|
38
|
+
--
|
|
39
|
+
-- Plan reference: docs/plans/2026-07-14-001-refactor-kg-schema-extraction-and-brain-cleanup-plan.md
|
|
40
|
+
-- Pattern doc: docs/solutions/database-issues/feature-schema-extraction-pattern.md
|
|
41
|
+
--
|
|
42
|
+
-- Apply manually (pause the observations-ingest schedule first — see the
|
|
43
|
+
-- writer runbook in the PR body):
|
|
44
|
+
-- psql "$DATABASE_URL" -f packages/database-pg/drizzle/0250_kg_schema_extraction.sql
|
|
45
|
+
-- Then verify:
|
|
46
|
+
-- bash scripts/db-migrate-manual.sh packages/database-pg/drizzle/0250_kg_schema_extraction.sql
|
|
47
|
+
-- psql -c "\dt kg.*" -- 5 tables expected
|
|
48
|
+
-- psql -c "\dv public.knowledge_graph_*" -- 5 compat views expected
|
|
49
|
+
-- psql -c "\dt public.knowledge_graph_*" -- 0 tables expected
|
|
50
|
+
--
|
|
51
|
+
-- Inverse runbook (rollback): drop the views, SET SCHEMA back, RENAME back,
|
|
52
|
+
-- restore the CHECK constraint names, and re-run the 0146/0147 function
|
|
53
|
+
-- bodies to restore the public.* qualification:
|
|
54
|
+
-- DROP VIEW IF EXISTS public.knowledge_graph_ingest_runs, ...; -- × 5
|
|
55
|
+
-- ALTER TABLE kg.evidence SET SCHEMA public;
|
|
56
|
+
-- ALTER TABLE public.evidence RENAME TO knowledge_graph_evidence;
|
|
57
|
+
-- ALTER TABLE public.knowledge_graph_evidence RENAME CONSTRAINT evidence_source_kind_allowed TO knowledge_graph_evidence_source_kind_allowed;
|
|
58
|
+
-- ... (× 5 tables, × 14 constraints, leaf-first)
|
|
59
|
+
-- -- re-apply 0146 + 0147 function definitions
|
|
60
|
+
-- DROP SCHEMA kg; -- last step; fails if any objects remain
|
|
61
|
+
--
|
|
62
|
+
-- Markers (consumed by scripts/db-migrate-manual.sh):
|
|
63
|
+
--
|
|
64
|
+
-- creates: kg.ingest_runs
|
|
65
|
+
-- creates: kg.entities
|
|
66
|
+
-- creates: kg.relationships
|
|
67
|
+
-- creates: kg.evidence
|
|
68
|
+
-- creates: kg.observation_cursors
|
|
69
|
+
-- creates-constraint: kg.ingest_runs.ingest_runs_status_allowed
|
|
70
|
+
-- creates-constraint: kg.ingest_runs.ingest_runs_trigger_allowed
|
|
71
|
+
-- creates-constraint: kg.ingest_runs.ingest_runs_source_kind_allowed
|
|
72
|
+
-- creates-constraint: kg.ingest_runs.ingest_runs_thread_scope_required
|
|
73
|
+
-- creates-constraint: kg.entities.entities_grounding_allowed
|
|
74
|
+
-- creates-constraint: kg.entities.entities_provenance_allowed
|
|
75
|
+
-- creates-constraint: kg.entities.entities_source_kind_allowed
|
|
76
|
+
-- creates-constraint: kg.entities.entities_resolution_state_allowed
|
|
77
|
+
-- creates-constraint: kg.relationships.relationships_grounding_allowed
|
|
78
|
+
-- creates-constraint: kg.relationships.relationships_provenance_allowed
|
|
79
|
+
-- creates-constraint: kg.relationships.relationships_source_kind_allowed
|
|
80
|
+
-- creates-constraint: kg.evidence.evidence_source_kind_allowed
|
|
81
|
+
-- creates-constraint: kg.evidence.evidence_evidence_source_kind_allowed
|
|
82
|
+
-- creates-constraint: kg.evidence.evidence_subject_required
|
|
83
|
+
-- creates: public.knowledge_graph_ingest_runs
|
|
84
|
+
-- creates: public.knowledge_graph_entities
|
|
85
|
+
-- creates: public.knowledge_graph_relationships
|
|
86
|
+
-- creates: public.knowledge_graph_evidence
|
|
87
|
+
-- creates: public.knowledge_graph_observation_cursors
|
|
88
|
+
|
|
89
|
+
\set ON_ERROR_STOP on
|
|
90
|
+
|
|
91
|
+
BEGIN;
|
|
92
|
+
|
|
93
|
+
-- Set timeouts BEFORE acquiring the advisory lock so the lock acquisition
|
|
94
|
+
-- itself is bounded.
|
|
95
|
+
SET LOCAL lock_timeout = '30s';
|
|
96
|
+
SET LOCAL statement_timeout = '300s';
|
|
97
|
+
|
|
98
|
+
-- Serialize concurrent application attempts.
|
|
99
|
+
SELECT pg_advisory_xact_lock(hashtext('kg_schema_extraction'));
|
|
100
|
+
|
|
101
|
+
-- Refuse to apply against an unexpected DB.
|
|
102
|
+
DO $$
|
|
103
|
+
BEGIN
|
|
104
|
+
IF current_database() != 'thinkwork' THEN
|
|
105
|
+
RAISE EXCEPTION 'wrong database: %, expected thinkwork', current_database();
|
|
106
|
+
END IF;
|
|
107
|
+
END $$;
|
|
108
|
+
|
|
109
|
+
-- Pre-flight invariants: for each table, assert old name exists AND new
|
|
110
|
+
-- name does not. Symmetric checks convert any partial-state scenario into a
|
|
111
|
+
-- clear pre-flight error. If the file was already applied (all five moved),
|
|
112
|
+
-- the customer runner's unattended re-sweep must be a no-op, so short-circuit
|
|
113
|
+
-- cleanly in that case.
|
|
114
|
+
DO $$
|
|
115
|
+
BEGIN
|
|
116
|
+
IF to_regclass('kg.ingest_runs') IS NOT NULL
|
|
117
|
+
AND to_regclass('kg.entities') IS NOT NULL
|
|
118
|
+
AND to_regclass('kg.relationships') IS NOT NULL
|
|
119
|
+
AND to_regclass('kg.evidence') IS NOT NULL
|
|
120
|
+
AND to_regclass('kg.observation_cursors') IS NOT NULL
|
|
121
|
+
AND to_regclass('public.knowledge_graph_ingest_runs') IS NOT NULL THEN
|
|
122
|
+
-- Already applied (views present at the old names). Nothing to do.
|
|
123
|
+
RETURN;
|
|
124
|
+
END IF;
|
|
125
|
+
|
|
126
|
+
IF to_regclass('public.knowledge_graph_ingest_runs') IS NULL THEN
|
|
127
|
+
RAISE EXCEPTION 'pre-flight: public.knowledge_graph_ingest_runs does not exist';
|
|
128
|
+
END IF;
|
|
129
|
+
IF to_regclass('kg.ingest_runs') IS NOT NULL THEN
|
|
130
|
+
RAISE EXCEPTION 'pre-flight: kg.ingest_runs already exists — refusing to re-apply';
|
|
131
|
+
END IF;
|
|
132
|
+
IF to_regclass('public.knowledge_graph_entities') IS NULL THEN
|
|
133
|
+
RAISE EXCEPTION 'pre-flight: public.knowledge_graph_entities does not exist';
|
|
134
|
+
END IF;
|
|
135
|
+
IF to_regclass('kg.entities') IS NOT NULL THEN
|
|
136
|
+
RAISE EXCEPTION 'pre-flight: kg.entities already exists — refusing to re-apply';
|
|
137
|
+
END IF;
|
|
138
|
+
IF to_regclass('public.knowledge_graph_relationships') IS NULL THEN
|
|
139
|
+
RAISE EXCEPTION 'pre-flight: public.knowledge_graph_relationships does not exist';
|
|
140
|
+
END IF;
|
|
141
|
+
IF to_regclass('kg.relationships') IS NOT NULL THEN
|
|
142
|
+
RAISE EXCEPTION 'pre-flight: kg.relationships already exists — refusing to re-apply';
|
|
143
|
+
END IF;
|
|
144
|
+
IF to_regclass('public.knowledge_graph_evidence') IS NULL THEN
|
|
145
|
+
RAISE EXCEPTION 'pre-flight: public.knowledge_graph_evidence does not exist';
|
|
146
|
+
END IF;
|
|
147
|
+
IF to_regclass('kg.evidence') IS NOT NULL THEN
|
|
148
|
+
RAISE EXCEPTION 'pre-flight: kg.evidence already exists — refusing to re-apply';
|
|
149
|
+
END IF;
|
|
150
|
+
IF to_regclass('public.knowledge_graph_observation_cursors') IS NULL THEN
|
|
151
|
+
RAISE EXCEPTION 'pre-flight: public.knowledge_graph_observation_cursors does not exist';
|
|
152
|
+
END IF;
|
|
153
|
+
IF to_regclass('kg.observation_cursors') IS NOT NULL THEN
|
|
154
|
+
RAISE EXCEPTION 'pre-flight: kg.observation_cursors already exists — refusing to re-apply';
|
|
155
|
+
END IF;
|
|
156
|
+
END $$;
|
|
157
|
+
|
|
158
|
+
-- Everything below is guarded so the whole file is idempotent for the
|
|
159
|
+
-- customer runner's unattended sweep: once applied, the pre-flight above
|
|
160
|
+
-- short-circuits nothing (DO blocks can't skip top-level DDL), so each DDL
|
|
161
|
+
-- statement carries its own existence guard.
|
|
162
|
+
|
|
163
|
+
-- Schema creation.
|
|
164
|
+
CREATE SCHEMA IF NOT EXISTS kg;
|
|
165
|
+
COMMENT ON SCHEMA kg IS 'Knowledge-graph mirror tables. Tenant-scoped entity/relationship/evidence snapshots and the ingest-run ledger. Extracted from public.knowledge_graph_* on 2026-07-14 (THINK-290).';
|
|
166
|
+
|
|
167
|
+
-- ── Move and rename tables ─────────────────────────────────────────────
|
|
168
|
+
-- FK-leaf-first ordering (evidence → relationships → entities →
|
|
169
|
+
-- observation_cursors → ingest_runs). Postgres preserves FKs across
|
|
170
|
+
-- SET SCHEMA automatically; ordering matters only for operator mental model.
|
|
171
|
+
|
|
172
|
+
DO $$
|
|
173
|
+
BEGIN
|
|
174
|
+
IF to_regclass('public.knowledge_graph_evidence') IS NOT NULL
|
|
175
|
+
AND to_regclass('kg.evidence') IS NULL THEN
|
|
176
|
+
ALTER TABLE public.knowledge_graph_evidence SET SCHEMA kg;
|
|
177
|
+
ALTER TABLE kg.knowledge_graph_evidence RENAME TO evidence;
|
|
178
|
+
END IF;
|
|
179
|
+
|
|
180
|
+
IF to_regclass('public.knowledge_graph_relationships') IS NOT NULL
|
|
181
|
+
AND to_regclass('kg.relationships') IS NULL THEN
|
|
182
|
+
ALTER TABLE public.knowledge_graph_relationships SET SCHEMA kg;
|
|
183
|
+
ALTER TABLE kg.knowledge_graph_relationships RENAME TO relationships;
|
|
184
|
+
END IF;
|
|
185
|
+
|
|
186
|
+
IF to_regclass('public.knowledge_graph_entities') IS NOT NULL
|
|
187
|
+
AND to_regclass('kg.entities') IS NULL THEN
|
|
188
|
+
ALTER TABLE public.knowledge_graph_entities SET SCHEMA kg;
|
|
189
|
+
ALTER TABLE kg.knowledge_graph_entities RENAME TO entities;
|
|
190
|
+
END IF;
|
|
191
|
+
|
|
192
|
+
IF to_regclass('public.knowledge_graph_observation_cursors') IS NOT NULL
|
|
193
|
+
AND to_regclass('kg.observation_cursors') IS NULL THEN
|
|
194
|
+
ALTER TABLE public.knowledge_graph_observation_cursors SET SCHEMA kg;
|
|
195
|
+
ALTER TABLE kg.knowledge_graph_observation_cursors RENAME TO observation_cursors;
|
|
196
|
+
END IF;
|
|
197
|
+
|
|
198
|
+
IF to_regclass('public.knowledge_graph_ingest_runs') IS NOT NULL
|
|
199
|
+
AND to_regclass('kg.ingest_runs') IS NULL THEN
|
|
200
|
+
ALTER TABLE public.knowledge_graph_ingest_runs SET SCHEMA kg;
|
|
201
|
+
ALTER TABLE kg.knowledge_graph_ingest_runs RENAME TO ingest_runs;
|
|
202
|
+
END IF;
|
|
203
|
+
END $$;
|
|
204
|
+
|
|
205
|
+
-- ── Rename CHECK constraints to drop the knowledge_graph_ prefix ────────
|
|
206
|
+
-- Drizzle's source names these after the (new) table stems; renaming keeps
|
|
207
|
+
-- the DB aligned with src/schema/knowledge-graph.ts.
|
|
208
|
+
|
|
209
|
+
DO $$
|
|
210
|
+
DECLARE
|
|
211
|
+
pair record;
|
|
212
|
+
BEGIN
|
|
213
|
+
FOR pair IN
|
|
214
|
+
SELECT * FROM (VALUES
|
|
215
|
+
('kg.ingest_runs', 'knowledge_graph_ingest_runs_status_allowed', 'ingest_runs_status_allowed'),
|
|
216
|
+
('kg.ingest_runs', 'knowledge_graph_ingest_runs_trigger_allowed', 'ingest_runs_trigger_allowed'),
|
|
217
|
+
('kg.ingest_runs', 'knowledge_graph_ingest_runs_source_kind_allowed', 'ingest_runs_source_kind_allowed'),
|
|
218
|
+
('kg.ingest_runs', 'knowledge_graph_ingest_runs_thread_scope_required', 'ingest_runs_thread_scope_required'),
|
|
219
|
+
('kg.entities', 'knowledge_graph_entities_grounding_allowed', 'entities_grounding_allowed'),
|
|
220
|
+
('kg.entities', 'knowledge_graph_entities_provenance_allowed', 'entities_provenance_allowed'),
|
|
221
|
+
('kg.entities', 'knowledge_graph_entities_source_kind_allowed', 'entities_source_kind_allowed'),
|
|
222
|
+
('kg.entities', 'knowledge_graph_entities_resolution_state_allowed', 'entities_resolution_state_allowed'),
|
|
223
|
+
('kg.relationships', 'knowledge_graph_relationships_grounding_allowed', 'relationships_grounding_allowed'),
|
|
224
|
+
('kg.relationships', 'knowledge_graph_relationships_provenance_allowed', 'relationships_provenance_allowed'),
|
|
225
|
+
('kg.relationships', 'knowledge_graph_relationships_source_kind_allowed', 'relationships_source_kind_allowed'),
|
|
226
|
+
('kg.evidence', 'knowledge_graph_evidence_source_kind_allowed', 'evidence_source_kind_allowed'),
|
|
227
|
+
('kg.evidence', 'knowledge_graph_evidence_evidence_source_kind_allowed', 'evidence_evidence_source_kind_allowed'),
|
|
228
|
+
('kg.evidence', 'knowledge_graph_evidence_subject_required', 'evidence_subject_required')
|
|
229
|
+
) AS v(tbl, old_name, new_name)
|
|
230
|
+
LOOP
|
|
231
|
+
IF EXISTS (
|
|
232
|
+
SELECT 1 FROM pg_constraint
|
|
233
|
+
WHERE conrelid = to_regclass(pair.tbl) AND conname = pair.old_name
|
|
234
|
+
) THEN
|
|
235
|
+
EXECUTE format('ALTER TABLE %s RENAME CONSTRAINT %I TO %I',
|
|
236
|
+
pair.tbl, pair.old_name, pair.new_name);
|
|
237
|
+
END IF;
|
|
238
|
+
END LOOP;
|
|
239
|
+
END $$;
|
|
240
|
+
|
|
241
|
+
-- ── Re-point scope-guard trigger functions at kg.* ─────────────────────
|
|
242
|
+
-- Bodies below are the 0146/0147 definitions with public.knowledge_graph_*
|
|
243
|
+
-- replaced by kg.* (and nothing else changed). CREATE OR REPLACE is
|
|
244
|
+
-- idempotent. Function and trigger names keep their original prefixes.
|
|
245
|
+
|
|
246
|
+
CREATE OR REPLACE FUNCTION public.enforce_knowledge_graph_entity_scope()
|
|
247
|
+
RETURNS trigger
|
|
248
|
+
LANGUAGE plpgsql
|
|
249
|
+
AS $$
|
|
250
|
+
DECLARE
|
|
251
|
+
run_tenant uuid;
|
|
252
|
+
run_thread uuid;
|
|
253
|
+
run_source_kind text;
|
|
254
|
+
run_source_ref text;
|
|
255
|
+
ontology_tenant uuid;
|
|
256
|
+
BEGIN
|
|
257
|
+
SELECT tenant_id, thread_id, source_kind, source_ref
|
|
258
|
+
INTO run_tenant, run_thread, run_source_kind, run_source_ref
|
|
259
|
+
FROM kg.ingest_runs
|
|
260
|
+
WHERE id = NEW.ingest_run_id;
|
|
261
|
+
|
|
262
|
+
IF run_tenant IS NOT NULL
|
|
263
|
+
AND (
|
|
264
|
+
run_tenant != NEW.tenant_id
|
|
265
|
+
OR run_thread IS DISTINCT FROM NEW.thread_id
|
|
266
|
+
OR run_source_kind != NEW.source_kind
|
|
267
|
+
OR run_source_ref != NEW.source_ref
|
|
268
|
+
) THEN
|
|
269
|
+
RAISE EXCEPTION 'knowledge graph entity run scope mismatch for run %', NEW.ingest_run_id;
|
|
270
|
+
END IF;
|
|
271
|
+
|
|
272
|
+
IF NEW.ontology_entity_type_id IS NOT NULL THEN
|
|
273
|
+
SELECT tenant_id INTO ontology_tenant
|
|
274
|
+
FROM ontology.entity_types
|
|
275
|
+
WHERE id = NEW.ontology_entity_type_id;
|
|
276
|
+
|
|
277
|
+
IF ontology_tenant IS NOT NULL AND ontology_tenant != NEW.tenant_id THEN
|
|
278
|
+
RAISE EXCEPTION 'knowledge graph entity ontology tenant mismatch for entity type %', NEW.ontology_entity_type_id;
|
|
279
|
+
END IF;
|
|
280
|
+
END IF;
|
|
281
|
+
|
|
282
|
+
RETURN NEW;
|
|
283
|
+
END;
|
|
284
|
+
$$;
|
|
285
|
+
|
|
286
|
+
CREATE OR REPLACE FUNCTION public.enforce_knowledge_graph_relationship_scope()
|
|
287
|
+
RETURNS trigger
|
|
288
|
+
LANGUAGE plpgsql
|
|
289
|
+
AS $$
|
|
290
|
+
DECLARE
|
|
291
|
+
run_tenant uuid;
|
|
292
|
+
run_thread uuid;
|
|
293
|
+
run_source_kind text;
|
|
294
|
+
run_source_ref text;
|
|
295
|
+
source_tenant uuid;
|
|
296
|
+
source_thread uuid;
|
|
297
|
+
source_run uuid;
|
|
298
|
+
source_entity_kind text;
|
|
299
|
+
source_entity_ref text;
|
|
300
|
+
target_tenant uuid;
|
|
301
|
+
target_thread uuid;
|
|
302
|
+
target_run uuid;
|
|
303
|
+
target_kind text;
|
|
304
|
+
target_ref text;
|
|
305
|
+
ontology_tenant uuid;
|
|
306
|
+
BEGIN
|
|
307
|
+
SELECT
|
|
308
|
+
r.tenant_id,
|
|
309
|
+
r.thread_id,
|
|
310
|
+
r.source_kind,
|
|
311
|
+
r.source_ref
|
|
312
|
+
INTO run_tenant, run_thread, run_source_kind, run_source_ref
|
|
313
|
+
FROM kg.ingest_runs AS r
|
|
314
|
+
WHERE r.id = NEW.ingest_run_id;
|
|
315
|
+
|
|
316
|
+
IF run_tenant IS NOT NULL
|
|
317
|
+
AND (
|
|
318
|
+
run_tenant != NEW.tenant_id
|
|
319
|
+
OR run_thread IS DISTINCT FROM NEW.thread_id
|
|
320
|
+
OR run_source_kind != NEW.source_kind
|
|
321
|
+
OR run_source_ref != NEW.source_ref
|
|
322
|
+
) THEN
|
|
323
|
+
RAISE EXCEPTION 'knowledge graph relationship run scope mismatch for run %', NEW.ingest_run_id;
|
|
324
|
+
END IF;
|
|
325
|
+
|
|
326
|
+
SELECT
|
|
327
|
+
e.tenant_id,
|
|
328
|
+
e.thread_id,
|
|
329
|
+
e.ingest_run_id,
|
|
330
|
+
e.source_kind,
|
|
331
|
+
e.source_ref
|
|
332
|
+
INTO source_tenant, source_thread, source_run, source_entity_kind, source_entity_ref
|
|
333
|
+
FROM kg.entities AS e
|
|
334
|
+
WHERE e.id = NEW.source_entity_id;
|
|
335
|
+
|
|
336
|
+
SELECT
|
|
337
|
+
e.tenant_id,
|
|
338
|
+
e.thread_id,
|
|
339
|
+
e.ingest_run_id,
|
|
340
|
+
e.source_kind,
|
|
341
|
+
e.source_ref
|
|
342
|
+
INTO target_tenant, target_thread, target_run, target_kind, target_ref
|
|
343
|
+
FROM kg.entities AS e
|
|
344
|
+
WHERE e.id = NEW.target_entity_id;
|
|
345
|
+
|
|
346
|
+
IF source_tenant IS NOT NULL
|
|
347
|
+
AND (
|
|
348
|
+
source_tenant != NEW.tenant_id
|
|
349
|
+
OR source_thread IS DISTINCT FROM NEW.thread_id
|
|
350
|
+
OR source_run != NEW.ingest_run_id
|
|
351
|
+
OR source_entity_kind != NEW.source_kind
|
|
352
|
+
OR source_entity_ref != NEW.source_ref
|
|
353
|
+
) THEN
|
|
354
|
+
RAISE EXCEPTION 'knowledge graph relationship source scope mismatch for entity %', NEW.source_entity_id;
|
|
355
|
+
END IF;
|
|
356
|
+
|
|
357
|
+
IF target_tenant IS NOT NULL
|
|
358
|
+
AND (
|
|
359
|
+
target_tenant != NEW.tenant_id
|
|
360
|
+
OR target_thread IS DISTINCT FROM NEW.thread_id
|
|
361
|
+
OR target_run != NEW.ingest_run_id
|
|
362
|
+
OR target_kind != NEW.source_kind
|
|
363
|
+
OR target_ref != NEW.source_ref
|
|
364
|
+
) THEN
|
|
365
|
+
RAISE EXCEPTION 'knowledge graph relationship target scope mismatch for entity %', NEW.target_entity_id;
|
|
366
|
+
END IF;
|
|
367
|
+
|
|
368
|
+
IF NEW.ontology_relationship_type_id IS NOT NULL THEN
|
|
369
|
+
SELECT rt.tenant_id INTO ontology_tenant
|
|
370
|
+
FROM ontology.relationship_types AS rt
|
|
371
|
+
WHERE rt.id = NEW.ontology_relationship_type_id;
|
|
372
|
+
|
|
373
|
+
IF ontology_tenant IS NOT NULL AND ontology_tenant != NEW.tenant_id THEN
|
|
374
|
+
RAISE EXCEPTION 'knowledge graph relationship ontology tenant mismatch for relationship type %', NEW.ontology_relationship_type_id;
|
|
375
|
+
END IF;
|
|
376
|
+
END IF;
|
|
377
|
+
|
|
378
|
+
RETURN NEW;
|
|
379
|
+
END;
|
|
380
|
+
$$;
|
|
381
|
+
|
|
382
|
+
CREATE OR REPLACE FUNCTION public.enforce_knowledge_graph_evidence_scope()
|
|
383
|
+
RETURNS trigger
|
|
384
|
+
LANGUAGE plpgsql
|
|
385
|
+
AS $$
|
|
386
|
+
DECLARE
|
|
387
|
+
run_tenant uuid;
|
|
388
|
+
run_thread uuid;
|
|
389
|
+
run_source_kind text;
|
|
390
|
+
run_source_ref text;
|
|
391
|
+
entity_tenant uuid;
|
|
392
|
+
entity_thread uuid;
|
|
393
|
+
entity_run uuid;
|
|
394
|
+
entity_kind text;
|
|
395
|
+
entity_ref text;
|
|
396
|
+
relationship_tenant uuid;
|
|
397
|
+
relationship_thread uuid;
|
|
398
|
+
relationship_run uuid;
|
|
399
|
+
relationship_kind text;
|
|
400
|
+
relationship_ref text;
|
|
401
|
+
message_tenant uuid;
|
|
402
|
+
message_thread uuid;
|
|
403
|
+
BEGIN
|
|
404
|
+
SELECT
|
|
405
|
+
r.tenant_id,
|
|
406
|
+
r.thread_id,
|
|
407
|
+
r.source_kind,
|
|
408
|
+
r.source_ref
|
|
409
|
+
INTO run_tenant, run_thread, run_source_kind, run_source_ref
|
|
410
|
+
FROM kg.ingest_runs AS r
|
|
411
|
+
WHERE r.id = NEW.ingest_run_id;
|
|
412
|
+
|
|
413
|
+
IF run_tenant IS NOT NULL
|
|
414
|
+
AND (
|
|
415
|
+
run_tenant != NEW.tenant_id
|
|
416
|
+
OR run_thread IS DISTINCT FROM NEW.thread_id
|
|
417
|
+
OR run_source_kind != NEW.source_kind
|
|
418
|
+
OR run_source_ref != NEW.source_ref
|
|
419
|
+
) THEN
|
|
420
|
+
RAISE EXCEPTION 'knowledge graph evidence run scope mismatch for run %', NEW.ingest_run_id;
|
|
421
|
+
END IF;
|
|
422
|
+
|
|
423
|
+
IF NEW.entity_id IS NOT NULL THEN
|
|
424
|
+
SELECT
|
|
425
|
+
e.tenant_id,
|
|
426
|
+
e.thread_id,
|
|
427
|
+
e.ingest_run_id,
|
|
428
|
+
e.source_kind,
|
|
429
|
+
e.source_ref
|
|
430
|
+
INTO entity_tenant, entity_thread, entity_run, entity_kind, entity_ref
|
|
431
|
+
FROM kg.entities AS e
|
|
432
|
+
WHERE e.id = NEW.entity_id;
|
|
433
|
+
|
|
434
|
+
IF entity_tenant IS NOT NULL
|
|
435
|
+
AND (
|
|
436
|
+
entity_tenant != NEW.tenant_id
|
|
437
|
+
OR entity_thread IS DISTINCT FROM NEW.thread_id
|
|
438
|
+
OR entity_run != NEW.ingest_run_id
|
|
439
|
+
OR entity_kind != NEW.source_kind
|
|
440
|
+
OR entity_ref != NEW.source_ref
|
|
441
|
+
) THEN
|
|
442
|
+
RAISE EXCEPTION 'knowledge graph evidence entity scope mismatch for entity %', NEW.entity_id;
|
|
443
|
+
END IF;
|
|
444
|
+
END IF;
|
|
445
|
+
|
|
446
|
+
IF NEW.relationship_id IS NOT NULL THEN
|
|
447
|
+
SELECT
|
|
448
|
+
r.tenant_id,
|
|
449
|
+
r.thread_id,
|
|
450
|
+
r.ingest_run_id,
|
|
451
|
+
r.source_kind,
|
|
452
|
+
r.source_ref
|
|
453
|
+
INTO relationship_tenant, relationship_thread, relationship_run, relationship_kind, relationship_ref
|
|
454
|
+
FROM kg.relationships AS r
|
|
455
|
+
WHERE r.id = NEW.relationship_id;
|
|
456
|
+
|
|
457
|
+
IF relationship_tenant IS NOT NULL
|
|
458
|
+
AND (
|
|
459
|
+
relationship_tenant != NEW.tenant_id
|
|
460
|
+
OR relationship_thread IS DISTINCT FROM NEW.thread_id
|
|
461
|
+
OR relationship_run != NEW.ingest_run_id
|
|
462
|
+
OR relationship_kind != NEW.source_kind
|
|
463
|
+
OR relationship_ref != NEW.source_ref
|
|
464
|
+
) THEN
|
|
465
|
+
RAISE EXCEPTION 'knowledge graph evidence relationship scope mismatch for relationship %', NEW.relationship_id;
|
|
466
|
+
END IF;
|
|
467
|
+
END IF;
|
|
468
|
+
|
|
469
|
+
IF NEW.message_id IS NOT NULL THEN
|
|
470
|
+
SELECT m.tenant_id, m.thread_id INTO message_tenant, message_thread
|
|
471
|
+
FROM public.messages AS m
|
|
472
|
+
WHERE m.id = NEW.message_id;
|
|
473
|
+
|
|
474
|
+
IF message_tenant IS NOT NULL
|
|
475
|
+
AND (
|
|
476
|
+
message_tenant != NEW.tenant_id
|
|
477
|
+
OR message_thread IS DISTINCT FROM NEW.thread_id
|
|
478
|
+
) THEN
|
|
479
|
+
RAISE EXCEPTION 'knowledge graph evidence message scope mismatch for message %', NEW.message_id;
|
|
480
|
+
END IF;
|
|
481
|
+
END IF;
|
|
482
|
+
|
|
483
|
+
RETURN NEW;
|
|
484
|
+
END;
|
|
485
|
+
$$;
|
|
486
|
+
|
|
487
|
+
-- ── Compat views in public.* ────────────────────────────────────────────
|
|
488
|
+
-- Old bundled Lambda code references public.knowledge_graph_*. Views are
|
|
489
|
+
-- column-enumerated per the plan's R6 (none of the five tables has a
|
|
490
|
+
-- generated column, so the enumeration is a stability guard, not a
|
|
491
|
+
-- workaround). Simple single-table views are auto-updatable, but the
|
|
492
|
+
-- ON CONFLICT writers are paused during the window regardless — views
|
|
493
|
+
-- reject ON CONFLICT at parse time. The U4 PR drops these.
|
|
494
|
+
|
|
495
|
+
DO $$
|
|
496
|
+
BEGIN
|
|
497
|
+
IF to_regclass('public.knowledge_graph_ingest_runs') IS NULL THEN
|
|
498
|
+
CREATE VIEW public.knowledge_graph_ingest_runs AS
|
|
499
|
+
SELECT id, tenant_id, thread_id, source_kind, source_ref, source_label,
|
|
500
|
+
requested_by_user_id, status, trigger, source_dataset_name,
|
|
501
|
+
source_dataset_id, started_at, finished_at, duration_ms, error,
|
|
502
|
+
entity_count, relationship_count, evidence_count,
|
|
503
|
+
diagnostic_count, message_count, input, metrics, metadata,
|
|
504
|
+
created_at, updated_at
|
|
505
|
+
FROM kg.ingest_runs;
|
|
506
|
+
END IF;
|
|
507
|
+
|
|
508
|
+
IF to_regclass('public.knowledge_graph_entities') IS NULL THEN
|
|
509
|
+
CREATE VIEW public.knowledge_graph_entities AS
|
|
510
|
+
SELECT id, tenant_id, thread_id, source_kind, source_ref,
|
|
511
|
+
ingest_run_id, graph_node_id, label, normalized_label,
|
|
512
|
+
type_label, ontology_entity_type_id, ontology_type_slug,
|
|
513
|
+
canonical_entity_id, resolution_state, grounding_status,
|
|
514
|
+
provenance_status, summary, aliases, properties, diagnostics,
|
|
515
|
+
relationship_count, evidence_count, last_seen_at, created_at,
|
|
516
|
+
updated_at
|
|
517
|
+
FROM kg.entities;
|
|
518
|
+
END IF;
|
|
519
|
+
|
|
520
|
+
IF to_regclass('public.knowledge_graph_relationships') IS NULL THEN
|
|
521
|
+
CREATE VIEW public.knowledge_graph_relationships AS
|
|
522
|
+
SELECT id, tenant_id, thread_id, source_kind, source_ref,
|
|
523
|
+
ingest_run_id, graph_edge_id, source_entity_id,
|
|
524
|
+
target_entity_id, label, ontology_relationship_type_id,
|
|
525
|
+
ontology_type_slug, grounding_status, provenance_status,
|
|
526
|
+
confidence, properties, diagnostics, evidence_count,
|
|
527
|
+
last_seen_at, created_at, updated_at
|
|
528
|
+
FROM kg.relationships;
|
|
529
|
+
END IF;
|
|
530
|
+
|
|
531
|
+
IF to_regclass('public.knowledge_graph_evidence') IS NULL THEN
|
|
532
|
+
CREATE VIEW public.knowledge_graph_evidence AS
|
|
533
|
+
SELECT id, tenant_id, thread_id, source_kind, source_ref,
|
|
534
|
+
ingest_run_id, entity_id, relationship_id, message_id,
|
|
535
|
+
message_role, message_created_at, speaker_label, snippet,
|
|
536
|
+
char_start, char_end, evidence_source_kind,
|
|
537
|
+
evidence_source_ref, metadata, observed_at, created_at
|
|
538
|
+
FROM kg.evidence;
|
|
539
|
+
END IF;
|
|
540
|
+
|
|
541
|
+
IF to_regclass('public.knowledge_graph_observation_cursors') IS NULL THEN
|
|
542
|
+
CREATE VIEW public.knowledge_graph_observation_cursors AS
|
|
543
|
+
SELECT tenant_id, bank_id, last_record_updated_at, last_record_id,
|
|
544
|
+
updated_at
|
|
545
|
+
FROM kg.observation_cursors;
|
|
546
|
+
END IF;
|
|
547
|
+
END $$;
|
|
548
|
+
|
|
549
|
+
COMMIT;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
-- THINK-291: promote json-render-ui (emit_json_render_ui generated UI) from a
|
|
2
|
+
-- hidden agent_capabilities row to a standard platform-tool opt-in column on
|
|
3
|
+
-- agents, matching sandbox/browser/web_search/web_extract/send_email/
|
|
4
|
+
-- context_engine. Default-on so charts and rich result chunks work out of the
|
|
5
|
+
-- box on greenfield stages (the legacy row was unseeded and invisible).
|
|
6
|
+
--
|
|
7
|
+
-- The runtime cutover in the same PR reads this column and retires the
|
|
8
|
+
-- agent_capabilities 'thread-json-render-ui' read; existing agents inherit
|
|
9
|
+
-- enabled-on via the UPDATE below unless a legacy row explicitly disabled the
|
|
10
|
+
-- capability.
|
|
11
|
+
--
|
|
12
|
+
-- creates-column: public.agents.json_render_ui
|
|
13
|
+
|
|
14
|
+
ALTER TABLE public.agents
|
|
15
|
+
ADD COLUMN IF NOT EXISTS json_render_ui jsonb DEFAULT '{"enabled": true}'::jsonb;
|
|
16
|
+
|
|
17
|
+
-- Legacy carry-over: an agent whose capability row was explicitly disabled
|
|
18
|
+
-- stays disabled (ADD COLUMN already filled every existing row with the
|
|
19
|
+
-- enabled default).
|
|
20
|
+
UPDATE public.agents a
|
|
21
|
+
SET json_render_ui = '{"enabled": false}'::jsonb
|
|
22
|
+
FROM public.agent_capabilities c
|
|
23
|
+
WHERE c.agent_id = a.id
|
|
24
|
+
AND c.capability = 'thread-json-render-ui'
|
|
25
|
+
AND c.enabled = false;
|