feat(ql3): establish 3.0 incubation baseline

This commit is contained in:
whyour
2026-08-12 00:25:26 +08:00
parent 4bf92dcfeb
commit c699c32461
2817 changed files with 779642 additions and 653 deletions
@@ -0,0 +1,223 @@
const assert = require('node:assert/strict');
const { test } = require('node:test');
const {
InvalidPluginPackagePromptExecutionPlanError,
PLUGIN_PACKAGE_PROMPT_EXECUTION_PLAN_SCHEMA,
createPluginPackagePromptAdmissionBundle,
normalizePluginPackagePromptExecutionPlan,
pluginPackagePromptExecutionPlanDigest,
preparePluginPackagePromptExecution,
} = require('../dist/prompt/pluginPackagePromptExecution.js');
const {
pluginPackageAutomationPublicationDigest,
} = require('@qinglong/runtime-core/plugin-package-automation-publication');
function publication(overrides = {}) {
const unsigned = {
schema: 'qinglong/plugin-package-automation-publication@v1',
target: {
projectId: 'project-a',
packageName: 'package-a',
installationId: 'installation-a',
lockDigest: '1'.repeat(64),
generation: 3,
generationDigest: '2'.repeat(64),
materializedRevisionDigest: '3'.repeat(64),
},
state: 'active',
version: 1,
previousPublicationDigest: null,
lifecycleEventDigest: null,
definitions: {
workflows: [],
prompts: [
{
schema: 'qinglong/plugin-package-prompt-resource@v1',
id: 'summary',
name: 'Summary',
template: 'Summarize {{subject}} for {{audience}}.',
parameters: [
{ name: 'audience', required: false },
{ name: 'subject', required: true },
],
},
],
},
publishedAtMs: 1_000,
...overrides,
};
return {
...unsigned,
publicationDigest: pluginPackageAutomationPublicationDigest(unsigned),
};
}
function prepare(overrides = {}) {
const active = publication();
return preparePluginPackagePromptExecution({
publication: active,
expectedPublicationDigest: active.publicationDigest,
promptId: 'summary',
requestId: 'prompt-request-a',
traceId: 'trace-a',
requestedBySubject: { type: 'user', id: 'user-a' },
policyFence: { projectVersion: 1, bindingVersion: 1 },
parameters: { subject: 'QingLong 3.0' },
provider: 'openai-compatible',
model: 'model-a',
maxOutputTokens: 512,
temperature: 0.2,
plannedAtMs: 2_000,
deadlineAtMs: 62_000,
...overrides,
});
}
test('prepares a content-free immutable Prompt execution plan', () => {
const first = prepare();
const second = prepare();
assert.deepEqual(first, second);
assert.equal(first.plan.schema, PLUGIN_PACKAGE_PROMPT_EXECUTION_PLAN_SCHEMA);
assert.deepEqual(first.plan.output, { mode: 'live_only' });
assert.equal(
first.request.messages[0].content,
'Summarize QingLong 3.0 for .',
);
assert.match(first.plan.invocationId, /^ppi:[0-9a-f]{32}$/);
assert.match(first.plan.runId, /^ppr:[0-9a-f]{32}$/);
assert.match(first.plan.stepRunId, /^pps:[0-9a-f]{32}$/);
assert.match(first.plan.modelRequestDigest, /^sha256:[0-9a-f]{64}$/);
const durable = JSON.stringify(first.plan);
assert.equal(durable.includes('QingLong 3.0'), false);
assert.equal(durable.includes('Summarize '), false);
assert.equal(Object.isFrozen(first.plan), true);
});
test('binds explicit durable output retention and preserves legacy live-only replay', () => {
const durable = prepare({
output: {
mode: 'durable_artifact',
retentionPolicy: {
revision: 'edge-output-v1',
retentionMs: 86_400_000,
},
},
}).plan;
assert.equal(durable.output.mode, 'durable_artifact');
assert.match(durable.output.retentionPolicyDigest, /^[0-9a-f]{64}$/);
assert.notEqual(durable.planDigest, prepare().plan.planDigest);
assert.throws(
() =>
normalizePluginPackagePromptExecutionPlan({
...durable,
output: {
...durable.output,
retentionPolicyDigest: 'f'.repeat(64),
},
}),
InvalidPluginPackagePromptExecutionPlanError,
);
const current = prepare().plan;
const {
output: _output,
planDigest: _planDigest,
...legacyUnsigned
} = current;
const legacy = {
...legacyUnsigned,
planDigest: pluginPackagePromptExecutionPlanDigest(legacyUnsigned),
};
assert.equal(
normalizePluginPackagePromptExecutionPlan(legacy).output,
undefined,
);
});
test('binds parameter presence and content without recursively rendering values', () => {
const omitted = prepare();
const empty = prepare({
parameters: { subject: 'QingLong 3.0', audience: '' },
});
const literal = prepare({
parameters: { subject: '{{audience}}', audience: 'operators' },
});
assert.notEqual(omitted.plan.parameterDigest, empty.plan.parameterDigest);
assert.equal(
literal.request.messages[0].content,
'Summarize {{audience}} for operators.',
);
});
test('rejects stale publication, missing or widened parameters and unsafe budgets', () => {
const active = publication();
assert.throws(
() =>
preparePluginPackagePromptExecution({
...prepare().plan,
publication: active,
expectedPublicationDigest: 'f'.repeat(64),
promptId: 'summary',
requestId: 'request-b',
traceId: 'trace-b',
requestedBySubject: { type: 'user', id: 'user-b' },
policyFence: { projectVersion: 1, bindingVersion: 1 },
parameters: { subject: 'x' },
provider: 'provider-a',
model: 'model-a',
maxOutputTokens: 1,
plannedAtMs: 2_000,
deadlineAtMs: 3_000,
}),
InvalidPluginPackagePromptExecutionPlanError,
);
assert.throws(() => prepare({ parameters: {} }), /subject is required/);
assert.throws(
() => prepare({ parameters: { subject: 'x', extra: 'y' } }),
/undeclared name/,
);
assert.throws(
() => prepare({ deadlineAtMs: 2_000 + 5 * 60_000 + 1 }),
/deadline/,
);
assert.throws(() => prepare({ maxOutputTokens: 32_769 }), /maxOutputTokens/);
});
test('creates one model StepRun admission without persisting Prompt content', () => {
const prepared = prepare();
const bundle = createPluginPackagePromptAdmissionBundle(prepared.plan);
assert.equal(bundle.run.status, 'running');
assert.equal(bundle.run.version, 2);
assert.equal(bundle.run.eventSequence, 2);
assert.equal(bundle.run.triggerType, 'plugin_package_prompt');
assert.equal(bundle.stepMutation.stepRun.kind, 'model');
assert.equal(bundle.stepMutation.stepRun.status, 'ready');
assert.equal(bundle.stepMutation.expectedRunVersion, 1);
assert.equal(bundle.stepMutation.event.sequence, 2);
assert.equal(bundle.receipt.finalRunVersion, 2);
assert.equal(bundle.receipt.invocationId, prepared.plan.invocationId);
const durable = JSON.stringify(bundle);
assert.equal(durable.includes('QingLong 3.0'), false);
assert.equal(durable.includes('Summarize '), false);
});
test('normalizer rejects identity and digest drift', () => {
const plan = prepare().plan;
assert.throws(
() =>
normalizePluginPackagePromptExecutionPlan({
...plan,
runId: 'ppr:drift',
}),
InvalidPluginPackagePromptExecutionPlanError,
);
assert.throws(
() =>
normalizePluginPackagePromptExecutionPlan({
...plan,
parameterDigest: 'f'.repeat(64),
}),
InvalidPluginPackagePromptExecutionPlanError,
);
});