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,479 @@
const assert = require('node:assert/strict');
const { createHash } = require('node:crypto');
const { test } = require('node:test');
const {
PLUGIN_PACKAGE_API_VERSION,
PLUGIN_PACKAGE_KIND,
planPluginPackageInstall,
} = require('../../packages/ql3-runtime-core/dist/plugin-package/pluginPackage');
const {
createPluginPackageLock,
createPluginPackageInstall,
pluginPackageActivationIntentDigest,
pluginPackageInstallActionDigest,
pluginPackageInstallCommit,
pluginPackageInstallCreate,
pluginPackageInstallPlanDigest,
serializePluginPackageManifest,
transitionPluginPackageInstall,
} = require('../../packages/ql3-runtime-core/dist/plugin-package/installation/pluginPackageInstall');
const {
pluginPackageContentTreeDigest,
} = require('../../packages/ql3-runtime-core/dist/plugin-package/pluginPackageBundle');
const {
createPluginPackagePublisherProvenance,
} = require('../../packages/ql3-runtime-core/dist/plugin-package/publisher/pluginPackagePublisherProvenance');
const {
createPluginPackageResourceGenerationFromReferences,
} = require('../../packages/ql3-runtime-core/dist/plugin-package/pluginPackageResourceGeneration');
const {
materializePluginPackageResources,
} = require('../../packages/ql3-runtime-core/dist/plugin-package/pluginPackageResourceMaterialization');
const {
createBuiltInTaskSpecSemanticRegistry,
} = require('../../packages/ql3-runtime-core/dist/task-definition/taskSpecSemantic');
function environment(profile) {
return {
qinglongVersion: '3.0.0-alpha.0',
architecture: 'arm64',
deploymentProfile: profile,
runtimes: [],
availableMemoryBytes: 128 * 1024 * 1024,
availableDiskBytes: 256 * 1024 * 1024,
};
}
function taskValue(id, argument = id) {
const command =
typeof argument === 'string'
? {
kind: 'argv',
file: '/usr/bin/printf',
args: [argument],
}
: argument;
return {
schema: 'qinglong/plugin-package-task-resource@v1',
id,
name: `Task ${id}`,
labels: { 'plugin.qinglong.io/source': 'contract' },
enabled: true,
kind: 'command',
spec: {
schema: 'qinglong/command@v1',
config: {
command,
},
},
};
}
function activeRecord(lock, namespace, previousHead = null) {
const queued = createPluginPackageInstall(lock, {
installationId: `install-${namespace}-${lock.targetGeneration}`,
mutationId: `create-${namespace}-${lock.targetGeneration}`,
occurredAtMs: 1_000 + lock.targetGeneration * 10,
});
const staged = transitionPluginPackageInstall(lock, queued, {
type: 'stage_completed',
mutationId: `stage-${namespace}-${lock.targetGeneration}`,
occurredAtMs: queued.updatedAtMs + 1,
stageRef: `stage:${lock.lockDigest}`,
artifactDigest: lock.source.artifactDigest,
manifestDigest: lock.manifestDigest,
contentDigest: lock.source.contentDigest,
evidenceDigest: createHash('sha256')
.update(`evidence-${namespace}-${lock.targetGeneration}`)
.digest('hex'),
});
const activating = transitionPluginPackageInstall(lock, staged, {
type: 'activation_started',
mutationId: `activate-${namespace}-${lock.targetGeneration}`,
occurredAtMs: staged.updatedAtMs + 1,
});
const active = transitionPluginPackageInstall(lock, activating, {
type: 'activation_committed',
mutationId: `commit-${namespace}-${lock.targetGeneration}`,
occurredAtMs: activating.updatedAtMs + 1,
activationRef: `activation:${lock.lockDigest}`,
intentDigest: pluginPackageActivationIntentDigest(lock, activating),
generation: lock.targetGeneration,
contentDigest: lock.source.contentDigest,
});
return {
queued,
staged,
activating,
active,
create: pluginPackageInstallCreate(lock, queued, previousHead),
commits: [
pluginPackageInstallCommit(queued, staged),
pluginPackageInstallCommit(staged, activating),
pluginPackageInstallCommit(activating, active),
],
};
}
function fixture(namespace, options = {}) {
const profile = options.profile ?? 'edge';
const previous = options.previous ?? null;
const generation = previous ? previous.generation + 1 : 1;
const packageName = `package-${namespace}`;
const projectId = `project-${namespace}`;
const tasks = options.tasks ?? [
['alpha', 'alpha'],
['beta', 'beta'],
];
const workflows = options.workflows ?? [];
const prompts = options.prompts ?? [];
const tools = options.tools ?? [];
const taskResources = tasks.map(([id, argument]) => {
const path = `tasks/${id}.json`;
const bytes = Buffer.from(JSON.stringify(taskValue(id, argument)));
return {
reference: { kind: 'task', path },
bytes,
descriptor: {
path,
bytes: bytes.byteLength,
digest: createHash('sha256').update(bytes).digest('hex'),
},
};
});
const toolResources = tools.map((definition, index) => {
const path = `tools/tool-${index}.json`;
const bytes = Buffer.from(
JSON.stringify({
schema: 'qinglong/plugin-package-tool-resource@v1',
definition,
}),
);
return {
reference: { kind: 'tool', path },
bytes,
descriptor: {
path,
bytes: bytes.byteLength,
digest: createHash('sha256').update(bytes).digest('hex'),
},
};
});
const workflowResources = workflows.map((value) => {
const path = `workflows/${value.id}.json`;
const bytes = Buffer.from(JSON.stringify(value));
return {
reference: { kind: 'workflow', path },
bytes,
descriptor: {
path,
bytes: bytes.byteLength,
digest: createHash('sha256').update(bytes).digest('hex'),
},
};
});
const promptResources = prompts.map((value) => {
const path = `prompts/${value.id}.json`;
const bytes = Buffer.from(JSON.stringify(value));
return {
reference: { kind: 'prompt', path },
bytes,
descriptor: {
path,
bytes: bytes.byteLength,
digest: createHash('sha256').update(bytes).digest('hex'),
},
};
});
const resources = [
...taskResources,
...workflowResources,
...promptResources,
...toolResources,
].sort((left, right) =>
left.reference.path.localeCompare(right.reference.path),
);
const contentDigest = pluginPackageContentTreeDigest(
resources.map(({ descriptor }) => descriptor),
);
const manifest = {
apiVersion: PLUGIN_PACKAGE_API_VERSION,
kind: PLUGIN_PACKAGE_KIND,
metadata: {
name: packageName,
displayName: packageName,
version: `${generation}.0.0`,
description: 'Task reconciliation contract package',
license: 'Apache-2.0',
},
spec: {
compatibility: {
qinglong: '>=3.0.0-0 <4.0.0',
architectures: ['arm64'],
deploymentProfiles: [profile],
},
runtimes: [],
resources: {
memory: { recommended: '16Mi' },
disk: { install: '4Mi', working: '8Mi' },
},
permissions: {
network: { allowedHosts: [] },
secrets: [],
tools: [
...new Set([
'system.command',
...tools.flatMap(
({ requiredPermissions = [] }) => requiredPermissions,
),
]),
].sort(),
},
contents: {
tasks: taskResources.map(({ reference }) => reference.path),
workflows: workflowResources.map(({ reference }) => reference.path),
prompts: promptResources.map(({ reference }) => reference.path),
tools: toolResources.map(({ reference }) => reference.path),
},
},
};
const installEnvironment = environment(profile);
const plan = planPluginPackageInstall(
manifest,
installEnvironment,
previous?.manifest,
);
const action = {
lockId: `lock-${namespace}-${generation}`,
projectId,
manifest,
plan,
environment: installEnvironment,
...(previous ? { previousManifest: previous.manifest } : {}),
source: {
kind: 'offline',
locator: `offline:sha256:${createHash('sha256')
.update(`artifact-${namespace}-${generation}`)
.digest('hex')}`,
artifactDigest: createHash('sha256')
.update(`artifact-${namespace}-${generation}`)
.digest('hex'),
artifactBytes: 2048,
contentDigest,
},
architecture: 'arm64',
deploymentProfile: profile,
targetGeneration: generation,
...(previous ? { previousLockDigest: previous.lock.lockDigest } : {}),
};
const lock = createPluginPackageLock({
...action,
approval: {
requestId: `approval-${namespace}-${generation}`,
requestVersion: 1,
dispatchId: `dispatch-${namespace}-${generation}`,
actionDigest: pluginPackageInstallActionDigest(action),
previewDigest: pluginPackageInstallPlanDigest(plan),
approvedBy: { type: 'user', id: 'owner-001' },
approvedAtMs: 100,
expiresAtMs: 100_000,
fence: { projectVersion: 1, bindingVersion: 1 },
},
createdAtMs: 200 + generation,
});
const generationRecord = createPluginPackageResourceGenerationFromReferences({
installationId: `install-${namespace}-${generation}`,
projectId,
packageName,
lockDigest: lock.lockDigest,
generation,
previousActiveLockDigest: previous?.lock.lockDigest ?? null,
contentDigest,
resources: lock.resources,
});
const registry =
previous?.registry ?? createBuiltInTaskSpecSemanticRegistry();
const revision = materializePluginPackageResources({
generation: generationRecord,
lock,
manifestBytes: Buffer.from(serializePluginPackageManifest(manifest)),
resources: resources.map(({ reference, bytes }) => ({ reference, bytes })),
taskSpecSemanticRegistry: registry,
});
const install = activeRecord(
lock,
namespace,
previous?.install.active ?? null,
);
return {
namespace,
profile,
projectId,
packageName,
generation,
manifest,
lock,
revision,
registry,
install,
manifestBytes: Buffer.from(serializePluginPackageManifest(manifest)),
resourceEntries: resources.map(({ reference, bytes }) => ({
reference,
bytes,
})),
};
}
async function activateInstall(repository, value) {
await repository.create(value.install.create);
for (const command of value.install.commits) {
await repository.commit(command);
}
}
function publisherProvenanceInstallRepository(repository, provenance) {
return Object.freeze({
find: (...args) => repository.find(...args),
findLock: (...args) => repository.findLock(...args),
create: (...args) => repository.create(...args),
listRecoveryPage: (...args) => repository.listRecoveryPage(...args),
async commit(command) {
if (command.record.state !== 'staged') {
return repository.commit(command);
}
const lock = await repository.findLock(command.record.lockDigest);
assert.ok(lock);
assert.ok(command.record.stageReceipt);
return provenance.commitStage(
command,
createPluginPackagePublisherProvenance({
projectId: command.record.projectId,
packageName: command.record.packageName,
installationId: command.record.installationId,
lockDigest: command.record.lockDigest,
artifactDigest: command.record.stageReceipt.artifactDigest,
manifestDigest: command.record.stageReceipt.manifestDigest,
contentDigest: command.record.stageReceipt.contentDigest,
stageEvidenceDigest: command.record.stageReceipt.evidenceDigest,
signature: {
publisher: 'packages.contract.qinglong.dev',
keyId: 'contract-key-1',
signatureDigest: createHash('sha256')
.update(`signature:${command.record.installationId}`)
.digest('hex'),
keyNotBeforeMs: 0,
keyNotAfterMs: 100_000,
verifiedAtMs: command.record.updatedAtMs,
},
}),
'cluster',
);
},
});
}
function registerPluginPackageTaskReconciliationRepositoryContract(options) {
test(`${options.name} reconciles one complete generation and exact replay`, async (t) => {
const first = fixture(`${options.namespace}-create`, {
profile: options.profile,
});
const harness = await options.createRepository(t, first);
t.after(() => harness.close?.());
await activateInstall(harness.installRepository, first);
await harness.materializedRepository.publish(first.revision);
assert.deepEqual(await harness.repository.listPendingPage({ limit: 1 }), {
candidates: [
{ projectId: first.projectId, packageName: first.packageName },
],
truncated: false,
});
const source = {
async findActiveResourceGeneration() {
return first.revision.generation;
},
};
const created = await harness.repository.reconcile(first.revision, source);
assert.equal(created.status, 'created');
assert.deepEqual(
created.receipt.items.map(({ disposition }) => disposition),
['created', 'created'],
);
assert.equal(
(await harness.repository.reconcile(first.revision, source)).status,
'existing',
);
assert.deepEqual(
await harness.repository.find(first.revision.generation.generationDigest),
created.receipt,
);
assert.deepEqual(await harness.repository.listPendingPage({ limit: 1 }), {
candidates: [],
truncated: false,
});
await options.assertGenericWriteRejected?.(harness, first);
});
test(`${options.name} retains, disables and creates as one next generation`, async (t) => {
const first = fixture(`${options.namespace}-upgrade`, {
profile: options.profile,
});
const harness = await options.createRepository(t, first);
t.after(() => harness.close?.());
await activateInstall(harness.installRepository, first);
await harness.materializedRepository.publish(first.revision);
await harness.repository.reconcile(first.revision, {
async findActiveResourceGeneration() {
return first.revision.generation;
},
});
const second = fixture(first.namespace, {
profile: options.profile,
previous: first,
tasks: [
['alpha', 'alpha'],
['gamma', 'gamma'],
],
});
await activateInstall(harness.installRepository, second);
await harness.materializedRepository.publish(second.revision);
const reconciled = await harness.repository.reconcile(second.revision, {
async findActiveResourceGeneration() {
return second.revision.generation;
},
});
assert.deepEqual(
reconciled.receipt.items.map(({ taskId, revision, disposition }) => ({
taskId,
revision,
disposition,
})),
[
{
taskId: `pkg:${first.packageName}:alpha`,
revision: 1,
disposition: 'retained',
},
{
taskId: `pkg:${first.packageName}:beta`,
revision: 2,
disposition: 'disabled',
},
{
taskId: `pkg:${first.packageName}:gamma`,
revision: 1,
disposition: 'created',
},
],
);
await options.assertDurableUpgrade?.(harness, second);
});
}
module.exports = {
activateInstall,
pluginPackageTaskReconciliationFixture: fixture,
publisherProvenanceInstallRepository,
registerPluginPackageTaskReconciliationRepositoryContract,
};