WeKnora deployment source with the reviewed wiki identity, summary and recovery fixes
Anydoc / anydoc parser engine (push) Canceled after 0s
App / Format, vet, test, and build (push) Canceled after 0s
CLI / test (macos-latest / go 1.26) (push) Canceled after 0s
CLI / test (ubuntu-latest / go 1.26) (push) Canceled after 0s
CLI / test (windows-latest / go 1.26) (push) Canceled after 0s
Build and Push Docker Image / build-ui (push) Canceled after 0s
Build and Push Docker Image / build-docreader (push) Canceled after 0s
Build and Push Docker Image / build-sandbox (push) Canceled after 0s
Build and Push Docker Image / build-app (amd64, linux/amd64, ubuntu-latest) (push) Canceled after 0s
Build and Push Docker Image / build-app (arm64, linux/arm64, ubuntu-24.04-arm) (push) Canceled after 0s
DocReader / Python tests and Go client tests (push) Canceled after 0s
Build & Publish (dsh-weknora) / Typecheck, test, pack (push) Canceled after 0s
Build & Publish (dsh-weknora) / End-to-end inside dsh (pinned) (push) Canceled after 0s
Build & Publish (dsh-weknora) / End-to-end inside dsh (latest, advisory) (push) Canceled after 0s
Frontend / Test, type-check, and build (push) Canceled after 0s
Go Lint Cache / warm lint cache (.) (push) Canceled after 0s
Go Lint Cache / warm lint cache (cli) (push) Canceled after 0s
Go Lint Cache / warm lint cache (client) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.10) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.11) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.12) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.13) (push) Canceled after 0s
Build and Push Docker Image / merge (push) Canceled after 0s
Build & Publish (dsh-weknora) / Publish to npm (push) Canceled after 0s
Build & Publish (mcp-server) / Build sdist + wheel (push) Canceled after 0s
Build & Publish (mcp-server) / Publish to PyPI (push) Canceled after 0s
Anydoc / anydoc parser engine (push) Canceled after 0s
App / Format, vet, test, and build (push) Canceled after 0s
CLI / test (macos-latest / go 1.26) (push) Canceled after 0s
CLI / test (ubuntu-latest / go 1.26) (push) Canceled after 0s
CLI / test (windows-latest / go 1.26) (push) Canceled after 0s
Build and Push Docker Image / build-ui (push) Canceled after 0s
Build and Push Docker Image / build-docreader (push) Canceled after 0s
Build and Push Docker Image / build-sandbox (push) Canceled after 0s
Build and Push Docker Image / build-app (amd64, linux/amd64, ubuntu-latest) (push) Canceled after 0s
Build and Push Docker Image / build-app (arm64, linux/arm64, ubuntu-24.04-arm) (push) Canceled after 0s
DocReader / Python tests and Go client tests (push) Canceled after 0s
Build & Publish (dsh-weknora) / Typecheck, test, pack (push) Canceled after 0s
Build & Publish (dsh-weknora) / End-to-end inside dsh (pinned) (push) Canceled after 0s
Build & Publish (dsh-weknora) / End-to-end inside dsh (latest, advisory) (push) Canceled after 0s
Frontend / Test, type-check, and build (push) Canceled after 0s
Go Lint Cache / warm lint cache (.) (push) Canceled after 0s
Go Lint Cache / warm lint cache (cli) (push) Canceled after 0s
Go Lint Cache / warm lint cache (client) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.10) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.11) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.12) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.13) (push) Canceled after 0s
Build and Push Docker Image / merge (push) Canceled after 0s
Build & Publish (dsh-weknora) / Publish to npm (push) Canceled after 0s
Build & Publish (mcp-server) / Build sdist + wheel (push) Canceled after 0s
Build & Publish (mcp-server) / Publish to PyPI (push) Canceled after 0s
This commit is contained in:
@@ -0,0 +1,105 @@
|
||||
const fs = require('node:fs')
|
||||
const path = require('node:path')
|
||||
const crypto = require('node:crypto')
|
||||
const { execFileSync } = require('node:child_process')
|
||||
|
||||
const schema = `persona_migration_test_${crypto.randomBytes(6).toString('hex')}`
|
||||
const migration = fs.readFileSync(path.join(__dirname, '../migrations/versioned/000206_legacy_agent_persona.up.sql'), 'utf8')
|
||||
const checks = []
|
||||
function sql(query) {
|
||||
return execFileSync('docker', ['--context', 'colima-yawan', 'exec', '-i', 'WeKnora-postgres',
|
||||
'psql', '-X', '-U', 'postgres', '-d', 'yawan_native_acceptance_20260915', '-At', '-v', 'ON_ERROR_STOP=1'],
|
||||
{ input: `SET search_path TO ${schema}, public;\n${query}`, encoding: 'utf8', stdio: ['pipe', 'pipe', 'pipe'] }).trim()
|
||||
}
|
||||
function check(name, condition) {
|
||||
if (!condition) throw new Error(`Failed: ${name}`)
|
||||
checks.push(name)
|
||||
}
|
||||
function assertion(condition, message) {
|
||||
return `DO $$ BEGIN IF NOT (${condition}) THEN RAISE EXCEPTION '${message}'; END IF; END $$;`
|
||||
}
|
||||
const fixtureAgent = '5e807157-e1ae-4b6b-a770-e4d2b2d90001'
|
||||
const boundAgent = '5e807157-e1ae-4b6b-a770-e4d2b2d90002'
|
||||
const boundHuman = '5e807157-e1ae-4b6b-a770-e4d2b2d90003'
|
||||
const copyAgent = (id, sourceID) => `
|
||||
INSERT INTO custom_agents SELECT (jsonb_populate_record(NULL::custom_agents,
|
||||
to_jsonb(a) || jsonb_build_object('id','${id}','name','Existing native name','config',
|
||||
a.config || '{"system_prompt":"Existing edited task rules","custom_test_flag":true}'::jsonb))).*
|
||||
FROM custom_agents a WHERE id=(SELECT target_id FROM yawan_legacy_asset_mappings WHERE source_id=2);
|
||||
INSERT INTO yawan_legacy_asset_mappings SELECT (jsonb_populate_record(NULL::yawan_legacy_asset_mappings,
|
||||
to_jsonb(m) || jsonb_build_object('source_id',${sourceID},'target_id','${id}'))).*
|
||||
FROM yawan_legacy_asset_mappings m WHERE source_id=2;
|
||||
`
|
||||
try {
|
||||
sql(`CREATE SCHEMA ${schema};
|
||||
${['custom_agents', 'digital_humans', 'digital_human_versions', 'digital_human_bindings', 'digital_human_jobs',
|
||||
'workbench_access_publications', 'workbench_access_grants', 'yawan_legacy_asset_mappings'].map(table =>
|
||||
`CREATE TABLE ${schema}.${table} (LIKE public.${table} INCLUDING DEFAULTS INCLUDING CONSTRAINTS INCLUDING INDEXES);`).join('\n')}
|
||||
INSERT INTO yawan_legacy_asset_mappings SELECT * FROM public.yawan_legacy_asset_mappings
|
||||
WHERE source_system='yawan-workbench' AND source_organization_id=1 AND source_kind='agent' AND source_id=2;
|
||||
INSERT INTO custom_agents SELECT a.* FROM public.custom_agents a JOIN yawan_legacy_asset_mappings m
|
||||
ON a.id=m.target_id AND a.tenant_id=m.target_tenant_id;
|
||||
${copyAgent(fixtureAgent, 902)}
|
||||
${copyAgent(boundAgent, 903)}
|
||||
INSERT INTO workbench_access_publications VALUES (10059,'agents','${fixtureAgent}',false,now());
|
||||
INSERT INTO workbench_access_grants VALUES (10059,'agents','${fixtureAgent}','test-grantee',now());
|
||||
INSERT INTO digital_humans (id,tenant_id,owner_id,name,status,primary_agent_id)
|
||||
SELECT '${boundHuman}',tenant_id,created_by,'Existing human','draft',id FROM custom_agents WHERE id='${boundAgent}';
|
||||
INSERT INTO digital_human_bindings (id,tenant_id,owner_id,digital_human_id,agent_id)
|
||||
SELECT '5e807157-e1ae-4b6b-a770-e4d2b2d90004',tenant_id,created_by,'${boundHuman}',id
|
||||
FROM custom_agents WHERE id='${boundAgent}';`)
|
||||
sql(`BEGIN; ${migration} COMMIT;`)
|
||||
sql(assertion(`(SELECT count(*) FROM yawan_legacy_agent_persona_mappings)=2`, 'Expected only two unbound persona imports'))
|
||||
checks.push('imports_nonempty_unbound_persona_only')
|
||||
sql(assertion(`NOT EXISTS (SELECT 1 FROM yawan_legacy_agent_persona_mappings p
|
||||
JOIN digital_human_versions v ON v.id=p.version_id
|
||||
JOIN digital_humans h ON h.id=p.digital_human_id
|
||||
JOIN digital_human_bindings b ON b.id=p.binding_id
|
||||
JOIN custom_agents a ON a.id=p.agent_id AND a.tenant_id=p.tenant_id
|
||||
WHERE v.persona<>p.source_persona OR v.status<>'imported' OR v.reviewed_at IS NOT NULL
|
||||
OR v.review_note<>'' OR v.sources<>'[]'::jsonb OR h.active_version<>1 OR h.status<>'active'
|
||||
OR b.applied_version<>1 OR h.owner_id<>a.created_by OR h.name<>a.name OR h.primary_agent_id<>a.id)
|
||||
AND (SELECT count(*) FROM digital_human_jobs)=0`, 'Provenance and imported active semantics'))
|
||||
checks.push('all_fields_owner_name_binding_preserved_without_fake_review_or_job')
|
||||
sql(assertion(`(SELECT count(*) FROM custom_agents)=3 AND
|
||||
(SELECT config->>'custom_test_flag' FROM custom_agents WHERE id='${fixtureAgent}')='true' AND
|
||||
(SELECT config->>'system_prompt' FROM custom_agents WHERE id='${fixtureAgent}') LIKE 'Existing edited task rules%' AND
|
||||
NOT EXISTS (SELECT 1 FROM yawan_legacy_agent_persona_mappings p
|
||||
JOIN custom_agents a ON a.id=p.agent_id AND a.tenant_id=p.tenant_id,
|
||||
jsonb_each_text(p.source_persona) f WHERE strpos(a.config->>'system_prompt',f.value)=0)`, 'Existing Agent configuration and all style values'))
|
||||
checks.push('existing_agent_rules_and_all_style_values_in_runtime_prompt')
|
||||
sql(assertion(`(SELECT global FROM workbench_access_publications WHERE kind='digital-humans' AND resource_id=
|
||||
(SELECT digital_human_id FROM yawan_legacy_agent_persona_mappings WHERE source_id=2)) AND
|
||||
NOT (SELECT global FROM workbench_access_publications WHERE kind='digital-humans' AND resource_id=
|
||||
(SELECT digital_human_id FROM yawan_legacy_agent_persona_mappings WHERE source_id=902)) AND
|
||||
EXISTS (SELECT 1 FROM workbench_access_grants WHERE kind='digital-humans' AND user_id='test-grantee')`, 'Visibility and explicit grants'))
|
||||
checks.push('global_visibility_private_override_and_grants_preserved')
|
||||
sql(assertion(`(SELECT count(*) FROM digital_humans WHERE id='${boundHuman}')=1 AND
|
||||
(SELECT config->>'system_prompt' FROM custom_agents WHERE id='${boundAgent}')='Existing edited task rules'`, 'Existing digital human binding unchanged'))
|
||||
checks.push('preexisting_human_binding_unchanged')
|
||||
sql(`UPDATE digital_human_versions SET persona='{"tone":"native owner edit"}'
|
||||
WHERE id=(SELECT version_id FROM yawan_legacy_agent_persona_mappings WHERE source_id=902);
|
||||
UPDATE custom_agents SET config=jsonb_set(config,'{system_prompt}','"native prompt edit"') WHERE id='${fixtureAgent}';
|
||||
UPDATE workbench_access_publications SET global=true WHERE kind='digital-humans' AND resource_id=
|
||||
(SELECT digital_human_id FROM yawan_legacy_agent_persona_mappings WHERE source_id=902);
|
||||
DELETE FROM digital_human_bindings WHERE id=(SELECT binding_id FROM yawan_legacy_agent_persona_mappings WHERE source_id=902);
|
||||
BEGIN; ${migration} COMMIT;`)
|
||||
sql(assertion(`(SELECT count(*) FROM yawan_legacy_agent_persona_mappings)=2 AND
|
||||
(SELECT persona->>'tone' FROM digital_human_versions WHERE id=
|
||||
(SELECT version_id FROM yawan_legacy_agent_persona_mappings WHERE source_id=902))='native owner edit' AND
|
||||
(SELECT config->>'system_prompt' FROM custom_agents WHERE id='${fixtureAgent}')='native prompt edit' AND
|
||||
NOT EXISTS (SELECT 1 FROM digital_human_bindings WHERE agent_id='${fixtureAgent}')`, 'Rerun preserves owner edits and intentional unbinding'))
|
||||
checks.push('idempotency_preserves_later_native_edits_and_unbinding')
|
||||
const invalidAgent = '5e807157-e1ae-4b6b-a770-e4d2b2d90005'
|
||||
sql(copyAgent(invalidAgent, 904) + `UPDATE yawan_legacy_asset_mappings SET source_snapshot=
|
||||
jsonb_set(source_snapshot,'{persona_json}','{"unknown_rule":"must review"}') WHERE source_id=904;`)
|
||||
let rejected = false
|
||||
try { sql(`BEGIN; ${migration} COMMIT;`) } catch (error) {
|
||||
rejected = error.stderr?.toString().includes('requires explicit field review')
|
||||
}
|
||||
check('unknown_source_fields_rejected_atomically', rejected)
|
||||
sql(assertion(`(SELECT count(*) FROM yawan_legacy_agent_persona_mappings)=2`, 'Invalid source cannot partly import'))
|
||||
console.log(JSON.stringify({ ok: true, checks }, null, 2))
|
||||
} finally {
|
||||
sql(`DROP SCHEMA IF EXISTS ${schema} CASCADE;`)
|
||||
}
|
||||
Reference in New Issue
Block a user