From 6c5a51f9ee348617f8b0cd7c6e5c3af2c3b0a9bc Mon Sep 17 00:00:00 2001 From: Adrian Webb Date: Sun, 11 Oct 2026 10:39:08 -0400 Subject: [PATCH 1/2] test: reproduce missing governed SDK graph ordering proof --- .../acceptance/golden-product-fixture.ts | 28 ++++++++++++++++++- .../operator-contracts/golden-product.test.ts | 13 ++++++++- 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/tests/unit/operator-contracts/acceptance/golden-product-fixture.ts b/tests/unit/operator-contracts/acceptance/golden-product-fixture.ts index 96cf8316..285f9d0f 100644 --- a/tests/unit/operator-contracts/acceptance/golden-product-fixture.ts +++ b/tests/unit/operator-contracts/acceptance/golden-product-fixture.ts @@ -2,6 +2,27 @@ import { createHash } from 'node:crypto'; import { parse, stringify } from 'yaml'; export const commit = 'a'.repeat(40); const libraryCommit = 'c'.repeat(40); +export const graphOrderFailures = ['missing-edges', 'malformed-edge', 'duplicate-edge', 'missing-pair', 'extra-pair', 'missing-profile', + 'transitive-profile', 'actor-profile', 'research-profile', 'work-item-profile', 'foreign-edge-team', 'edge-source-id', + 'edge-source-revision', 'edge-source-digest', 'edge-source-commit', 'edge-source-path', 'pair-endpoint', 'profile-foreign-node'] as const; +export function mutateGraphOrder(graph: { edges: Array> }, mode: string): void { + const pair = graph.edges[0]!, profile = graph.edges.find(edge => edge.provenance === 'profile-agent')!; + if (mode === 'missing-edges') Reflect.deleteProperty(graph, 'edges'); + else if (mode === 'malformed-edge') graph.edges[0] = {}; + else if (mode === 'duplicate-edge') graph.edges.push(structuredClone(pair)); + else if (mode === 'missing-pair') graph.edges.shift(); + else if (mode === 'extra-pair') graph.edges.push({ ...structuredClone(pair), id: 'extra-pair' }); + else if (mode === 'missing-profile') graph.edges.splice(graph.edges.indexOf(profile), 1); + else if (mode === 'transitive-profile') profile.toNodeId = 'actor-implement-change'; + else if (mode === 'actor-profile') profile.fromNodeId = 'actor-architecture-contract'; + else if (mode === 'research-profile') profile.fromNodeId = 'reviewer-research-context'; + else if (mode === 'work-item-profile') profile.provenance = 'work-item'; + else if (mode === 'foreign-edge-team') pair.teamId = 'foreign-team'; + else if (mode === 'pair-endpoint') pair.toNodeId = 'reviewer-architecture-contract'; + else if (mode === 'profile-foreign-node') profile.toNodeId = 'foreign-node'; + else if (mode.startsWith('edge-source-')) Reflect.set(pair.sourceRef as object, mode.slice(12), mode === 'edge-source-revision' ? 2 + : mode === 'edge-source-digest' ? `sha256:${'e'.repeat(64)}` : mode === 'edge-source-commit' ? 'd'.repeat(40) : 'foreign'); +} 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; @@ -82,7 +103,12 @@ export function proposalReadback(...input: [unknown?, number?, (boolean | 'alias 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: [] }; + const edge = (fromNodeId: string, toNodeId: string, provenance: string) => ({ schemaVersion: 'treeseed.execution-edge/v1', + id: `${fromNodeId}-${toNodeId}`, teamId: 'sdk-team', fromNodeId, toNodeId, provenance, sourceRef: structuredClone(sourceRef), graphRevisionCreated: 1 }); + const order = ['architecture-contract', 'tests-first', 'implement-change', 'document-change', 'simulate-release']; + const edges = [...proposal.executionPlan.workItems.map(item => edge(`actor-${item.id}`, `reviewer-${item.id}`, 'review-pair')), + ...order.slice(1).map((item, index) => edge(`reviewer-${order[index]}`, `actor-${item}`, 'profile-agent'))]; + 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, graph, binding: { repositoryId }, diff --git a/tests/unit/operator-contracts/golden-product.test.ts b/tests/unit/operator-contracts/golden-product.test.ts index f3983dab..b47de027 100644 --- a/tests/unit/operator-contracts/golden-product.test.ts +++ b/tests/unit/operator-contracts/golden-product.test.ts @@ -3,10 +3,21 @@ 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, graphPairFailures, mutateGraphPair } from './acceptance/golden-product-fixture.ts'; +import { commit, release, review, proposal, proposalReadback, graphPairFailures, mutateGraphPair, graphOrderFailures, mutateGraphOrder } from './acceptance/golden-product-fixture.ts'; const verifySdkGoldenProduct = (items: Parameters[0], source: string) => Reflect.apply(verifyProduct, undefined, [items, source, proposalReadback().governance, proposalReadback().original]); describe('SDK golden product gate (fixtures are not acceptance)', () => { + it('rejects counted graph pairs without independent research and exact immediate governed profile ordering', () => { + const observed = proposalReadback(); + const inspect = (value: typeof observed) => Reflect.apply(verifyProduct, undefined, [[release, review], commit, value.governance, value.original]); + expect(() => inspect(observed)).not.toThrow(); + for (const mode of graphOrderFailures) { + const changed = structuredClone(observed); mutateGraphOrder(changed.original.graph, mode); + const held = structuredClone(changed); + expect.soft(() => inspect(changed), mode).toThrow('ACCEPTANCE_SDK_GRAPH_ORDER'); expect(changed).toEqual(held); + } + expect(() => inspect(observed)).not.toThrow(); + }); 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]); From afa83d398c1419bdea87ea7a85d67934dc917a24 Mon Sep 17 00:00:00 2001 From: Adrian Webb Date: Sun, 11 Oct 2026 10:46:56 -0400 Subject: [PATCH 2/2] fix: verify independent research and immediate SDK graph order --- .../scenes/component-boundaries.scene.yaml | 3 +++ guarantees/verifiers/golden.verifiers.yaml | 5 ++++ tests/acceptance/golden-product.ts | 26 ++++++++++++++++++- .../acceptance/golden-product-fixture.ts | 5 +++- .../acceptance/golden-proposal-native.test.ts | 14 ++++++---- .../operator-contracts/golden-product.test.ts | 6 +++++ 6 files changed, 52 insertions(+), 7 deletions(-) diff --git a/guarantees/agent/golden/scenes/component-boundaries.scene.yaml b/guarantees/agent/golden/scenes/component-boundaries.scene.yaml index 960bf443..ee05de17 100644 --- a/guarantees/agent/golden/scenes/component-boundaries.scene.yaml +++ b/guarantees/agent/golden/scenes/component-boundaries.scene.yaml @@ -681,6 +681,9 @@ workflow: - id: authored-graph-pairs-unit action: { verifier: sdk.golden.authored-graph-pairs-unit } expect: { status: passed } + - id: standing-graph-order-unit + action: { verifier: sdk.golden.standing-graph-order-unit } + expect: { status: passed } - id: assignment-workday-native action: { verifier: sdk.golden.assignment-workday-native } expect: { status: passed } diff --git a/guarantees/verifiers/golden.verifiers.yaml b/guarantees/verifiers/golden.verifiers.yaml index 084519f4..ceaa0535 100644 --- a/guarantees/verifiers/golden.verifiers.yaml +++ b/guarantees/verifiers/golden.verifiers.yaml @@ -1,6 +1,11 @@ schemaVersion: treeseed.guarantee-verifiers/v1 ownerPackage: "@treeseed/sdk" verifiers: + sdk.golden.standing-graph-order-unit: + kind: vitestCase + ownerPackage: "@treeseed/sdk" + testFile: tests/unit/operator-contracts/golden-product.test.ts + testName: "rejects counted graph pairs without independent research and exact immediate governed profile ordering" sdk.golden.authored-graph-pairs-unit: kind: vitestCase ownerPackage: "@treeseed/sdk" diff --git a/tests/acceptance/golden-product.ts b/tests/acceptance/golden-product.ts index 35aed294..6c36b9f5 100644 --- a/tests/acceptance/golden-product.ts +++ b/tests/acceptance/golden-product.ts @@ -1,7 +1,7 @@ import assert from 'node:assert/strict'; import { closeSync, constants, fstatSync, lstatSync, openSync, readFileSync, realpathSync } from 'node:fs'; import { basename, isAbsolute, resolve } from 'node:path'; -import { exactEntityReferenceSchema } from '@treeseed/sdk/agent-capacity'; +import { exactEntityReferenceSchema, executionEdgeSchema } from '@treeseed/sdk/agent-capacity'; import { validatePortableContentData } from '@treeseed/sdk/content-validation'; import { createHash } from 'node:crypto'; import { parse, parseDocument, visit } from 'yaml'; @@ -131,6 +131,30 @@ function verifySdkGoldenGraph(proposal: Row, attempt: Row, graph: Row | undefine `${code}: Authored Actor or generated Reviewer authority drifted`); assert.deepEqual(node.sourceRef, attempt.sourceRef, `${code}: Pair must represent the exact original authored proposal`); } + const orderCode = 'ACCEPTANCE_SDK_GRAPH_ORDER'; + assert.ok(Array.isArray(graph.edges), `${orderCode}: Independent complete public edges required`); + const edges = graph.edges.map((edge: unknown) => { + const checked = executionEdgeSchema.safeParse(edge); + assert.ok(checked.success, `${orderCode}: Canonical original edge required`); return checked.data; + }); + assert.equal(new Set(edges.map(edge => edge.id)).size, edges.length, `${orderCode}: Duplicate edge identity`); + const ids = new Set(nodes.map(node => node.id)); + const scoped = edges.filter(edge => ids.has(edge.fromNodeId) || ids.has(edge.toNodeId)); + const nodeId = (item: string, role: string) => nodes.find(node => node.workItemId === item && node.pairRole === role)!.id; + const expectedPairs = items.map(item => [nodeId(item.id, 'actor'), nodeId(item.id, 'reviewer')]); + const engineering = ['architecture-contract', 'tests-first', 'implement-change', 'document-change', 'simulate-release']; + const expectedProfiles = engineering.slice(1).map((item, index) => [nodeId(engineering[index]!, 'reviewer'), nodeId(item, 'actor')]); + for (const [provenance, expected] of [['review-pair', expectedPairs], ['profile-agent', expectedProfiles]] as const) { + const actual = scoped.filter(edge => edge.provenance === provenance || (provenance === 'profile-agent' && edge.provenance === 'work-item')); + assert.equal(actual.length, expected.length, `${orderCode}: Exact pairs and immediate standing profile dependencies required`); + for (const [from, to] of expected) { + const matching = actual.filter(edge => edge.provenance === provenance && edge.fromNodeId === from && edge.toNodeId === to); + assert.equal(matching.length, 1, `${orderCode}: Independent research and immediate reviewed predecessor required`); + assert.equal(matching[0]!.teamId, attempt.teamId, `${orderCode}: Foreign edge owner`); + assert.equal(matching[0]!.graphRevisionRemoved, undefined, `${orderCode}: Removed edge cannot establish current order`); + assert.deepEqual(matching[0]!.sourceRef, attempt.sourceRef, `${orderCode}: Edge must retain exact authored source authority`); + } + } } export function verifySdkGoldenProduct(assignments: Row[], sourceBase: string, storedProposal: unknown, diff --git a/tests/unit/operator-contracts/acceptance/golden-product-fixture.ts b/tests/unit/operator-contracts/acceptance/golden-product-fixture.ts index 285f9d0f..f5fad226 100644 --- a/tests/unit/operator-contracts/acceptance/golden-product-fixture.ts +++ b/tests/unit/operator-contracts/acceptance/golden-product-fixture.ts @@ -4,7 +4,8 @@ export const commit = 'a'.repeat(40); const libraryCommit = 'c'.repeat(40); export const graphOrderFailures = ['missing-edges', 'malformed-edge', 'duplicate-edge', 'missing-pair', 'extra-pair', 'missing-profile', 'transitive-profile', 'actor-profile', 'research-profile', 'work-item-profile', 'foreign-edge-team', 'edge-source-id', - 'edge-source-revision', 'edge-source-digest', 'edge-source-commit', 'edge-source-path', 'pair-endpoint', 'profile-foreign-node'] as const; + 'edge-source-revision', 'edge-source-digest', 'edge-source-commit', 'edge-source-path', 'edge-source-repository', 'missing-edge-source', + 'removed-edge', 'pair-endpoint', 'profile-foreign-node'] as const; export function mutateGraphOrder(graph: { edges: Array> }, mode: string): void { const pair = graph.edges[0]!, profile = graph.edges.find(edge => edge.provenance === 'profile-agent')!; if (mode === 'missing-edges') Reflect.deleteProperty(graph, 'edges'); @@ -20,6 +21,8 @@ export function mutateGraphOrder(graph: { edges: Array> else if (mode === 'foreign-edge-team') pair.teamId = 'foreign-team'; else if (mode === 'pair-endpoint') pair.toNodeId = 'reviewer-architecture-contract'; else if (mode === 'profile-foreign-node') profile.toNodeId = 'foreign-node'; + else if (mode === 'missing-edge-source') Reflect.deleteProperty(pair, 'sourceRef'); + else if (mode === 'removed-edge') pair.graphRevisionRemoved = 2; else if (mode.startsWith('edge-source-')) Reflect.set(pair.sourceRef as object, mode.slice(12), mode === 'edge-source-revision' ? 2 : mode === 'edge-source-digest' ? `sha256:${'e'.repeat(64)}` : mode === 'edge-source-commit' ? 'd'.repeat(40) : 'foreign'); } diff --git a/tests/unit/operator-contracts/acceptance/golden-proposal-native.test.ts b/tests/unit/operator-contracts/acceptance/golden-proposal-native.test.ts index 0e129a30..57aeecbf 100644 --- a/tests/unit/operator-contracts/acceptance/golden-proposal-native.test.ts +++ b/tests/unit/operator-contracts/acceptance/golden-proposal-native.test.ts @@ -7,7 +7,7 @@ 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, graphPairFailures, mutateGraphPair } from './golden-product-fixture.ts'; +import { commit, release, review, proposal, proposalReadback, graphPairFailures, mutateGraphPair, graphOrderFailures, mutateGraphOrder } 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 () => { @@ -35,7 +35,11 @@ it('native public SDK proposal reads in isolated product verification reject cha 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)); + if (mode.startsWith('graph-')) { + const denial = mode.slice(6); + if ((graphOrderFailures as readonly string[]).includes(denial)) mutateGraphOrder(fixture.graph, denial); + else mutateGraphPair(fixture.graph, denial); + } response.end(JSON.stringify({ data: fixture.graph })); return; } if (['reference-open', 'reference-repository', 'reference-path'].includes(mode)) { @@ -253,13 +257,13 @@ Reflect.apply(verifySdkGoldenProduct,undefined,[actors,${JSON.stringify(commit)} 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']) { + for (const denial of [...graphPairFailures, ...graphOrderFailures, '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')); + expect(graphFailures).toEqual(retainedGraphFailures); expect(graphFailures).toHaveLength(graphPairFailures.length + graphOrderFailures.length + 4); + expect(graphCalls.slice(graphStart)).toEqual(Array(graphPairFailures.length + graphOrderFailures.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); diff --git a/tests/unit/operator-contracts/golden-product.test.ts b/tests/unit/operator-contracts/golden-product.test.ts index b47de027..3234c1ae 100644 --- a/tests/unit/operator-contracts/golden-product.test.ts +++ b/tests/unit/operator-contracts/golden-product.test.ts @@ -11,6 +11,12 @@ describe('SDK golden product gate (fixtures are not acceptance)', () => { 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 independent = structuredClone(observed), edge = independent.original.graph.edges[0]!; + independent.original.graph.edges.push({ ...edge, id: 'unrelated-edge', fromNodeId: 'other-actor', toNodeId: 'other-reviewer' }, + { ...edge, id: 'governance-edge', fromNodeId: 'accepted-condition', toNodeId: 'actor-research-context', provenance: 'governance' }, + { ...edge, id: 'event-edge', fromNodeId: 'question-condition', toNodeId: 'actor-research-context', provenance: 'profile-event' }); + const heldIndependent = structuredClone(independent); + expect(() => inspect(independent)).not.toThrow(); expect(independent).toEqual(heldIndependent); for (const mode of graphOrderFailures) { const changed = structuredClone(observed); mutateGraphOrder(changed.original.graph, mode); const held = structuredClone(changed);