Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -678,6 +678,9 @@ workflow:
- id: assignment-workday-unit
action: { verifier: sdk.golden.assignment-workday-unit }
expect: { status: passed }
- id: authored-graph-pairs-unit
action: { verifier: sdk.golden.authored-graph-pairs-unit }
expect: { status: passed }
- id: assignment-workday-native
action: { verifier: sdk.golden.assignment-workday-native }
expect: { status: passed }
5 changes: 5 additions & 0 deletions guarantees/verifiers/golden.verifiers.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
schemaVersion: treeseed.guarantee-verifiers/v1
ownerPackage: "@treeseed/sdk"
verifiers:
sdk.golden.authored-graph-pairs-unit:
kind: vitestCase
ownerPackage: "@treeseed/sdk"
testFile: tests/unit/operator-contracts/golden-product.test.ts
testName: "rejects six counted Actor Reviewer pairs that do not represent their exact authored proposal work"
sdk.golden.frozen-draft-unit:
kind: vitestCase
ownerPackage: "@treeseed/sdk"
Expand Down
2 changes: 2 additions & 0 deletions tests/acceptance/golden-product.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ test('SDK golden retains exact source and passing measured candidate release gat
assert.ok(result.page.nextCursor && result.page.nextCursor !== cursor && page < 39, 'ACCEPTANCE_SDK_PAGINATION: Incomplete assignment evidence');
cursor = result.page.nextCursor;
}
original.graph = read(['execution', 'graph', 'show']);
verifySdkGoldenProduct(assignments, sdkGoldenSource(freeze, run.parameters.proposalIds), proposal, original);
// Complete public list/show custody, not a time-cutoff approximation or a
// synthetic replacement for a managed Releaser and its independent Reviewer.
Expand All @@ -56,6 +57,7 @@ test('SDK golden retains exact source and passing measured candidate release gat
return value;
});
verifySdkGoldenProduct(full, sdkGoldenSource(freeze, run.parameters.proposalIds), proposal, original);
assert.deepEqual(read(['execution', 'graph', 'show']), original.graph, 'ACCEPTANCE_SDK_GRAPH_PAIRS: Public graph changed during independent read-back');
const final = (activity: string, workItemId = 'simulate-release') => full.filter(item => item.status === 'completed'
&& item.assignmentAttempt?.workItemId === workItemId && item.assignmentAttempt.effectiveProfile?.activity === activity)
.sort((a, b) => String(a.createdAt).localeCompare(String(b.createdAt))).at(-1);
Expand Down
25 changes: 24 additions & 1 deletion tests/acceptance/golden-product.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { createHash } from 'node:crypto';
import { parse, parseDocument, visit } from 'yaml';

type Row = Record<string, any>;
export type SdkGoldenOriginal = { binding: Row; files: Row; initialProposal: Row; teamLibrary?: Row; referenceFiles?: Row[] };
export type SdkGoldenOriginal = { binding: Row; files: Row; initialProposal: Row; teamLibrary?: Row; referenceFiles?: Row[]; graph?: Row };
/** The selected scene consumes the existing CLI library-read result. */
export function sdkGoldenLibraryFiles(readback: Row): Row {
const result = readback && typeof readback === 'object' && !Array.isArray(readback) ? readback.result : undefined;
Expand Down Expand Up @@ -111,6 +111,28 @@ function verifySdkGoldenAuthoredWork(proposal: Row, draft = false): void {
}
}

function verifySdkGoldenGraph(proposal: Row, attempt: Row, graph: Row | undefined): void {
const code = 'ACCEPTANCE_SDK_GRAPH_PAIRS';
assert.ok(graph && graph.teamId === attempt.teamId && Array.isArray(graph.nodes), `${code}: Independent public graph required`);
assert.ok(graph.nodes.every((node: unknown) => node && typeof node === 'object' && !Array.isArray(node)), `${code}: Malformed graph node`);
const nodes: Row[] = graph.nodes.filter((node: Row) => node.workdayId === attempt.workdayId && node.pairRole !== null);
const items: Row[] = proposal.executionPlan.workItems;
assert.equal(nodes.length, items.length * 2, `${code}: Exactly six authored Actors and six generated Reviewers required`);
assert.equal(new Set(nodes.map(node => node.id)).size, nodes.length, `${code}: Duplicate node identity`);
for (const item of items) for (const role of ['actor', 'reviewer']) {
const pair = nodes.filter(node => node.workItemId === item.id && node.pairRole === role);
assert.equal(pair.length, 1, `${code}: Each authored work item requires one exact ${role}`);
const node = pair[0]!;
assert.ok(typeof node.id === 'string' && node.id && node.teamId === attempt.teamId && node.projectId === proposal.projectId
&& node.kind === (role === 'actor' ? item.activity : 'reviewing')
&& node.agentClass === (role === 'actor' ? item.agentClass : 'reviewer')
&& node.workspace === (role === 'actor' ? item.workspace : 'treedx')
&& node.maximumReviewCycles === item.maximumReviewCycles && item.review === 'required',
`${code}: Authored Actor or generated Reviewer authority drifted`);
assert.deepEqual(node.sourceRef, attempt.sourceRef, `${code}: Pair must represent the exact original authored proposal`);
}
}

export function verifySdkGoldenProduct(assignments: Row[], sourceBase: string, storedProposal: unknown,
original?: SdkGoldenOriginal): void {
const actors = assignments.filter(item => item.status === 'completed'
Expand Down Expand Up @@ -155,6 +177,7 @@ export function verifySdkGoldenProduct(assignments: Row[], sourceBase: string, s
&& sourceRef.repository === provenance.repositoryId && sourceRef.commit === provenance.commitSha
&& sourceRef.path === provenance.contentPath,
'ACCEPTANCE_SDK_PROPOSAL: Read content differs from original issued proposal authority');
verifySdkGoldenGraph(proposal, release.assignmentAttempt, original.graph);
for (const item of actors.filter(item => ['research-context', 'architecture-contract', 'tests-first'].includes(item.assignmentAttempt.workItemId)))
assert.ok(item.assignmentAttempt.contextRefs?.some((ref: Row) => ref.store === 'git' && ref.commit === sourceBase),
'ACCEPTANCE_SDK_SOURCE: Early roles must receive exact frozen SDK source');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,21 @@ import { createHash } from 'node:crypto';
import { parse, stringify } from 'yaml';
export const commit = 'a'.repeat(40);
const libraryCommit = 'c'.repeat(40);
export const graphPairFailures = ['missing', 'foreign-team', 'duplicate-id', 'missing-node', 'extra-node', 'work-item',
'pair-role', 'kind', 'class', 'workspace', 'cycles', 'project', 'team', 'workday', 'source-id', 'source-revision',
'source-digest', 'source-commit', 'source-path', 'source-repository'] as const;
export function mutateGraphPair(graph: { teamId: string; nodes: Array<Record<string, unknown>> }, mode: string): void {
const node = graph.nodes[1]!;
if (mode === 'missing') Reflect.deleteProperty(graph, 'nodes');
else if (mode === 'foreign-team') graph.teamId = 'foreign';
else if (mode === 'duplicate-id') node.id = graph.nodes[0]!.id;
else if (mode === 'missing-node') graph.nodes.pop();
else if (mode === 'extra-node') graph.nodes.push({ ...node, id: 'extra-pair' });
else if (mode.startsWith('source-')) Reflect.set(node.sourceRef as object, mode.slice(7), mode === 'source-revision' ? 2 : mode === 'source-digest' ? `sha256:${'e'.repeat(64)}` : mode === 'source-commit' ? 'd'.repeat(40) : 'foreign');
else Reflect.set(node, ({ 'work-item': 'workItemId', 'pair-role': 'pairRole', class: 'agentClass', cycles: 'maximumReviewCycles',
project: 'projectId', team: 'teamId', workday: 'workdayId' } as Record<string, string>)[mode] ?? mode,
mode === 'cycles' ? 3 : mode === 'kind' ? 'acting' : mode === 'pair-role' ? 'actor' : mode === 'workspace' ? 'git' : 'foreign');
}
const referenced = [
{ schemaVersion: 'treeseed.objective/v1', id: 'sdk-objective', projectId: 'sdk-project', title: 'SDK objective', outcome: 'Portable intent', status: 'active' },
{ schemaVersion: 'treeseed.objective/v1', id: 'team-objective', projectId: 'team-project', title: 'Team objective', outcome: 'Governed execution', status: 'active' },
Expand Down Expand Up @@ -55,9 +70,22 @@ export function proposalReadback(...input: [unknown?, number?, (boolean | 'alias
const digest = createHash('sha256').update(content).digest('hex'), repositoryId = 'repo_sdk_fixture', commitSha = 'c'.repeat(40), contentPath = 'proposals/governance/sdk-proposal.mdx';
const initialProposal = structuredClone({ ...proposal, status: 'draft' });
for (const item of initialProposal.executionPlan.workItems) { Reflect.deleteProperty(item, 'estimate'); Reflect.deleteProperty(item, 'reviewEstimate'); }
// Controlled graph observations, not generated production evidence.
const sourceRef = { store: 'treedx', model: 'proposal', id: proposal.id, revision: 1, digest: `sha256:${digest}`,
repository: repositoryId, commit: commitSha, path: contentPath };
const nodes = proposal.executionPlan.workItems.flatMap(item => ['actor', 'reviewer'].map(pairRole => ({
schemaVersion: 'treeseed.execution-node/v1', ruleRevision: 1, nodeRevision: 1, status: 'completed',
graphRevisionCreated: 1, graphRevisionUpdated: 1,
id: `${pairRole}-${item.id}`, teamId: 'sdk-team', projectId: proposal.projectId, workdayId: 'workday-fixture',
workItemId: item.id, pairRole, kind: pairRole === 'actor' ? 'acting' : 'reviewing',
agentClass: pairRole === 'actor' ? item.agentClass : 'reviewer', workspace: pairRole === 'actor' ? item.workspace : 'treedx',
maximumReviewCycles: item.maximumReviewCycles, sourceRef: structuredClone(sourceRef),
estimate: structuredClone(pairRole === 'actor' ? item.estimate : item.reviewEstimate),
requiredCapabilities: ['source.read'], requestedPermissions: structuredClone(item.requestedPermissions) })));
const graph = { teamId: 'sdk-team', revision: 1, digest: `sha256:${'f'.repeat(64)}`, nodes, edges: [] };
return { governance: { id: fields.id, projectId: fields.projectId, title: fields.title, summary: fields.summary, body: fields.request,
activeVersion: 1, activeContentHash: digest, metadata: { contentProvenance: { repositoryId, commitSha, contentPath, digest } } },
original: { initialProposal, binding: { repositoryId },
original: { initialProposal, graph, binding: { repositoryId },
teamLibrary: { project: { id: 'team-project', slug: 'team', teamId: 'sdk-team' }, library: { projectId: 'team-project', teamId: 'sdk-team', repositoryId: 'repo_team_fixture' } },
referenceFiles: structuredClone(referenced.map(item => item.read)), files: { ok: true, repoId: repositoryId, resolvedRef: commitSha,
files: [{ path: contentPath, content, frontmatter: parse(encoded) as unknown }] } } };
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,12 @@ import { resolve } from 'node:path';
import { createHash } from 'node:crypto';
import { parse } from 'yaml';
import { expect, it } from 'vitest';
import { commit, release, review, proposal, proposalReadback } from './golden-product-fixture.ts';
import { commit, release, review, proposal, proposalReadback, graphPairFailures, mutateGraphPair } from './golden-product-fixture.ts';
import { workdayStartFixture } from './workday-start-fixture.ts';

it('native public SDK proposal reads in isolated product verification reject changed stored identity title and summary and retain denied observations before unchanged retry', async () => {
let mode = 'exact'; const calls: string[] = [], referenceCalls: string[] = [], failed: Array<Record<string, unknown>> = [];
const graphCalls: string[] = [], graphFailures: string[] = [];
const discussionBytes = (kind: string, bytes: string) => kind === 'reference-open' ? bytes.replace('status: closed', 'status: open')
: kind === 'reference-repository' ? bytes.replace('repository: repo_sdk_fixture', 'repository: repo_foreign')
: kind === 'reference-path' ? bytes.replace('path: proposals/governance/sdk-proposal.mdx', 'path: proposals/foreign.mdx') : bytes;
Expand All @@ -27,7 +28,16 @@ it('native public SDK proposal reads in isolated product verification reject cha
const fail = (error: Error) => { for (const item of pending.values()) { clearTimeout(item.timer); item.reject(error); } pending.clear(); };
const server = createServer((request, response) => {
let bytes = ''; request.setEncoding('utf8'); request.on('data', value => { bytes += String(value); }); request.on('end', () => {
const fixture = proposalReadback().original, path = request.method === 'POST' ? JSON.parse(bytes).paths?.[0] : undefined;
const fixture = proposalReadback(proposal, mode === 'budget-boundary' ? 1_048_576 : undefined).original, path = request.method === 'POST' ? JSON.parse(bytes).paths?.[0] : undefined;
if (request.url === '/v1/teams/sdk-team/execution-graph') {
graphCalls.push(`${request.method} ${request.url}`); response.setHeader('content-type', 'application/json');
if (mode.startsWith('graph-')) graphFailures.push(mode);
if (mode === 'graph-denied' || mode === 'graph-unavailable') { response.writeHead(mode === 'graph-denied' ? 403 : 503).end(JSON.stringify({ title: 'Controlled graph failure' })); return; }
if (mode === 'graph-interrupted') { request.socket.destroy(); return; }
if (mode === 'graph-json') { response.end('{'); return; }
if (mode.startsWith('graph-')) mutateGraphPair(fixture.graph, mode.slice(6));
response.end(JSON.stringify({ data: fixture.graph })); return;
}
if (['reference-open', 'reference-repository', 'reference-path'].includes(mode)) {
const discussion = fixture.referenceFiles[2]!.files[0]!;
discussion.content = discussionBytes(mode, discussion.content);
Expand Down Expand Up @@ -126,7 +136,8 @@ const teamBinding=await client.invoke(controlPlaneOperation('treedx.library.show
const referenceFiles=[];
for(const ref of [...(Array.isArray(document.objectiveRefs)?document.objectiveRefs:[]),...(document.discussionRef?[document.discussionRef]:[])]){
const result=await client.invoke(controlPlaneOperation('treedx.repositories.files.read'),{path:{projectId:ref.repository===teamBinding.data.repositoryId?'team-project':'sdk-project',repoId:ref.repository},query:{},body:{ref:ref.commit,paths:[ref.path],encoding:'utf8',parseFrontmatter:true}});referenceFiles.push(sdkGoldenLibraryFiles({result:result.data,receipt:{operation:'read'}}));}
Reflect.apply(verifySdkGoldenProduct,undefined,[actors,${JSON.stringify(commit)},observed.data,{...original,teamLibrary:{project:teamProject.data,library:teamBinding.data},referenceFiles}]);process.send({id,passed:true});
const graph=await client.invoke(controlPlaneOperation('execution.graph.show'),{path:{teamId:'sdk-team'},query:{},body:undefined});
Reflect.apply(verifySdkGoldenProduct,undefined,[actors,${JSON.stringify(commit)},observed.data,{...original,graph:graph.data,teamLibrary:{project:teamProject.data,library:teamBinding.data},referenceFiles}]);process.send({id,passed:true});
}catch(error){process.send({id,passed:false,error:error instanceof Error?error.message:'Native verification failed'});}});`;
worker = spawn(process.execPath, ['--import', 'tsx', '--input-type=module', '-e', code], {
cwd: new URL('../../../../', import.meta.url), stdio: ['ignore', 'ignore', 'pipe', 'ipc'], env: process.env,
Expand Down Expand Up @@ -240,6 +251,15 @@ Reflect.apply(verifySdkGoldenProduct,undefined,[actors,${JSON.stringify(commit)}
const preservedDrafts = structuredClone(deniedDrafts); writeFileSync(inputPath, inputBytes);
expect((await observe()).stdout).toBe('verified'); expect(deniedDrafts).toEqual(preservedDrafts);
expect(failed).toEqual(deniedReferences); expect(calls).toHaveLength(291);
const graphStart = graphCalls.length;
mode = 'exact'; expect((await Promise.all([observe(), observe()])).map(value => value.stdout)).toEqual(['verified', 'verified']);
for (const denial of [...graphPairFailures, 'denied', 'unavailable', 'interrupted', 'json']) {
mode = `graph-${denial}`; await expect.soft(observe(), mode).rejects.toThrow();
}
const retainedGraphFailures = structuredClone(graphFailures);
mode = 'exact'; expect((await observe()).stdout).toBe('verified');
expect(graphFailures).toEqual(retainedGraphFailures); expect(graphFailures).toHaveLength(graphPairFailures.length + 4);
expect(graphCalls.slice(graphStart)).toEqual(Array(graphPairFailures.length + 7).fill('GET /v1/teams/sdk-team/execution-graph'));
for (const file of proposalReadback().original.referenceFiles)
expect(referenceCalls.some(value => value.endsWith(` ${file.files[0]!.path}`))).toBe(true);
expect({ release, review, proposal }).toEqual(original);
Expand Down
23 changes: 22 additions & 1 deletion tests/unit/operator-contracts/golden-product.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,31 @@ import { readFileSync } from 'node:fs';
import { sdkGoldenSource, sdkGoldenLibraryFiles, verifySdkGoldenProposalReferences, verifySdkGoldenProduct as verifyProduct } from '../../acceptance/golden-product.ts';
import { stringify } from 'yaml';
import { createHash } from 'node:crypto';
import { commit, release, review, proposal, proposalReadback } from './acceptance/golden-product-fixture.ts';
import { commit, release, review, proposal, proposalReadback, graphPairFailures, mutateGraphPair } from './acceptance/golden-product-fixture.ts';
const verifySdkGoldenProduct = (items: Parameters<typeof verifyProduct>[0], source: string) =>
Reflect.apply(verifyProduct, undefined, [items, source, proposalReadback().governance, proposalReadback().original]);
describe('SDK golden product gate (fixtures are not acceptance)', () => {
it('rejects six counted Actor Reviewer pairs that do not represent their exact authored proposal work', () => {
const observed = proposalReadback();
const inspect = (value: typeof observed) => Reflect.apply(verifyProduct, undefined, [[release, review], commit, value.governance, value.original]);
expect(() => inspect(observed)).not.toThrow();
const unrelated = structuredClone(observed);
unrelated.original.graph.nodes.push({ ...structuredClone(unrelated.original.graph.nodes[0]!), id: 'unrelated-retained-actor', workdayId: 'another-workday' });
const retainedUnrelated = structuredClone(unrelated);
expect(() => inspect(unrelated)).not.toThrow(); expect(unrelated).toEqual(retainedUnrelated);
for (const mode of graphPairFailures) {
const changed = structuredClone(observed); mutateGraphPair(changed.original.graph, mode);
const retained = structuredClone(changed);
expect.soft(() => inspect(changed), mode).toThrow('ACCEPTANCE_SDK_GRAPH_PAIRS');
expect(changed).toEqual(retained);
}
const changed = structuredClone(observed);
changed.original.graph.nodes[1]!.workItemId = 'unrelated-authored-work';
const retained = structuredClone(changed);
expect(() => inspect(changed)).toThrow('ACCEPTANCE_SDK_GRAPH_PAIRS');
expect(changed).toEqual(retained);
expect(() => inspect(observed)).not.toThrow();
});
it('rejects a coherently rehashed closed discussion that names another proposal repository or path', () => {
for (const [field, value] of [['repository', 'repo_foreign'], ['path', 'proposals/foreign.mdx']]) {
const input = structuredClone(proposal), original = proposalReadback().original, file = original.referenceFiles[2]!.files[0]!;
Expand Down
Loading