修复角色动作元数据迁移与画布归一化
迁移按计划态分类排除同任务预览视频并区分零候选与多候选。 历史画布迁移忽略复制的来源链,正式生成继续保持严格血缘校验。 逐帧核验登记对象并补齐对象路径与对象 ID,支持前置 scope 的安全 dry-run。 补充迁移 HTTP 调用、撤权能力、回归测试和长期数据契约。
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
import { pathToFileURL } from 'node:url';
|
||||
|
||||
import {
|
||||
callSpacetimeProcedure,
|
||||
callSpacetimeProcedureViaCli,
|
||||
encodeSpacetimeCliOption,
|
||||
ensureProcedureOk,
|
||||
@@ -34,6 +35,8 @@ export function parseOptions(argv, env = process.env) {
|
||||
passthrough: [],
|
||||
server: env.GENARRATIVE_SPACETIME_SERVER || '',
|
||||
serverUrl: env.GENARRATIVE_SPACETIME_SERVER_URL || '',
|
||||
token: env.GENARRATIVE_SPACETIME_TOKEN || '',
|
||||
useHttp: false,
|
||||
};
|
||||
for (let index = 0; index < argv.length; index += 1) {
|
||||
const arg = argv[index];
|
||||
@@ -51,10 +54,14 @@ export function parseOptions(argv, env = process.env) {
|
||||
options.server = readValue();
|
||||
} else if (arg === '--server-url') {
|
||||
options.serverUrl = readValue();
|
||||
} else if (arg === '--token') {
|
||||
options.token = readValue();
|
||||
} else if (arg === '--chunk-size') {
|
||||
options.chunkSize = parsePositiveInteger(readValue(), arg);
|
||||
} else if (arg === '--apply') {
|
||||
options.apply = true;
|
||||
} else if (arg === '--use-http') {
|
||||
options.useHttp = true;
|
||||
} else if (arg === '--no-config' || arg === '--anonymous') {
|
||||
options.passthrough.push(arg);
|
||||
} else if (arg === '--help' || arg === '-h') {
|
||||
@@ -121,7 +128,9 @@ function assertSafeBatch(result, scope) {
|
||||
}
|
||||
|
||||
async function callBatch(options, input) {
|
||||
return callSpacetimeProcedureViaCli(options, PROCEDURE_NAME, input);
|
||||
return options.useHttp
|
||||
? callSpacetimeProcedure(options, PROCEDURE_NAME, input)
|
||||
: callSpacetimeProcedureViaCli(options, PROCEDURE_NAME, input);
|
||||
}
|
||||
|
||||
export async function scanScopes(
|
||||
@@ -198,6 +207,9 @@ export async function main(argv = process.argv.slice(2)) {
|
||||
if (!options.server && !options.serverUrl) {
|
||||
throw new Error('必须显式传入 --server / --server-url,不使用默认 cloud target。');
|
||||
}
|
||||
if (options.useHttp && !options.token) {
|
||||
throw new Error('--use-http 需要通过 --token 或 GENARRATIVE_SPACETIME_TOKEN 提供身份。');
|
||||
}
|
||||
|
||||
const migration = await scanScopes(options, { apply: options.apply });
|
||||
const verification = options.apply
|
||||
|
||||
@@ -21,6 +21,26 @@ describe('角色动作元数据规范化脚本', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('支持使用环境 token 的 HTTP 调用模式', () => {
|
||||
expect(
|
||||
parseOptions(
|
||||
[
|
||||
'--database',
|
||||
'genarrative-dev',
|
||||
'--server-url',
|
||||
'http://127.0.0.1:3101',
|
||||
'--use-http',
|
||||
],
|
||||
{ GENARRATIVE_SPACETIME_TOKEN: 'dev-migration-token' },
|
||||
),
|
||||
).toMatchObject({
|
||||
database: 'genarrative-dev',
|
||||
serverUrl: 'http://127.0.0.1:3101',
|
||||
token: 'dev-migration-token',
|
||||
useHttp: true,
|
||||
});
|
||||
});
|
||||
|
||||
it('编码 dry-run cursor 并禁止 canvas 超过五行', () => {
|
||||
expect(
|
||||
buildNormalizationInput({
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
import {
|
||||
callSpacetimeProcedure,
|
||||
callSpacetimeProcedureViaCli,
|
||||
ensureProcedureOk,
|
||||
parseArgs,
|
||||
@@ -15,11 +16,20 @@ try {
|
||||
const input = {
|
||||
operator_identity_hex: options.operatorIdentity,
|
||||
};
|
||||
const result = await callSpacetimeProcedureViaCli(
|
||||
options,
|
||||
'revoke_database_migration_operator',
|
||||
input,
|
||||
);
|
||||
if (options.useHttp && !options.token) {
|
||||
throw new Error('--use-http 需要同时传入 --token。');
|
||||
}
|
||||
const result = options.useHttp
|
||||
? await callSpacetimeProcedure(
|
||||
options,
|
||||
'revoke_database_migration_operator',
|
||||
input,
|
||||
)
|
||||
: await callSpacetimeProcedureViaCli(
|
||||
options,
|
||||
'revoke_database_migration_operator',
|
||||
input,
|
||||
);
|
||||
ensureProcedureOk(result);
|
||||
|
||||
console.log(
|
||||
|
||||
Reference in New Issue
Block a user